Merge "ConnectivityService: log wakelock activity in dumps"
diff --git a/Android.mk b/Android.mk
index a07fd01..92098eb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -128,8 +128,8 @@
core/java/android/bluetooth/IBluetoothInputHost.aidl \
core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl \
core/java/android/bluetooth/IBluetoothGatt.aidl \
- core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl \
- core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl \
+ core/java/android/bluetooth/IBluetoothGattCallback.aidl \
+ core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \
core/java/android/bluetooth/le/IAdvertiserCallback.aidl \
core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl \
core/java/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl \
@@ -210,6 +210,7 @@
core/java/android/net/IIpConnectivityMetrics.aidl \
core/java/android/net/IEthernetManager.aidl \
core/java/android/net/IEthernetServiceListener.aidl \
+ core/java/android/net/IIpSecService.aidl \
core/java/android/net/INetworkManagementEventObserver.aidl \
core/java/android/net/INetworkPolicyListener.aidl \
core/java/android/net/INetworkPolicyManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index ad4dc0b..3964221 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6694,8 +6694,8 @@
method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+ method public int getLeMaximumAdvertisingDataLength();
method public java.lang.String getName();
- method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7076,9 +7076,7 @@
public final class BluetoothDevice implements android.os.Parcelable {
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
- method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt);
- method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int);
- method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int, int);
+ method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
method public boolean createBond();
method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -7174,12 +7172,8 @@
field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
}
- public abstract deprecated class BluetoothGattCallback extends android.bluetooth.BluetoothGattCallbackExt {
+ public abstract class BluetoothGattCallback {
ctor public BluetoothGattCallback();
- }
-
- public abstract class BluetoothGattCallbackExt {
- ctor public BluetoothGattCallbackExt();
method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
@@ -7288,12 +7282,8 @@
method public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
}
- public abstract deprecated class BluetoothGattServerCallback extends android.bluetooth.BluetoothGattServerCallbackExt {
+ public abstract class BluetoothGattServerCallback {
ctor public BluetoothGattServerCallback();
- }
-
- public abstract class BluetoothGattServerCallbackExt {
- ctor public BluetoothGattServerCallbackExt();
method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
@@ -7505,11 +7495,11 @@
}
public final class AdvertisingSet {
- method public void enableAdvertising(boolean);
- method public void periodicAdvertisingEnable(boolean);
+ method public void enableAdvertising(boolean, int, int);
method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
+ method public void setPeriodicAdvertisingEnable(boolean);
method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
method public void setScanResponseData(android.bluetooth.le.AdvertiseData);
}
@@ -7518,11 +7508,11 @@
ctor public AdvertisingSetCallback();
method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
- method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
- method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int);
+ method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int);
+ method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int);
method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
- method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int);
+ method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
@@ -7538,12 +7528,12 @@
method public int getInterval();
method public int getPrimaryPhy();
method public int getSecondaryPhy();
- method public int getTimeout();
method public int getTxPowerLevel();
method public boolean includeTxPower();
method public boolean isAnonymous();
method public boolean isConnectable();
method public boolean isLegacy();
+ method public boolean isScannable();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
field public static final int INTERVAL_HIGH = 160; // 0xa0
@@ -7565,14 +7555,14 @@
public static final class AdvertisingSetParameters.Builder {
ctor public AdvertisingSetParameters.Builder();
method public android.bluetooth.le.AdvertisingSetParameters build();
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+ method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
+ method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
}
@@ -7581,6 +7571,8 @@
method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
}
@@ -7592,21 +7584,6 @@
method public void stopScan(android.bluetooth.le.ScanCallback);
}
- public abstract class PeriodicAdvertisingCallback {
- ctor public PeriodicAdvertisingCallback();
- method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
- method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
- method public void onSyncLost(int);
- field public static final int SYNC_NO_RESOURCES = 2; // 0x2
- field public static final int SYNC_NO_RESPONSE = 1; // 0x1
- }
-
- public final class PeriodicAdvertisingManager {
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
- method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
- }
-
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
method public int describeContents();
method public boolean getEnable();
@@ -7624,21 +7601,6 @@
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
}
- public final class PeriodicAdvertisingReport implements android.os.Parcelable {
- ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
- method public int describeContents();
- method public android.bluetooth.le.ScanRecord getData();
- method public int getDataStatus();
- method public int getRssi();
- method public int getSyncHandle();
- method public long getTimestampNanos();
- method public int getTxPower();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
- field public static final int DATA_COMPLETE = 0; // 0x0
- field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
- }
-
public abstract class ScanCallback {
ctor public ScanCallback();
method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
@@ -23822,8 +23784,8 @@
method public void reportNetworkConnectivity(android.net.Network, boolean);
method public boolean requestBandwidthUpdate(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
- method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
+ method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
method public deprecated boolean requestRouteToHost(int, int);
@@ -23933,7 +23895,7 @@
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
- method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+ method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
}
@@ -23967,7 +23929,6 @@
method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm);
method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm);
method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int);
- method public android.net.IpSecTransform.Builder setSpi(int, int);
method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex);
}
@@ -25015,7 +24976,7 @@
public class WifiManager {
method public int addNetwork(android.net.wifi.WifiConfiguration);
- method public boolean addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+ method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public static int calculateSignalLevel(int, int);
method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
method public static int compareSignalLevel(int, int);
@@ -25044,7 +25005,7 @@
method public boolean reassociate();
method public boolean reconnect();
method public boolean removeNetwork(int);
- method public boolean removePasspointConfiguration(java.lang.String);
+ method public void removePasspointConfiguration(java.lang.String);
method public deprecated boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -25059,26 +25020,22 @@
field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
field public static final int ERROR_AUTHENTICATING = 1; // 0x1
+ field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA";
field public static final java.lang.String EXTRA_BSSID = "bssid";
+ field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
+ field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
+ field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
+ field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
+ field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
field public static final java.lang.String EXTRA_NEW_STATE = "newState";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
- field public static final java.lang.String EXTRA_PASSPOINT_ICON_BSSID = "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_ICON_DATA = "android.net.wifi.extra.PASSPOINT_ICON_DATA";
- field public static final java.lang.String EXTRA_PASSPOINT_ICON_FILENAME = "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
- field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
- field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
- field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
+ field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+ field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL";
field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
@@ -25200,7 +25157,6 @@
ctor public PublishConfig.Builder();
method public android.net.wifi.aware.PublishConfig build();
method public android.net.wifi.aware.PublishConfig.Builder setMatchFilter(java.util.List<byte[]>);
- method public android.net.wifi.aware.PublishConfig.Builder setPublishCount(int);
method public android.net.wifi.aware.PublishConfig.Builder setPublishType(int);
method public android.net.wifi.aware.PublishConfig.Builder setServiceName(java.lang.String);
method public android.net.wifi.aware.PublishConfig.Builder setServiceSpecificInfo(byte[]);
@@ -25229,7 +25185,6 @@
method public android.net.wifi.aware.SubscribeConfig.Builder setMatchStyle(int);
method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(java.lang.String);
method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(byte[]);
- method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeCount(int);
method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int);
method public android.net.wifi.aware.SubscribeConfig.Builder setTerminateNotificationEnabled(boolean);
method public android.net.wifi.aware.SubscribeConfig.Builder setTtlSec(int);
@@ -25297,7 +25252,6 @@
method public void setUsageLimitStartTimeInMs(long);
method public void setUsageLimitTimeLimitInMinutes(long);
method public void setUsageLimitUsageTimePeriodInMinutes(long);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
}
@@ -25338,7 +25292,6 @@
method public void setRealm(java.lang.String);
method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
}
@@ -25351,7 +25304,6 @@
method public java.lang.String getCertType();
method public void setCertSha256Fingerprint(byte[]);
method public void setCertType(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
}
@@ -25364,7 +25316,6 @@
method public java.lang.String getImsi();
method public void setEapType(int);
method public void setImsi(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
}
@@ -25387,7 +25338,6 @@
method public void setPassword(java.lang.String);
method public void setSoftTokenApp(java.lang.String);
method public void setUsername(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
}
@@ -25412,7 +25362,6 @@
method public void setMatchAnyOis(long[]);
method public void setOtherHomePartners(java.lang.String[]);
method public void setRoamingConsortiumOis(long[]);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
}
@@ -25439,7 +25388,6 @@
method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
}
@@ -25456,7 +25404,6 @@
method public void setFqdn(java.lang.String);
method public void setFqdnExactMatch(boolean);
method public void setPriority(int);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
}
@@ -25481,7 +25428,6 @@
method public void setUpdateIntervalInMinutes(long);
method public void setUpdateMethod(java.lang.String);
method public void setUsername(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
@@ -37128,6 +37074,7 @@
field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
+ field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME = "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -37535,6 +37482,7 @@
field public static final java.lang.String EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME = "android.telecom.extra.CHANGE_DEFAULT_DIALER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_INCOMING_CALL_ADDRESS = "android.telecom.extra.INCOMING_CALL_ADDRESS";
field public static final java.lang.String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS";
+ field public static final java.lang.String EXTRA_INCOMING_VIDEO_STATE = "android.telecom.extra.INCOMING_VIDEO_STATE";
field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telecom.extra.NOTIFICATION_COUNT";
field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
@@ -37648,6 +37596,7 @@
field public static final java.lang.String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
field public static final java.lang.String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
field public static final java.lang.String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
+ field public static final java.lang.String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool";
field public static final java.lang.String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool";
field public static final java.lang.String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
@@ -38211,13 +38160,17 @@
method public boolean getDataEnabled();
method public int getDataNetworkType();
method public int getDataState();
- method public java.lang.String getDeviceId();
- method public java.lang.String getDeviceId(int);
+ method public deprecated java.lang.String getDeviceId();
+ method public deprecated java.lang.String getDeviceId(int);
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String[] getForbiddenPlmns();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getImei();
+ method public java.lang.String getImei(int);
method public java.lang.String getLine1Number();
+ method public java.lang.String getMeid();
+ method public java.lang.String getMeid(int);
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
@@ -53167,6 +53120,7 @@
public class GenericSignatureFormatError extends java.lang.ClassFormatError {
ctor public GenericSignatureFormatError();
+ ctor public GenericSignatureFormatError(java.lang.String);
}
public abstract interface InvocationHandler {
diff --git a/api/system-current.txt b/api/system-current.txt
index a89d3ca..9d4794d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -87,6 +87,7 @@
field public static final java.lang.String CLEAR_APP_CACHE = "android.permission.CLEAR_APP_CACHE";
field public static final java.lang.String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
field public static final java.lang.String CONNECTIVITY_INTERNAL = "android.permission.CONNECTIVITY_INTERNAL";
+ field public static final java.lang.String CONNECTIVITY_USE_RESTRICTED_NETWORKS = "android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS";
field public static final java.lang.String CONTROL_INCALL_EXPERIENCE = "android.permission.CONTROL_INCALL_EXPERIENCE";
field public static final java.lang.String CONTROL_LOCATION_UPDATES = "android.permission.CONTROL_LOCATION_UPDATES";
field public static final java.lang.String CONTROL_VPN = "android.permission.CONTROL_VPN";
@@ -6992,8 +6993,8 @@
method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+ method public int getLeMaximumAdvertisingDataLength();
method public java.lang.String getName();
- method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7378,9 +7379,7 @@
public final class BluetoothDevice implements android.os.Parcelable {
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
- method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt);
- method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int);
- method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int, int);
+ method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
method public boolean createBond();
method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -7478,12 +7477,8 @@
field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
}
- public abstract deprecated class BluetoothGattCallback extends android.bluetooth.BluetoothGattCallbackExt {
+ public abstract class BluetoothGattCallback {
ctor public BluetoothGattCallback();
- }
-
- public abstract class BluetoothGattCallbackExt {
- ctor public BluetoothGattCallbackExt();
method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
@@ -7592,12 +7587,8 @@
method public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
}
- public abstract deprecated class BluetoothGattServerCallback extends android.bluetooth.BluetoothGattServerCallbackExt {
+ public abstract class BluetoothGattServerCallback {
ctor public BluetoothGattServerCallback();
- }
-
- public abstract class BluetoothGattServerCallbackExt {
- ctor public BluetoothGattServerCallbackExt();
method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
@@ -7809,11 +7800,11 @@
}
public final class AdvertisingSet {
- method public void enableAdvertising(boolean);
- method public void periodicAdvertisingEnable(boolean);
+ method public void enableAdvertising(boolean, int, int);
method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
+ method public void setPeriodicAdvertisingEnable(boolean);
method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
method public void setScanResponseData(android.bluetooth.le.AdvertiseData);
}
@@ -7822,11 +7813,11 @@
ctor public AdvertisingSetCallback();
method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
- method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
- method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int);
+ method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int);
+ method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int);
method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
- method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int);
+ method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
@@ -7842,12 +7833,12 @@
method public int getInterval();
method public int getPrimaryPhy();
method public int getSecondaryPhy();
- method public int getTimeout();
method public int getTxPowerLevel();
method public boolean includeTxPower();
method public boolean isAnonymous();
method public boolean isConnectable();
method public boolean isLegacy();
+ method public boolean isScannable();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
field public static final int INTERVAL_HIGH = 160; // 0xa0
@@ -7869,14 +7860,14 @@
public static final class AdvertisingSetParameters.Builder {
ctor public AdvertisingSetParameters.Builder();
method public android.bluetooth.le.AdvertisingSetParameters build();
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+ method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
+ method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
}
@@ -7885,6 +7876,8 @@
method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
}
@@ -7899,21 +7892,6 @@
method public void stopScan(android.bluetooth.le.ScanCallback);
}
- public abstract class PeriodicAdvertisingCallback {
- ctor public PeriodicAdvertisingCallback();
- method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
- method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
- method public void onSyncLost(int);
- field public static final int SYNC_NO_RESOURCES = 2; // 0x2
- field public static final int SYNC_NO_RESPONSE = 1; // 0x1
- }
-
- public final class PeriodicAdvertisingManager {
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
- method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
- }
-
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
method public int describeContents();
method public boolean getEnable();
@@ -7931,21 +7909,6 @@
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
}
- public final class PeriodicAdvertisingReport implements android.os.Parcelable {
- ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
- method public int describeContents();
- method public android.bluetooth.le.ScanRecord getData();
- method public int getDataStatus();
- method public int getRssi();
- method public int getSyncHandle();
- method public long getTimestampNanos();
- method public int getTxPower();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
- field public static final int DATA_COMPLETE = 0; // 0x0
- field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
- }
-
public final class ResultStorageDescriptor implements android.os.Parcelable {
ctor public ResultStorageDescriptor(int, int, int);
method public int describeContents();
@@ -25609,8 +25572,8 @@
method public void reportNetworkConnectivity(android.net.Network, boolean);
method public boolean requestBandwidthUpdate(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
- method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
+ method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
method public deprecated boolean requestRouteToHost(int, int);
@@ -25766,13 +25729,11 @@
public final class IpSecManager {
method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
- method public void applyTunnelModeTransform(android.net.Network, android.net.IpSecTransform);
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
- method public void removeTunnelModeTransform(android.net.Network, android.net.IpSecTransform);
- method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+ method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
}
@@ -25803,12 +25764,10 @@
public static class IpSecTransform.Builder {
ctor public IpSecTransform.Builder(android.content.Context);
method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
- method public android.net.IpSecTransform buildTunnelModeTransform(java.net.InetAddress, java.net.InetAddress);
method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm);
method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm);
method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int);
method public android.net.IpSecTransform.Builder setNattKeepalive(int);
- method public android.net.IpSecTransform.Builder setSpi(int, int);
method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex);
method public android.net.IpSecTransform.Builder setUnderlyingNetwork(android.net.Network);
}
@@ -27393,7 +27352,7 @@
public class WifiManager {
method public int addNetwork(android.net.wifi.WifiConfiguration);
- method public boolean addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+ method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public static int calculateSignalLevel(int, int);
method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
method public static int compareSignalLevel(int, int);
@@ -27433,7 +27392,7 @@
method public boolean reassociate();
method public boolean reconnect();
method public boolean removeNetwork(int);
- method public boolean removePasspointConfiguration(java.lang.String);
+ method public void removePasspointConfiguration(java.lang.String);
method public deprecated boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -27456,29 +27415,25 @@
field public static final int CHANGE_REASON_REMOVED = 1; // 0x1
field public static final java.lang.String CONFIGURED_NETWORKS_CHANGED_ACTION = "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
field public static final int ERROR_AUTHENTICATING = 1; // 0x1
+ field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA";
field public static final java.lang.String EXTRA_BSSID = "bssid";
+ field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
field public static final java.lang.String EXTRA_CHANGE_REASON = "changeReason";
+ field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
+ field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
+ field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
+ field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
field public static final java.lang.String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
field public static final java.lang.String EXTRA_NEW_STATE = "newState";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
- field public static final java.lang.String EXTRA_PASSPOINT_ICON_BSSID = "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_ICON_DATA = "android.net.wifi.extra.PASSPOINT_ICON_DATA";
- field public static final java.lang.String EXTRA_PASSPOINT_ICON_FILENAME = "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
- field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
- field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
- field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
field public static final java.lang.String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
+ field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+ field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL";
field public static final java.lang.String EXTRA_WIFI_AP_STATE = "wifi_state";
field public static final java.lang.String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
@@ -27759,7 +27714,6 @@
ctor public PublishConfig.Builder();
method public android.net.wifi.aware.PublishConfig build();
method public android.net.wifi.aware.PublishConfig.Builder setMatchFilter(java.util.List<byte[]>);
- method public android.net.wifi.aware.PublishConfig.Builder setPublishCount(int);
method public android.net.wifi.aware.PublishConfig.Builder setPublishType(int);
method public android.net.wifi.aware.PublishConfig.Builder setServiceName(java.lang.String);
method public android.net.wifi.aware.PublishConfig.Builder setServiceSpecificInfo(byte[]);
@@ -27788,7 +27742,6 @@
method public android.net.wifi.aware.SubscribeConfig.Builder setMatchStyle(int);
method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(java.lang.String);
method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(byte[]);
- method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeCount(int);
method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int);
method public android.net.wifi.aware.SubscribeConfig.Builder setTerminateNotificationEnabled(boolean);
method public android.net.wifi.aware.SubscribeConfig.Builder setTtlSec(int);
@@ -27857,7 +27810,6 @@
method public void setUsageLimitStartTimeInMs(long);
method public void setUsageLimitTimeLimitInMinutes(long);
method public void setUsageLimitUsageTimePeriodInMinutes(long);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
}
@@ -27898,7 +27850,6 @@
method public void setRealm(java.lang.String);
method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
}
@@ -27911,7 +27862,6 @@
method public java.lang.String getCertType();
method public void setCertSha256Fingerprint(byte[]);
method public void setCertType(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
}
@@ -27924,7 +27874,6 @@
method public java.lang.String getImsi();
method public void setEapType(int);
method public void setImsi(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
}
@@ -27947,7 +27896,6 @@
method public void setPassword(java.lang.String);
method public void setSoftTokenApp(java.lang.String);
method public void setUsername(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
}
@@ -27972,7 +27920,6 @@
method public void setMatchAnyOis(long[]);
method public void setOtherHomePartners(java.lang.String[]);
method public void setRoamingConsortiumOis(long[]);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
}
@@ -27999,7 +27946,6 @@
method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
}
@@ -28016,7 +27962,6 @@
method public void setFqdn(java.lang.String);
method public void setFqdnExactMatch(boolean);
method public void setPriority(int);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
}
@@ -28041,7 +27986,6 @@
method public void setUpdateIntervalInMinutes(long);
method public void setUpdateMethod(java.lang.String);
method public void setUsername(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
@@ -40115,6 +40059,7 @@
field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
+ field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME = "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -40710,6 +40655,7 @@
field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
field public static final java.lang.String EXTRA_INCOMING_CALL_ADDRESS = "android.telecom.extra.INCOMING_CALL_ADDRESS";
field public static final java.lang.String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS";
+ field public static final java.lang.String EXTRA_INCOMING_VIDEO_STATE = "android.telecom.extra.INCOMING_VIDEO_STATE";
field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telecom.extra.NOTIFICATION_COUNT";
field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
@@ -40825,6 +40771,7 @@
field public static final java.lang.String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
field public static final java.lang.String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
field public static final java.lang.String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
+ field public static final java.lang.String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool";
field public static final java.lang.String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool";
field public static final java.lang.String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
@@ -41429,8 +41376,8 @@
method public boolean getDataEnabled(int);
method public int getDataNetworkType();
method public int getDataState();
- method public java.lang.String getDeviceId();
- method public java.lang.String getDeviceId(int);
+ method public deprecated java.lang.String getDeviceId();
+ method public deprecated java.lang.String getDeviceId(int);
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String[] getForbiddenPlmns();
method public java.lang.String getGroupIdLevel1();
@@ -41438,6 +41385,8 @@
method public java.lang.String getImei();
method public java.lang.String getImei(int);
method public java.lang.String getLine1Number();
+ method public java.lang.String getMeid();
+ method public java.lang.String getMeid(int);
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
@@ -56797,6 +56746,7 @@
public class GenericSignatureFormatError extends java.lang.ClassFormatError {
ctor public GenericSignatureFormatError();
+ ctor public GenericSignatureFormatError(java.lang.String);
}
public abstract interface InvocationHandler {
diff --git a/api/test-current.txt b/api/test-current.txt
index 43072bd..1c6a41b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6703,8 +6703,8 @@
method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+ method public int getLeMaximumAdvertisingDataLength();
method public java.lang.String getName();
- method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7085,9 +7085,7 @@
public final class BluetoothDevice implements android.os.Parcelable {
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
- method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt);
- method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int);
- method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int, int);
+ method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
method public boolean createBond();
method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -7183,12 +7181,8 @@
field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
}
- public abstract deprecated class BluetoothGattCallback extends android.bluetooth.BluetoothGattCallbackExt {
+ public abstract class BluetoothGattCallback {
ctor public BluetoothGattCallback();
- }
-
- public abstract class BluetoothGattCallbackExt {
- ctor public BluetoothGattCallbackExt();
method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
@@ -7297,12 +7291,8 @@
method public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
}
- public abstract deprecated class BluetoothGattServerCallback extends android.bluetooth.BluetoothGattServerCallbackExt {
+ public abstract class BluetoothGattServerCallback {
ctor public BluetoothGattServerCallback();
- }
-
- public abstract class BluetoothGattServerCallbackExt {
- ctor public BluetoothGattServerCallbackExt();
method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
@@ -7514,11 +7504,11 @@
}
public final class AdvertisingSet {
- method public void enableAdvertising(boolean);
- method public void periodicAdvertisingEnable(boolean);
+ method public void enableAdvertising(boolean, int, int);
method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
+ method public void setPeriodicAdvertisingEnable(boolean);
method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
method public void setScanResponseData(android.bluetooth.le.AdvertiseData);
}
@@ -7527,11 +7517,11 @@
ctor public AdvertisingSetCallback();
method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
- method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
- method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int);
+ method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int);
+ method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int);
method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
- method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int);
+ method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
@@ -7547,12 +7537,12 @@
method public int getInterval();
method public int getPrimaryPhy();
method public int getSecondaryPhy();
- method public int getTimeout();
method public int getTxPowerLevel();
method public boolean includeTxPower();
method public boolean isAnonymous();
method public boolean isConnectable();
method public boolean isLegacy();
+ method public boolean isScannable();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
field public static final int INTERVAL_HIGH = 160; // 0xa0
@@ -7574,14 +7564,14 @@
public static final class AdvertisingSetParameters.Builder {
ctor public AdvertisingSetParameters.Builder();
method public android.bluetooth.le.AdvertisingSetParameters build();
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+ method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
+ method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int);
method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
}
@@ -7590,6 +7580,8 @@
method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
}
@@ -7601,21 +7593,6 @@
method public void stopScan(android.bluetooth.le.ScanCallback);
}
- public abstract class PeriodicAdvertisingCallback {
- ctor public PeriodicAdvertisingCallback();
- method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
- method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
- method public void onSyncLost(int);
- field public static final int SYNC_NO_RESOURCES = 2; // 0x2
- field public static final int SYNC_NO_RESPONSE = 1; // 0x1
- }
-
- public final class PeriodicAdvertisingManager {
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
- method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
- }
-
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
method public int describeContents();
method public boolean getEnable();
@@ -7633,21 +7610,6 @@
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
}
- public final class PeriodicAdvertisingReport implements android.os.Parcelable {
- ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
- method public int describeContents();
- method public android.bluetooth.le.ScanRecord getData();
- method public int getDataStatus();
- method public int getRssi();
- method public int getSyncHandle();
- method public long getTimestampNanos();
- method public int getTxPower();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
- field public static final int DATA_COMPLETE = 0; // 0x0
- field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
- }
-
public abstract class ScanCallback {
ctor public ScanCallback();
method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
@@ -23895,8 +23857,8 @@
method public void reportNetworkConnectivity(android.net.Network, boolean);
method public boolean requestBandwidthUpdate(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
- method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
+ method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
method public deprecated boolean requestRouteToHost(int, int);
@@ -24006,7 +23968,7 @@
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
- method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+ method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
}
@@ -24040,7 +24002,6 @@
method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm);
method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm);
method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int);
- method public android.net.IpSecTransform.Builder setSpi(int, int);
method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex);
}
@@ -25088,7 +25049,7 @@
public class WifiManager {
method public int addNetwork(android.net.wifi.WifiConfiguration);
- method public boolean addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+ method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public static int calculateSignalLevel(int, int);
method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
method public static int compareSignalLevel(int, int);
@@ -25117,7 +25078,7 @@
method public boolean reassociate();
method public boolean reconnect();
method public boolean removeNetwork(int);
- method public boolean removePasspointConfiguration(java.lang.String);
+ method public void removePasspointConfiguration(java.lang.String);
method public deprecated boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -25132,26 +25093,22 @@
field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
field public static final int ERROR_AUTHENTICATING = 1; // 0x1
+ field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA";
field public static final java.lang.String EXTRA_BSSID = "bssid";
+ field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
+ field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
+ field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
+ field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
+ field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
field public static final java.lang.String EXTRA_NEW_STATE = "newState";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
- field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
- field public static final java.lang.String EXTRA_PASSPOINT_ICON_BSSID = "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_ICON_DATA = "android.net.wifi.extra.PASSPOINT_ICON_DATA";
- field public static final java.lang.String EXTRA_PASSPOINT_ICON_FILENAME = "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
- field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
- field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
- field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
- field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
+ field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+ field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL";
field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
@@ -25273,7 +25230,6 @@
ctor public PublishConfig.Builder();
method public android.net.wifi.aware.PublishConfig build();
method public android.net.wifi.aware.PublishConfig.Builder setMatchFilter(java.util.List<byte[]>);
- method public android.net.wifi.aware.PublishConfig.Builder setPublishCount(int);
method public android.net.wifi.aware.PublishConfig.Builder setPublishType(int);
method public android.net.wifi.aware.PublishConfig.Builder setServiceName(java.lang.String);
method public android.net.wifi.aware.PublishConfig.Builder setServiceSpecificInfo(byte[]);
@@ -25302,7 +25258,6 @@
method public android.net.wifi.aware.SubscribeConfig.Builder setMatchStyle(int);
method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(java.lang.String);
method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(byte[]);
- method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeCount(int);
method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int);
method public android.net.wifi.aware.SubscribeConfig.Builder setTerminateNotificationEnabled(boolean);
method public android.net.wifi.aware.SubscribeConfig.Builder setTtlSec(int);
@@ -25370,7 +25325,6 @@
method public void setUsageLimitStartTimeInMs(long);
method public void setUsageLimitTimeLimitInMinutes(long);
method public void setUsageLimitUsageTimePeriodInMinutes(long);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
}
@@ -25411,7 +25365,6 @@
method public void setRealm(java.lang.String);
method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
}
@@ -25424,7 +25377,6 @@
method public java.lang.String getCertType();
method public void setCertSha256Fingerprint(byte[]);
method public void setCertType(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
}
@@ -25437,7 +25389,6 @@
method public java.lang.String getImsi();
method public void setEapType(int);
method public void setImsi(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
}
@@ -25460,7 +25411,6 @@
method public void setPassword(java.lang.String);
method public void setSoftTokenApp(java.lang.String);
method public void setUsername(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
}
@@ -25485,7 +25435,6 @@
method public void setMatchAnyOis(long[]);
method public void setOtherHomePartners(java.lang.String[]);
method public void setRoamingConsortiumOis(long[]);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
}
@@ -25512,7 +25461,6 @@
method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
}
@@ -25529,7 +25477,6 @@
method public void setFqdn(java.lang.String);
method public void setFqdnExactMatch(boolean);
method public void setPriority(int);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
}
@@ -25554,7 +25501,6 @@
method public void setUpdateIntervalInMinutes(long);
method public void setUpdateMethod(java.lang.String);
method public void setUsername(java.lang.String);
- method public boolean validate();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
@@ -37210,6 +37156,7 @@
field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
+ field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME = "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -37617,6 +37564,7 @@
field public static final java.lang.String EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME = "android.telecom.extra.CHANGE_DEFAULT_DIALER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_INCOMING_CALL_ADDRESS = "android.telecom.extra.INCOMING_CALL_ADDRESS";
field public static final java.lang.String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS";
+ field public static final java.lang.String EXTRA_INCOMING_VIDEO_STATE = "android.telecom.extra.INCOMING_VIDEO_STATE";
field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telecom.extra.NOTIFICATION_COUNT";
field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
@@ -37730,6 +37678,7 @@
field public static final java.lang.String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
field public static final java.lang.String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
field public static final java.lang.String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
+ field public static final java.lang.String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool";
field public static final java.lang.String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool";
field public static final java.lang.String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
@@ -38293,13 +38242,17 @@
method public boolean getDataEnabled();
method public int getDataNetworkType();
method public int getDataState();
- method public java.lang.String getDeviceId();
- method public java.lang.String getDeviceId(int);
+ method public deprecated java.lang.String getDeviceId();
+ method public deprecated java.lang.String getDeviceId(int);
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String[] getForbiddenPlmns();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getImei();
+ method public java.lang.String getImei(int);
method public java.lang.String getLine1Number();
+ method public java.lang.String getMeid();
+ method public java.lang.String getMeid(int);
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
@@ -53258,6 +53211,7 @@
public class GenericSignatureFormatError extends java.lang.ClassFormatError {
ctor public GenericSignatureFormatError();
+ ctor public GenericSignatureFormatError(java.lang.String);
}
public abstract interface InvocationHandler {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index c7fc860..f272105 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -143,6 +143,7 @@
import libcore.io.EventLogger;
import libcore.io.IoUtils;
import libcore.net.event.NetworkEventDispatcher;
+import dalvik.system.BaseDexClassLoader;
import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;
@@ -5346,6 +5347,16 @@
}
}
+ // If we use profiles, setup the dex reporter to notify package manager
+ // of any relevant dex loads. The idle maintenance job will use the information
+ // reported to optimize the loaded dex files.
+ // Note that we only need one global reporter per app.
+ // Make sure we do this before calling onCreate so that we can capture the
+ // complete application startup.
+ if (SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
+ BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
+ }
+
// Install the Network Security Config Provider. This must happen before the application
// code is loaded to prevent issues with instances of TLS objects being created before
// the provider is installed.
diff --git a/core/java/android/app/DexLoadReporter.java b/core/java/android/app/DexLoadReporter.java
new file mode 100644
index 0000000..13f288a
--- /dev/null
+++ b/core/java/android/app/DexLoadReporter.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2017 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.app;
+
+import android.os.FileUtils;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import dalvik.system.BaseDexClassLoader;
+import dalvik.system.VMRuntime;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A dex load reporter which will notify package manager of any dex file loaded
+ * with {@code BaseDexClassLoader}.
+ * The goals are:
+ * 1) discover secondary dex files so that they can be optimized during the
+ * idle maintenance job.
+ * 2) determine whether or not a dex file is used by an app which does not
+ * own it (in order to select the optimal compilation method).
+ * @hide
+ */
+/*package*/ class DexLoadReporter implements BaseDexClassLoader.Reporter {
+ private static final String TAG = "DexLoadReporter";
+
+ private static final DexLoadReporter INSTANCE = new DexLoadReporter();
+
+ private static final boolean DEBUG = false;
+
+ // We must guard the access to the list of data directories because
+ // we might have concurrent accesses. Apps might load dex files while
+ // new data dirs are registered (due to creation of LoadedApks via
+ // create createApplicationContext).
+ @GuardedBy("mDataDirs")
+ private final Set<String> mDataDirs;
+
+ private DexLoadReporter() {
+ mDataDirs = new HashSet<>();
+ }
+
+ /*package*/ static DexLoadReporter getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Register an application data directory with the reporter.
+ * The data directories are used to determine if a dex file is secondary dex or not.
+ * Note that this method may be called multiple times for the same app, registering
+ * different data directories. This may happen when apps share the same user id
+ * ({@code android:sharedUserId}). For example, if app1 and app2 share the same user
+ * id, and app1 loads app2 apk, then both data directories will be registered.
+ */
+ /*package*/ void registerAppDataDir(String packageName, String dataDir) {
+ if (DEBUG) {
+ Slog.i(TAG, "Package " + packageName + " registering data dir: " + dataDir);
+ }
+ // TODO(calin): A few code paths imply that the data dir
+ // might be null. Investigate when that can happen.
+ if (dataDir != null) {
+ synchronized (mDataDirs) {
+ mDataDirs.add(dataDir);
+ }
+ }
+ }
+
+ @Override
+ public void report(List<String> dexPaths) {
+ if (dexPaths.isEmpty()) {
+ return;
+ }
+ // Notify the package manager about the dex loads unconditionally.
+ // The load might be for either a primary or secondary dex file.
+ notifyPackageManager(dexPaths);
+ // Check for secondary dex files and register them for profiling if
+ // possible.
+ registerSecondaryDexForProfiling(dexPaths);
+ }
+
+ private void notifyPackageManager(List<String> dexPaths) {
+ String packageName = ActivityThread.currentPackageName();
+ try {
+ ActivityThread.getPackageManager().notifyDexLoad(
+ packageName, dexPaths, VMRuntime.getRuntime().vmInstructionSet());
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re);
+ }
+ }
+
+ private void registerSecondaryDexForProfiling(List<String> dexPaths) {
+ if (!SystemProperties.getBoolean("dalvik.vm.dexopt.secondary", false)) {
+ return;
+ }
+ // Make a copy of the current data directories so that we don't keep the lock
+ // while registering for profiling. The registration will perform I/O to
+ // check for or create the profile.
+ String[] dataDirs;
+ synchronized (mDataDirs) {
+ dataDirs = mDataDirs.toArray(new String[0]);
+ }
+ for (String dexPath : dexPaths) {
+ registerSecondaryDexForProfiling(dexPath, dataDirs);
+ }
+ }
+
+ private void registerSecondaryDexForProfiling(String dexPath, String[] dataDirs) {
+ if (!isSecondaryDexFile(dexPath, dataDirs)) {
+ // The dex path is not a secondary dex file. Nothing to do.
+ return;
+ }
+ File secondaryProfile = getSecondaryProfileFile(dexPath);
+ try {
+ // Create the profile if not already there.
+ // Returns true if the file was created, false if the file already exists.
+ // or throws exceptions in case of errors.
+ boolean created = secondaryProfile.createNewFile();
+ if (DEBUG && created) {
+ Slog.i(TAG, "Created profile for secondary dex: " + secondaryProfile);
+ }
+ } catch (IOException ex) {
+ Slog.e(TAG, "Failed to create profile for secondary dex " + secondaryProfile +
+ ":" + ex.getMessage());
+ // Don't move forward with the registration if we failed to create the profile.
+ return;
+ }
+
+ VMRuntime.registerAppInfo(secondaryProfile.getPath(), new String[] { dexPath });
+ }
+
+ // A dex file is a secondary dex file if it is in any of the registered app
+ // data directories.
+ private boolean isSecondaryDexFile(String dexPath, String[] dataDirs) {
+ for (String dataDir : dataDirs) {
+ if (FileUtils.contains(dataDir, dexPath)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Secondary dex profiles are stored next to the dex file and have the same
+ // name with '.prof' appended.
+ // NOTE: Keep in sync with installd.
+ private File getSecondaryProfileFile(String dexPath) {
+ return new File(dexPath + ".prof");
+ }
+}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index c625756..404b7db 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -51,7 +51,6 @@
import android.view.Display;
import android.view.DisplayAdjustments;
-import dalvik.system.BaseDexClassLoader;
import dalvik.system.VMRuntime;
import java.io.File;
@@ -610,39 +609,10 @@
VMRuntime.registerAppInfo(profileFile.getPath(),
codePaths.toArray(new String[codePaths.size()]));
- // Setup the reporter to notify package manager of any relevant dex loads.
- // At this point the primary apk is loaded and will not be reported.
- // Anything loaded from now on will be tracked as a potential secondary
- // or foreign dex file. The goal is to enable:
- // 1) monitoring and compilation of secondary dex file
- // 2) track whether or not a dex file is used by other apps (used to
- // determined the compilation filter of apks).
- if (BaseDexClassLoader.getReporter() != DexLoadReporter.INSTANCE) {
- // Set the dex load reporter if not already set.
- // Note that during the app's life cycle different LoadedApks may be
- // created and loaded (e.g. if two different apps share the same runtime).
- BaseDexClassLoader.setReporter(DexLoadReporter.INSTANCE);
- }
- }
-
- private static class DexLoadReporter implements BaseDexClassLoader.Reporter {
- private static final DexLoadReporter INSTANCE = new DexLoadReporter();
-
- private DexLoadReporter() {}
-
- @Override
- public void report(List<String> dexPaths) {
- if (dexPaths.isEmpty()) {
- return;
- }
- String packageName = ActivityThread.currentPackageName();
- try {
- ActivityThread.getPackageManager().notifyDexLoad(
- packageName, dexPaths, VMRuntime.getRuntime().vmInstructionSet());
- } catch (RemoteException re) {
- Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re);
- }
- }
+ // Register the app data directory with the reporter. It will
+ // help deciding whether or not a dex file is the primary apk or a
+ // secondary dex.
+ DexLoadReporter.getInstance().registerAppDataDir(mPackageName, mDataDir);
}
/**
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0dd9c63..bcdf3f4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1761,7 +1761,9 @@
if (this.actions != null) {
that.actions = new Action[this.actions.length];
for(int i=0; i<this.actions.length; i++) {
- that.actions[i] = this.actions[i].clone();
+ if ( this.actions[i] != null) {
+ that.actions[i] = this.actions[i].clone();
+ }
}
}
@@ -3108,7 +3110,9 @@
* @param action The action to add.
*/
public Builder addAction(Action action) {
- mActions.add(action);
+ if (action != null) {
+ mActions.add(action);
+ }
return this;
}
@@ -3122,7 +3126,9 @@
public Builder setActions(Action... actions) {
mActions.clear();
for (int i = 0; i < actions.length; i++) {
- mActions.add(actions[i]);
+ if (actions[i] != null) {
+ mActions.add(actions[i]);
+ }
}
return this;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 4c5fb13..c933678 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -73,7 +73,9 @@
import android.net.EthernetManager;
import android.net.IConnectivityManager;
import android.net.IEthernetManager;
+import android.net.IIpSecService;
import android.net.INetworkPolicyManager;
+import android.net.IpSecManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkScoreManager;
import android.net.nsd.INsdManager;
@@ -239,6 +241,15 @@
return new ConnectivityManager(context, service);
}});
+ registerService(Context.IPSEC_SERVICE, IpSecManager.class,
+ new StaticServiceFetcher<IpSecManager>() {
+ @Override
+ public IpSecManager createService() {
+ IBinder b = ServiceManager.getService(Context.IPSEC_SERVICE);
+ IIpSecService service = IIpSecService.Stub.asInterface(b);
+ return new IpSecManager(service);
+ }});
+
registerService(Context.COUNTRY_DETECTOR, CountryDetector.class,
new StaticServiceFetcher<CountryDetector>() {
@Override
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 4960159..08e5a6e 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -611,6 +611,51 @@
}
/**
+ * Enables the optional codecs.
+ *
+ * @hide
+ */
+ public void enableOptionalCodecs() {
+ if (DBG) Log.d(TAG, "enableOptionalCodecs");
+ enableDisableOptionalCodecs(true);
+ }
+
+ /**
+ * Disables the optional codecs.
+ *
+ * @hide
+ */
+ public void disableOptionalCodecs() {
+ if (DBG) Log.d(TAG, "disableOptionalCodecs");
+ enableDisableOptionalCodecs(false);
+ }
+
+ /**
+ * Enables or disables the optional codecs.
+ *
+ * @param enable if true, enable the optional codecs, other disable them
+ */
+ private void enableDisableOptionalCodecs(boolean enable) {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
+ if (enable) {
+ mService.enableOptionalCodecs();
+ } else {
+ mService.disableOptionalCodecs();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in enableDisableOptionalCodecs()", e);
+ return;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
* Helper for converting a state to a string.
*
* For debug use only - strings are not internationalized.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 8186937..2c4520d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -638,6 +638,7 @@
* <p>
* Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
* supported on this device before calling this method.
+ * @hide
*/
public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
if (!getLeAccess())
@@ -1447,9 +1448,9 @@
}
/**
- * Return true if LE Periodic Advertising feature is supported.
+ * Return true if LE Extended Advertising feature is supported.
*
- * @return true if chipset supports LE Periodic Advertising feature
+ * @return true if chipset supports LE Extended Advertising feature
*/
public boolean isLeExtendedAdvertisingSupported() {
if (!getLeAccess()) return false;
@@ -1483,6 +1484,25 @@
}
/**
+ * Return the maximum LE advertising data length,
+ * if LE Extended Advertising feature is supported.
+ *
+ * @return the maximum LE advertising data length.
+ */
+ public int getLeMaximumAdvertisingDataLength() {
+ if (!getLeAccess()) return 0;
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) return mService.getLeMaximumAdvertisingDataLength();
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return 0;
+ }
+
+ /**
* Return true if hardware has entries available for matching beacons
*
* @return true if there are hw entries available for matching beacons
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 176e48f..d5e1429 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -63,7 +63,7 @@
public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
private final int mCodecType;
- private final int mCodecPriority;
+ private int mCodecPriority;
private final int mSampleRate;
private final int mBitsPerSample;
private final int mChannelMode;
@@ -280,6 +280,15 @@
}
/**
+ * Checks whether the codec is mandatory.
+ *
+ * @return true if the codec is mandatory, otherwise false.
+ */
+ public boolean isMandatoryCodec() {
+ return mCodecType == SOURCE_CODEC_TYPE_SBC;
+ }
+
+ /**
* Gets the codec selection priority.
* The codec selection priority is relative to other codecs: larger value
* means higher priority. If 0, reset to default.
@@ -291,6 +300,17 @@
}
/**
+ * Sets the codec selection priority.
+ * The codec selection priority is relative to other codecs: larger value
+ * means higher priority. If 0, reset to default.
+ *
+ * @param codecPriority the codec priority
+ */
+ public void setCodecPriority(int codecPriority) {
+ mCodecPriority = codecPriority;
+ }
+
+ /**
* Gets the codec sample rate. The value can be a bitmask with all
* supported sample rates:
* {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 31fc294..cb6fa05 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1664,43 +1664,6 @@
* @param autoConnect Whether to directly connect to the remote device (false)
* or to automatically connect as soon as the remote
* device becomes available (true).
- * @throws IllegalArgumentException if callback is null
- */
- public BluetoothGatt connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallbackExt callback) {
- return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO));
- }
-
- /**
- * Connect to GATT Server hosted by this device. Caller acts as GATT client.
- * The callback is used to deliver results to Caller, such as connection status as well
- * as any further GATT client operations.
- * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
- * GATT client operations.
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @param autoConnect Whether to directly connect to the remote device (false)
- * or to automatically connect as soon as the remote
- * device becomes available (true).
- * @param transport preferred transport for GATT connections to remote dual-mode devices
- * {@link BluetoothDevice#TRANSPORT_AUTO} or
- * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
- * @throws IllegalArgumentException if callback is null
- */
- public BluetoothGatt connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallbackExt callback, int transport) {
- return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M));
- }
-
- /**
- * Connect to GATT Server hosted by this device. Caller acts as GATT client.
- * The callback is used to deliver results to Caller, such as connection status as well
- * as any further GATT client operations.
- * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
- * GATT client operations.
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @param autoConnect Whether to directly connect to the remote device (false)
- * or to automatically connect as soon as the remote
- * device becomes available (true).
* @param transport preferred transport for GATT connections to remote dual-mode devices
* {@link BluetoothDevice#TRANSPORT_AUTO} or
* {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
@@ -1711,7 +1674,7 @@
* @throws IllegalArgumentException if callback is null
*/
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallbackExt callback, int transport, int phy) {
+ BluetoothGattCallback callback, int transport, int phy) {
// TODO(Bluetooth) check whether platform support BLE
// Do the check here or in GattServer?
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 0cb69ae..02ba403 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -31,7 +31,7 @@
* <p>This class provides Bluetooth GATT functionality to enable communication
* with Bluetooth Smart or Smart Ready devices.
*
- * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallbackExt}
+ * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
* and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
* GATT capable devices can be discovered using the Bluetooth device discovery or BLE
* scan process.
@@ -42,7 +42,7 @@
private static final boolean VDBG = false;
private IBluetoothGatt mService;
- private BluetoothGattCallbackExt mCallback;
+ private BluetoothGattCallback mCallback;
private int mClientIf;
private BluetoothDevice mDevice;
private boolean mAutoConnect;
@@ -133,14 +133,15 @@
/*package*/ static final int AUTHENTICATION_MITM = 2;
/**
- * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallbackExt implementation.
+ * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation.
*/
- private final IBluetoothGattCallbackExt mBluetoothGattCallbackExt =
- new IBluetoothGattCallbackExt.Stub() {
+ private final IBluetoothGattCallback mBluetoothGattCallback =
+ new IBluetoothGattCallback.Stub() {
/**
* Application interface registered - app is ready to go
* @hide
*/
+ @Override
public void onClientRegistered(int status, int clientIf) {
if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
+ " clientIf=" + clientIf);
@@ -210,6 +211,7 @@
* Client connection state changed
* @hide
*/
+ @Override
public void onClientConnectionState(int status, int clientIf,
boolean connected, String address) {
if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
@@ -245,6 +247,7 @@
* we are done at this point.
* @hide
*/
+ @Override
public void onSearchComplete(String address, List<BluetoothGattService> services,
int status) {
if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
@@ -288,6 +291,7 @@
* Updates the internal value.
* @hide
*/
+ @Override
public void onCharacteristicRead(String address, int status, int handle, byte[] value) {
if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
+ " handle=" + handle + " Status=" + status);
@@ -336,6 +340,7 @@
* Let the app know how we did...
* @hide
*/
+ @Override
public void onCharacteristicWrite(String address, int status, int handle) {
if (VDBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
+ " handle=" + handle + " Status=" + status);
@@ -380,6 +385,7 @@
* Updates the internal value.
* @hide
*/
+ @Override
public void onNotify(String address, int handle, byte[] value) {
if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle);
@@ -403,6 +409,7 @@
* Descriptor has been read.
* @hide
*/
+ @Override
public void onDescriptorRead(String address, int status, int handle, byte[] value) {
if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " handle=" + handle);
@@ -446,6 +453,7 @@
* Descriptor write operation complete.
* @hide
*/
+ @Override
public void onDescriptorWrite(String address, int status, int handle) {
if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " handle=" + handle);
@@ -488,6 +496,7 @@
* Prepared write transaction completed (or aborted)
* @hide
*/
+ @Override
public void onExecuteWrite(String address, int status) {
if (VDBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
+ " status=" + status);
@@ -510,6 +519,7 @@
* Remote device RSSI has been read
* @hide
*/
+ @Override
public void onReadRemoteRssi(String address, int rssi, int status) {
if (VDBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
" rssi=" + rssi + " status=" + status);
@@ -527,6 +537,7 @@
* Callback invoked when the MTU for a given connection changes
* @hide
*/
+ @Override
public void onConfigureMTU(String address, int mtu, int status) {
if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address +
" mtu=" + mtu + " status=" + status);
@@ -539,6 +550,27 @@
Log.w(TAG, "Unhandled exception in callback", ex);
}
}
+
+ /**
+ * Callback invoked when the given connection is updated
+ * @hide
+ */
+ @Override
+ public void onConnectionUpdated(String address, int interval, int latency,
+ int timeout, int status) {
+ if (DBG) Log.d(TAG, "onConnectionUpdated() - Device=" + address +
+ " interval=" + interval + " latency=" + latency +
+ " timeout=" + timeout + " status=" + status);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ try {
+ mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
+ timeout, status);
+ } catch (Exception ex) {
+ Log.w(TAG, "Unhandled exception in callback", ex);
+ }
+ }
};
/*package*/ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device,
@@ -618,7 +650,7 @@
/**
* Register an application callback to start using GATT.
*
- * <p>This is an asynchronous call. The callback {@link BluetoothGattCallbackExt#onAppRegistered}
+ * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
* is used to notify success or failure if the function returns true.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -627,7 +659,7 @@
* @return If true, the callback will be called to notify success or failure,
* false on immediate error
*/
- private boolean registerApp(BluetoothGattCallbackExt callback) {
+ private boolean registerApp(BluetoothGattCallback callback) {
if (DBG) Log.d(TAG, "registerApp()");
if (mService == null) return false;
@@ -636,7 +668,7 @@
if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
try {
- mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallbackExt);
+ mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -666,7 +698,7 @@
*
* <p>The connection may not be established right away, but will be
* completed when the remote device is available. A
- * {@link BluetoothGattCallbackExt#onConnectionStateChange} callback will be
+ * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
* invoked when the connection state changes as a result of this function.
*
* <p>The autoConnect parameter determines whether to actively connect to
@@ -684,7 +716,7 @@
* device becomes available (true).
* @return true, if the connection attempt was initiated successfully
*/
- /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallbackExt callback) {
+ /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
synchronized(mStateLock) {
if (mConnState != CONN_STATE_IDLE) {
@@ -746,10 +778,10 @@
/**
* Set the preferred connection PHY for this app. Please note that this is just a
- * recommendation, wether the PHY change will happen depends on other applications peferences,
+ * recommendation, whether the PHY change will happen depends on other applications peferences,
* local and remote controller capabilities. Controller can override these settings.
* <p>
- * {@link BluetoothGattCallbackExt#onPhyUpdate} will be triggered as a result of this call, even
+ * {@link BluetoothGattCallback#onPhyUpdate} will be triggered as a result of this call, even
* if no PHY change happens. It is also triggered when remote device updates the PHY.
*
* @param txPhy preferred transmitter PHY. Bitwise OR of any of
@@ -773,7 +805,7 @@
/**
* Read the current transmitter PHY and receiver PHY of the connection. The values are returned
- * in {@link BluetoothGattCallbackExt#onPhyRead}
+ * in {@link BluetoothGattCallback#onPhyRead}
*/
public void readPhy() {
try {
@@ -797,7 +829,7 @@
* characteristics and descriptors.
*
* <p>This is an asynchronous operation. Once service discovery is completed,
- * the {@link BluetoothGattCallbackExt#onServicesDiscovered} callback is
+ * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
* triggered. If the discovery was successful, the remote services can be
* retrieved using the {@link #getServices} function.
*
@@ -876,7 +908,7 @@
* Reads the requested characteristic from the associated remote device.
*
* <p>This is an asynchronous operation. The result of the read operation
- * is reported by the {@link BluetoothGattCallbackExt#onCharacteristicRead}
+ * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
* callback.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -918,7 +950,7 @@
* Writes a given characteristic and its values to the associated remote device.
*
* <p>Once the write operation has been completed, the
- * {@link BluetoothGattCallbackExt#onCharacteristicWrite} callback is invoked,
+ * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
* reporting the result of the operation.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -962,7 +994,7 @@
* Reads the value for a given descriptor from the associated remote device.
*
* <p>Once the read operation has been completed, the
- * {@link BluetoothGattCallbackExt#onDescriptorRead} callback is
+ * {@link BluetoothGattCallback#onDescriptorRead} callback is
* triggered, signaling the result of the operation.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1003,7 +1035,7 @@
/**
* Write the value of a given descriptor to the associated remote device.
*
- * <p>A {@link BluetoothGattCallbackExt#onDescriptorWrite} callback is
+ * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
* triggered to report the result of the write operation.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1047,7 +1079,7 @@
* <p>Once a reliable write transaction has been initiated, all calls
* to {@link #writeCharacteristic} are sent to the remote device for
* verification and queued up for atomic execution. The application will
- * receive an {@link BluetoothGattCallbackExt#onCharacteristicWrite} callback
+ * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
* in response to every {@link #writeCharacteristic} call and is responsible
* for verifying if the value has been transmitted accurately.
*
@@ -1081,7 +1113,7 @@
* <p>This function will commit all queued up characteristic write
* operations for a given remote device.
*
- * <p>A {@link BluetoothGattCallbackExt#onReliableWriteCompleted} callback is
+ * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
* invoked to indicate whether the transaction has been executed correctly.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1138,7 +1170,7 @@
* Enable or disable notifications/indications for a given characteristic.
*
* <p>Once notifications are enabled for a characteristic, a
- * {@link BluetoothGattCallbackExt#onCharacteristicChanged} callback will be
+ * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
* triggered if the remote device indicates that the given characteristic
* has changed.
*
@@ -1193,7 +1225,7 @@
/**
* Read the RSSI for a connected remote device.
*
- * <p>The {@link BluetoothGattCallbackExt#onReadRemoteRssi} callback will be
+ * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
* invoked when the RSSI value has been read.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1221,7 +1253,7 @@
* the data sent is truncated to the MTU size. This function may be used
* to request a larger MTU size to be able to send more data at once.
*
- * <p>A {@link BluetoothGattCallbackExt#onMtuChanged} callback will indicate
+ * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate
* whether this operation was successful.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 4da106d..11a15c6 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -18,22 +18,183 @@
/**
* This abstract class is used to implement {@link BluetoothGatt} callbacks.
- * @deprecated use {@link BluetoothGattCallbackExt}
*/
-public abstract class BluetoothGattCallback extends BluetoothGattCallbackExt {
+public abstract class BluetoothGattCallback{
/**
- * @hide
+ * Callback triggered as result of {@link BluetoothGatt#setPreferredPhy}, or as a result of
+ * remote device changing the PHY.
+ *
+ * @param gatt GATT client
+ * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+ * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+ * @param status status of the operation
*/
- @Override
public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
}
/**
- * @hide
+ * Callback triggered as result of {@link BluetoothGatt#readPhy}
+ *
+ * @param gatt GATT client
+ * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+ * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+ * @param status status of the operation
*/
- @Override
public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
}
+ /**
+ * Callback indicating when GATT client has connected/disconnected to/from a remote
+ * GATT server.
+ *
+ * @param gatt GATT client
+ * @param status Status of the connect or disconnect operation.
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
+ * @param newState Returns the new connection state. Can be one of
+ * {@link BluetoothProfile#STATE_DISCONNECTED} or
+ * {@link BluetoothProfile#STATE_CONNECTED}
+ */
+ public void onConnectionStateChange(BluetoothGatt gatt, int status,
+ int newState) {
+ }
+
+ /**
+ * Callback invoked when the list of remote services, characteristics and descriptors
+ * for the remote device have been updated, ie new services have been discovered.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices}
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device
+ * has been explored successfully.
+ */
+ public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+ }
+
+ /**
+ * Callback reporting the result of a characteristic read operation.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#readCharacteristic}
+ * @param characteristic Characteristic that was read from the associated
+ * remote device.
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
+ * was completed successfully.
+ */
+ public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
+ int status) {
+ }
+
+ /**
+ * Callback indicating the result of a characteristic write operation.
+ *
+ * <p>If this callback is invoked while a reliable write transaction is
+ * in progress, the value of the characteristic represents the value
+ * reported by the remote device. An application should compare this
+ * value to the desired value to be written. If the values don't match,
+ * the application must abort the reliable write transaction.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic}
+ * @param characteristic Characteristic that was written to the associated
+ * remote device.
+ * @param status The result of the write operation
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
+ */
+ public void onCharacteristicWrite(BluetoothGatt gatt,
+ BluetoothGattCharacteristic characteristic, int status) {
+ }
+
+ /**
+ * Callback triggered as a result of a remote characteristic notification.
+ *
+ * @param gatt GATT client the characteristic is associated with
+ * @param characteristic Characteristic that has been updated as a result
+ * of a remote notification event.
+ */
+ public void onCharacteristicChanged(BluetoothGatt gatt,
+ BluetoothGattCharacteristic characteristic) {
+ }
+
+ /**
+ * Callback reporting the result of a descriptor read operation.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
+ * @param descriptor Descriptor that was read from the associated
+ * remote device.
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
+ * was completed successfully
+ */
+ public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
+ int status) {
+ }
+
+ /**
+ * Callback indicating the result of a descriptor write operation.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
+ * @param descriptor Descriptor that was writte to the associated
+ * remote device.
+ * @param status The result of the write operation
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
+ */
+ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
+ int status) {
+ }
+
+ /**
+ * Callback invoked when a reliable write transaction has been completed.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#executeReliableWrite}
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write
+ * transaction was executed successfully
+ */
+ public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
+ }
+
+ /**
+ * Callback reporting the RSSI for a remote device connection.
+ *
+ * This callback is triggered in response to the
+ * {@link BluetoothGatt#readRemoteRssi} function.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#readRemoteRssi}
+ * @param rssi The RSSI value for the remote device
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
+ */
+ public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
+ }
+
+ /**
+ * Callback indicating the MTU for a given device connection has changed.
+ *
+ * This callback is triggered in response to the
+ * {@link BluetoothGatt#requestMtu} function, or in response to a connection
+ * event.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu}
+ * @param mtu The new MTU size
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
+ */
+ public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
+ }
+
+ /**
+ * Callback indicating the connection parameters were updated.
+ *
+ * @param gatt GATT client involved
+ * @param interval Connection interval used on this connection, 1.25ms unit. Valid
+ * range is from 6 (7.5ms) to 3200 (4000ms).
+ * @param latency Slave latency for the connection in number of connection events. Valid
+ * range is from 0 to 499
+ * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is
+ * from 10 (0.1s) to 3200 (32s)
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated
+ * successfully
+ * @hide
+ */
+ public void onConnectionUpdated(BluetoothGatt gatt, int interval, int latency, int timeout,
+ int status) {
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothGattCallbackExt.java b/core/java/android/bluetooth/BluetoothGattCallbackExt.java
deleted file mode 100644
index 63774c8..0000000
--- a/core/java/android/bluetooth/BluetoothGattCallbackExt.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-/**
- * This abstract class is used to implement {@link BluetoothGatt} callbacks.
- */
-public abstract class BluetoothGattCallbackExt {
-
- /**
- * Callback triggered as result of {@link BluetoothGatt#setPreferredPhy}, or as a result of
- * remote device changing the PHY.
- *
- * @param gatt GATT client
- * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
- * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
- * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param status status of the operation
- */
- public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
- }
-
- /**
- * Callback triggered as result of {@link BluetoothGatt#readPhy}
- *
- * @param gatt GATT client
- * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
- * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
- * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param status status of the operation
- */
- public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
- }
-
- /**
- * Callback indicating when GATT client has connected/disconnected to/from a remote
- * GATT server.
- *
- * @param gatt GATT client
- * @param status Status of the connect or disconnect operation.
- * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
- * @param newState Returns the new connection state. Can be one of
- * {@link BluetoothProfile#STATE_DISCONNECTED} or
- * {@link BluetoothProfile#STATE_CONNECTED}
- */
- public void onConnectionStateChange(BluetoothGatt gatt, int status,
- int newState) {
- }
-
- /**
- * Callback invoked when the list of remote services, characteristics and descriptors
- * for the remote device have been updated, ie new services have been discovered.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices}
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device
- * has been explored successfully.
- */
- public void onServicesDiscovered(BluetoothGatt gatt, int status) {
- }
-
- /**
- * Callback reporting the result of a characteristic read operation.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#readCharacteristic}
- * @param characteristic Characteristic that was read from the associated
- * remote device.
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
- * was completed successfully.
- */
- public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
- int status) {
- }
-
- /**
- * Callback indicating the result of a characteristic write operation.
- *
- * <p>If this callback is invoked while a reliable write transaction is
- * in progress, the value of the characteristic represents the value
- * reported by the remote device. An application should compare this
- * value to the desired value to be written. If the values don't match,
- * the application must abort the reliable write transaction.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic}
- * @param characteristic Characteristic that was written to the associated
- * remote device.
- * @param status The result of the write operation
- * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
- */
- public void onCharacteristicWrite(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic, int status) {
- }
-
- /**
- * Callback triggered as a result of a remote characteristic notification.
- *
- * @param gatt GATT client the characteristic is associated with
- * @param characteristic Characteristic that has been updated as a result
- * of a remote notification event.
- */
- public void onCharacteristicChanged(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic) {
- }
-
- /**
- * Callback reporting the result of a descriptor read operation.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
- * @param descriptor Descriptor that was read from the associated
- * remote device.
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
- * was completed successfully
- */
- public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
- int status) {
- }
-
- /**
- * Callback indicating the result of a descriptor write operation.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
- * @param descriptor Descriptor that was writte to the associated
- * remote device.
- * @param status The result of the write operation
- * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
- */
- public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
- int status) {
- }
-
- /**
- * Callback invoked when a reliable write transaction has been completed.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#executeReliableWrite}
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write
- * transaction was executed successfully
- */
- public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
- }
-
- /**
- * Callback reporting the RSSI for a remote device connection.
- *
- * This callback is triggered in response to the
- * {@link BluetoothGatt#readRemoteRssi} function.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#readRemoteRssi}
- * @param rssi The RSSI value for the remote device
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
- */
- public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
- }
-
- /**
- * Callback indicating the MTU for a given device connection has changed.
- *
- * This callback is triggered in response to the
- * {@link BluetoothGatt#requestMtu} function, or in response to a connection
- * event.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu}
- * @param mtu The new MTU size
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
- */
- public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 9ee739f..2df2ed8 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -46,7 +46,7 @@
private BluetoothAdapter mAdapter;
private IBluetoothGatt mService;
- private BluetoothGattServerCallbackExt mCallback;
+ private BluetoothGattServerCallback mCallback;
private Object mServerIfLock = new Object();
private int mServerIf;
@@ -59,12 +59,13 @@
/**
* Bluetooth GATT interface callbacks
*/
- private final IBluetoothGattServerCallbackExt mBluetoothGattServerCallback =
- new IBluetoothGattServerCallbackExt.Stub() {
+ private final IBluetoothGattServerCallback mBluetoothGattServerCallback =
+ new IBluetoothGattServerCallback.Stub() {
/**
* Application interface registered - app is ready to go
* @hide
*/
+ @Override
public void onServerRegistered(int status, int serverIf) {
if (DBG) Log.d(TAG, "onServerRegistered() - status=" + status
+ " serverIf=" + serverIf);
@@ -80,18 +81,10 @@
}
/**
- * Callback reporting an LE scan result.
- * @hide
- */
- public void onScanResult(String address, int rssi, byte[] advData) {
- if (VDBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
- // no op
- }
-
- /**
* Server connection state changed
* @hide
*/
+ @Override
public void onServerConnectionState(int status, int serverIf,
boolean connected, String address) {
if (DBG) Log.d(TAG, "onServerConnectionState() - status=" + status
@@ -109,6 +102,7 @@
* Service has been added
* @hide
*/
+ @Override
public void onServiceAdded(int status, BluetoothGattService service) {
if (DBG) Log.d(TAG, "onServiceAdded() - handle=" + service.getInstanceId()
+ " uuid=" + service.getUuid() + " status=" + status);
@@ -149,6 +143,7 @@
* Remote client characteristic read request.
* @hide
*/
+ @Override
public void onCharacteristicReadRequest(String address, int transId,
int offset, boolean isLong, int handle) {
if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
@@ -171,6 +166,7 @@
* Remote client descriptor read request.
* @hide
*/
+ @Override
public void onDescriptorReadRequest(String address, int transId,
int offset, boolean isLong, int handle) {
if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
@@ -193,6 +189,7 @@
* Remote client characteristic write request.
* @hide
*/
+ @Override
public void onCharacteristicWriteRequest(String address, int transId,
int offset, int length, boolean isPrep, boolean needRsp,
int handle, byte[] value) {
@@ -218,6 +215,7 @@
* Remote client descriptor write request.
* @hide
*/
+ @Override
public void onDescriptorWriteRequest(String address, int transId, int offset,
int length, boolean isPrep, boolean needRsp, int handle, byte[] value) {
if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - handle=" + handle);
@@ -241,6 +239,7 @@
* Execute pending writes.
* @hide
*/
+ @Override
public void onExecuteWrite(String address, int transId,
boolean execWrite) {
if (DBG) Log.d(TAG, "onExecuteWrite() - "
@@ -261,6 +260,7 @@
* A notification/indication has been sent.
* @hide
*/
+ @Override
public void onNotificationSent(String address, int status) {
if (VDBG) Log.d(TAG, "onNotificationSent() - "
+ "device=" + address + ", status=" + status);
@@ -279,6 +279,7 @@
* The MTU for a connection has changed
* @hide
*/
+ @Override
public void onMtuChanged(String address, int mtu) {
if (DBG) Log.d(TAG, "onMtuChanged() - "
+ "device=" + address + ", mtu=" + mtu);
@@ -297,6 +298,7 @@
* The PHY for a connection was updated
* @hide
*/
+ @Override
public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
if (DBG) Log.d(TAG, "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
+ ", rxPHy=" + rxPhy);
@@ -315,6 +317,7 @@
* The PHY for a connection was read
* @hide
*/
+ @Override
public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
if (DBG) Log.d(TAG, "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
+ ", rxPHy=" + rxPhy);
@@ -328,6 +331,28 @@
Log.w(TAG, "Unhandled exception: " + ex);
}
}
+
+ /**
+ * Callback invoked when the given connection is updated
+ * @hide
+ */
+ @Override
+ public void onConnectionUpdated(String address, int interval, int latency,
+ int timeout, int status) {
+ if (DBG) Log.d(TAG, "onConnectionUpdated() - Device=" + address +
+ " interval=" + interval + " latency=" + latency +
+ " timeout=" + timeout + " status=" + status);
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if (device == null) return;
+
+ try {
+ mCallback.onConnectionUpdated(device, interval, latency,
+ timeout, status);
+ } catch (Exception ex) {
+ Log.w(TAG, "Unhandled exception: " + ex);
+ }
+ }
+
};
/**
@@ -396,7 +421,7 @@
* @return true, the callback will be called to notify success or failure,
* false on immediate error
*/
- /*package*/ boolean registerCallback(BluetoothGattServerCallbackExt callback) {
+ /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
if (DBG) Log.d(TAG, "registerCallback()");
if (mService == null) {
Log.e(TAG, "GATT service not available");
@@ -472,7 +497,7 @@
*
* <p>The connection may not be established right away, but will be
* completed when the remote device is available. A
- * {@link BluetoothGattServerCallbackExt#onConnectionStateChange} callback will be
+ * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
* invoked when the connection state changes as a result of this function.
*
* <p>The autoConnect paramter determines whether to actively connect to
@@ -525,10 +550,10 @@
/**
* Set the preferred connection PHY for this app. Please note that this is just a
- * recommendation, wether the PHY change will happen depends on other applications peferences,
+ * recommendation, whether the PHY change will happen depends on other applications peferences,
* local and remote controller capabilities. Controller can override these settings.
* <p>
- * {@link BluetoothGattServerCallbackExt#onPhyUpdate} will be triggered as a result of this call, even
+ * {@link BluetoothGattServerCallback#onPhyUpdate} will be triggered as a result of this call, even
* if no PHY change happens. It is also triggered when remote device updates the PHY.
*
* @param device The remote device to send this response to
@@ -553,7 +578,7 @@
/**
* Read the current transmitter PHY and receiver PHY of the connection. The values are returned
- * in {@link BluetoothGattServerCallbackExt#onPhyRead}
+ * in {@link BluetoothGattServerCallback#onPhyRead}
*
* @param device The remote device to send this response to
*/
@@ -572,10 +597,10 @@
* is received by one of these callback methods:
*
* <ul>
- * <li>{@link BluetoothGattServerCallbackExt#onCharacteristicReadRequest}
- * <li>{@link BluetoothGattServerCallbackExt#onCharacteristicWriteRequest}
- * <li>{@link BluetoothGattServerCallbackExt#onDescriptorReadRequest}
- * <li>{@link BluetoothGattServerCallbackExt#onDescriptorWriteRequest}
+ * <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
+ * <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest}
+ * <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest}
+ * <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest}
* </ul>
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
index 75ceb52..3b8f962 100644
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java
@@ -20,21 +20,187 @@
/**
* This abstract class is used to implement {@link BluetoothGattServer} callbacks.
- * @deprecated please use {@link BluetoothGattServerCallbackExt}
*/
-public abstract class BluetoothGattServerCallback extends BluetoothGattServerCallbackExt {
+public abstract class BluetoothGattServerCallback {
/**
- * @hide
+ * Callback indicating when a remote device has been connected or disconnected.
+ *
+ * @param device Remote device that has been connected or disconnected.
+ * @param status Status of the connect or disconnect operation.
+ * @param newState Returns the new connection state. Can be one of
+ * {@link BluetoothProfile#STATE_DISCONNECTED} or
+ * {@link BluetoothProfile#STATE_CONNECTED}
*/
- @Override
+ public void onConnectionStateChange(BluetoothDevice device, int status,
+ int newState) {
+ }
+
+ /**
+ * Indicates whether a local service has been added successfully.
+ *
+ * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service
+ * was added successfully.
+ * @param service The service that has been added
+ */
+ public void onServiceAdded(int status, BluetoothGattService service) {
+ }
+
+ /**
+ * A remote client has requested to read a local characteristic.
+ *
+ * <p>An application must call {@link BluetoothGattServer#sendResponse}
+ * to complete the request.
+ *
+ * @param device The remote device that has requested the read operation
+ * @param requestId The Id of the request
+ * @param offset Offset into the value of the characteristic
+ * @param characteristic Characteristic to be read
+ */
+ public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
+ int offset, BluetoothGattCharacteristic characteristic) {
+ }
+
+ /**
+ * A remote client has requested to write to a local characteristic.
+ *
+ * <p>An application must call {@link BluetoothGattServer#sendResponse}
+ * to complete the request.
+ *
+ * @param device The remote device that has requested the write operation
+ * @param requestId The Id of the request
+ * @param characteristic Characteristic to be written to.
+ * @param preparedWrite true, if this write operation should be queued for
+ * later execution.
+ * @param responseNeeded true, if the remote device requires a response
+ * @param offset The offset given for the value
+ * @param value The value the client wants to assign to the characteristic
+ */
+ public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
+ BluetoothGattCharacteristic characteristic,
+ boolean preparedWrite, boolean responseNeeded,
+ int offset, byte[] value) {
+ }
+
+ /**
+ * A remote client has requested to read a local descriptor.
+ *
+ * <p>An application must call {@link BluetoothGattServer#sendResponse}
+ * to complete the request.
+ *
+ * @param device The remote device that has requested the read operation
+ * @param requestId The Id of the request
+ * @param offset Offset into the value of the characteristic
+ * @param descriptor Descriptor to be read
+ */
+ public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
+ int offset, BluetoothGattDescriptor descriptor) {
+ }
+
+ /**
+ * A remote client has requested to write to a local descriptor.
+ *
+ * <p>An application must call {@link BluetoothGattServer#sendResponse}
+ * to complete the request.
+ *
+ * @param device The remote device that has requested the write operation
+ * @param requestId The Id of the request
+ * @param descriptor Descriptor to be written to.
+ * @param preparedWrite true, if this write operation should be queued for
+ * later execution.
+ * @param responseNeeded true, if the remote device requires a response
+ * @param offset The offset given for the value
+ * @param value The value the client wants to assign to the descriptor
+ */
+ public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
+ BluetoothGattDescriptor descriptor,
+ boolean preparedWrite, boolean responseNeeded,
+ int offset, byte[] value) {
+ }
+
+ /**
+ * Execute all pending write operations for this device.
+ *
+ * <p>An application must call {@link BluetoothGattServer#sendResponse}
+ * to complete the request.
+ *
+ * @param device The remote device that has requested the write operations
+ * @param requestId The Id of the request
+ * @param execute Whether the pending writes should be executed (true) or
+ * cancelled (false)
+ */
+ public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
+ }
+
+ /**
+ * Callback invoked when a notification or indication has been sent to
+ * a remote device.
+ *
+ * <p>When multiple notifications are to be sent, an application must
+ * wait for this callback to be received before sending additional
+ * notifications.
+ *
+ * @param device The remote device the notification has been sent to
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful
+ */
+ public void onNotificationSent(BluetoothDevice device, int status) {
+ }
+
+ /**
+ * Callback indicating the MTU for a given device connection has changed.
+ *
+ * <p>This callback will be invoked if a remote client has requested to change
+ * the MTU for a given connection.
+ *
+ * @param device The remote device that requested the MTU change
+ * @param mtu The new MTU size
+ */
+ public void onMtuChanged(BluetoothDevice device, int mtu) {
+ }
+
+ /**
+ * Callback triggered as result of {@link BluetoothGattServer#setPreferredPhy}, or as a result
+ * of remote device changing the PHY.
+ *
+ * @param device The remote device
+ * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+ * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+ * @param status status of the operation
+ */
public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
}
/**
- * @hide
+ * Callback triggered as result of {@link BluetoothGattServer#readPhy}
+ *
+ * @param device The remote device that requested the PHY read
+ * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+ * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+ * @param status status of the operation
*/
- @Override
public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
}
+
+ /**
+ * Callback indicating the connection parameters were updated.
+ *
+ * @param device The remote device involved
+ * @param interval Connection interval used on this connection, 1.25ms unit. Valid
+ * range is from 6 (7.5ms) to 3200 (4000ms).
+ * @param latency Slave latency for the connection in number of connection events. Valid
+ * range is from 0 to 499
+ * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is
+ * from 10 (0.1s) to 3200 (32s)
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated
+ * successfully
+ * @hide
+ */
+ public void onConnectionUpdated(BluetoothDevice gatt, int interval, int latency, int timeout,
+ int status) {
+ }
+
}
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallbackExt.java b/core/java/android/bluetooth/BluetoothGattServerCallbackExt.java
deleted file mode 100644
index 455cce0..0000000
--- a/core/java/android/bluetooth/BluetoothGattServerCallbackExt.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2013 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.bluetooth.BluetoothDevice;
-
-/**
- * This abstract class is used to implement {@link BluetoothGattServer} callbacks.
- */
-public abstract class BluetoothGattServerCallbackExt {
-
- /**
- * Callback indicating when a remote device has been connected or disconnected.
- *
- * @param device Remote device that has been connected or disconnected.
- * @param status Status of the connect or disconnect operation.
- * @param newState Returns the new connection state. Can be one of
- * {@link BluetoothProfile#STATE_DISCONNECTED} or
- * {@link BluetoothProfile#STATE_CONNECTED}
- */
- public void onConnectionStateChange(BluetoothDevice device, int status,
- int newState) {
- }
-
- /**
- * Indicates whether a local service has been added successfully.
- *
- * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service
- * was added successfully.
- * @param service The service that has been added
- */
- public void onServiceAdded(int status, BluetoothGattService service) {
- }
-
- /**
- * A remote client has requested to read a local characteristic.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the read operation
- * @param requestId The Id of the request
- * @param offset Offset into the value of the characteristic
- * @param characteristic Characteristic to be read
- */
- public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
- int offset, BluetoothGattCharacteristic characteristic) {
- }
-
- /**
- * A remote client has requested to write to a local characteristic.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the write operation
- * @param requestId The Id of the request
- * @param characteristic Characteristic to be written to.
- * @param preparedWrite true, if this write operation should be queued for
- * later execution.
- * @param responseNeeded true, if the remote device requires a response
- * @param offset The offset given for the value
- * @param value The value the client wants to assign to the characteristic
- */
- public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
- BluetoothGattCharacteristic characteristic,
- boolean preparedWrite, boolean responseNeeded,
- int offset, byte[] value) {
- }
-
- /**
- * A remote client has requested to read a local descriptor.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the read operation
- * @param requestId The Id of the request
- * @param offset Offset into the value of the characteristic
- * @param descriptor Descriptor to be read
- */
- public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
- int offset, BluetoothGattDescriptor descriptor) {
- }
-
- /**
- * A remote client has requested to write to a local descriptor.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the write operation
- * @param requestId The Id of the request
- * @param descriptor Descriptor to be written to.
- * @param preparedWrite true, if this write operation should be queued for
- * later execution.
- * @param responseNeeded true, if the remote device requires a response
- * @param offset The offset given for the value
- * @param value The value the client wants to assign to the descriptor
- */
- public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
- BluetoothGattDescriptor descriptor,
- boolean preparedWrite, boolean responseNeeded,
- int offset, byte[] value) {
- }
-
- /**
- * Execute all pending write operations for this device.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the write operations
- * @param requestId The Id of the request
- * @param execute Whether the pending writes should be executed (true) or
- * cancelled (false)
- */
- public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
- }
-
- /**
- * Callback invoked when a notification or indication has been sent to
- * a remote device.
- *
- * <p>When multiple notifications are to be sent, an application must
- * wait for this callback to be received before sending additional
- * notifications.
- *
- * @param device The remote device the notification has been sent to
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful
- */
- public void onNotificationSent(BluetoothDevice device, int status) {
- }
-
- /**
- * Callback indicating the MTU for a given device connection has changed.
- *
- * <p>This callback will be invoked if a remote client has requested to change
- * the MTU for a given connection.
- *
- * @param device The remote device that requested the MTU change
- * @param mtu The new MTU size
- */
- public void onMtuChanged(BluetoothDevice device, int mtu) {
- }
-
- /**
- * Callback triggered as result of {@link BluetoothGattServer#setPreferredPhy}, or as a result
- * of remote device changing the PHY.
- *
- * @param device The remote device
- * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
- * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
- * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param status status of the operation
- */
- public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
- }
-
- /**
- * Callback triggered as result of {@link BluetoothGattServer#readPhy}
- *
- * @param device The remote device that requested the PHY read
- * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
- * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
- * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param status status of the operation
- */
- public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 98a5341..6bf6aa0 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -416,6 +416,11 @@
if(mSocketState != SocketState.INIT) return EBADFD;
if(mPfd == null) return -1;
FileDescriptor fd = mPfd.getFileDescriptor();
+ if (fd == null) {
+ Log.e(TAG, "bindListen(), null file descriptor");
+ return -1;
+ }
+
if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket");
mSocket = LocalSocket.createConnectedLocalSocket(fd);
if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()");
@@ -556,8 +561,9 @@
@Override
public void close() throws IOException {
- if (DBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: "
- + mSocketState);
+ Log.d(TAG, "close() this: " + this + ", channel: " + mPort +
+ ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS +
+ "mSocket: " + mSocket + ", mSocketState: " + mSocketState);
if(mSocketState == SocketState.CLOSED)
return;
else
@@ -567,9 +573,6 @@
if(mSocketState == SocketState.CLOSED)
return;
mSocketState = SocketState.CLOSED;
- if (DBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort +
- ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS +
- "mSocket: " + mSocket);
if(mSocket != null) {
if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket);
mSocket.shutdownInput();
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 76ca554..b337817 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -108,6 +108,7 @@
boolean isLeCodedPhySupported();
boolean isLeExtendedAdvertisingSupported();
boolean isLePeriodicAdvertisingSupported();
+ int getLeMaximumAdvertisingDataLength();
BluetoothActivityEnergyInfo reportActivityInfo();
/**
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index dbb5b7d..a775a1f 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -40,4 +40,6 @@
boolean isA2dpPlaying(in BluetoothDevice device);
BluetoothCodecStatus getCodecStatus();
oneway void setCodecConfigPreference(in BluetoothCodecConfig codecConfig);
+ oneway void enableOptionalCodecs();
+ oneway void disableOptionalCodecs();
}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 33fedc7..334e88b 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -29,8 +29,8 @@
import android.os.ParcelUuid;
import android.os.WorkSource;
-import android.bluetooth.IBluetoothGattCallbackExt;
-import android.bluetooth.IBluetoothGattServerCallbackExt;
+import android.bluetooth.IBluetoothGattCallback;
+import android.bluetooth.IBluetoothGattServerCallback;
import android.bluetooth.le.IAdvertiserCallback;
import android.bluetooth.le.IAdvertisingSetCallback;
import android.bluetooth.le.IPeriodicAdvertisingCallback;
@@ -50,31 +50,24 @@
void stopScan(in int scannerId);
void flushPendingBatchResults(in int scannerId);
- void registerAdvertiser(in IAdvertiserCallback callback);
- void unregisterAdvertiser(in int advertiserId);
- void startMultiAdvertising(in int advertiserId,
- in AdvertiseData advertiseData,
- in AdvertiseData scanResponse,
- in AdvertiseSettings settings);
- void stopMultiAdvertising(in int advertiserId);
-
void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData,
in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters,
- in AdvertiseData periodicData, in IAdvertisingSetCallback callback);
+ in AdvertiseData periodicData, in int duration, in int maxExtAdvEvents,
+ in IAdvertisingSetCallback callback);
void stopAdvertisingSet(in IAdvertisingSetCallback callback);
- void enableAdverisingSet(in int advertiserId, in boolean enable);
+ void enableAdvertisingSet(in int advertiserId, in boolean enable, in int duration, in int maxExtAdvEvents);
void setAdvertisingData(in int advertiserId, in AdvertiseData data);
void setScanResponseData(in int advertiserId, in AdvertiseData data);
void setAdvertisingParameters(in int advertiserId, in AdvertisingSetParameters parameters);
void setPeriodicAdvertisingParameters(in int advertiserId, in PeriodicAdvertisingParameters parameters);
void setPeriodicAdvertisingData(in int advertiserId, in AdvertiseData data);
- void periodicAdvertisingEnable(in int advertiserId, in boolean enable);
+ void setPeriodicAdvertisingEnable(in int advertiserId, in boolean enable);
void registerSync(in ScanResult scanResult, in int skip, in int timeout, in IPeriodicAdvertisingCallback callback);
void unregisterSync(in IPeriodicAdvertisingCallback callback);
- void registerClient(in ParcelUuid appId, in IBluetoothGattCallbackExt callback);
+ void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
void unregisterClient(in int clientIf);
void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport, in int phy);
@@ -96,7 +89,7 @@
void configureMTU(in int clientIf, in String address, in int mtu);
void connectionParameterUpdate(in int clientIf, in String address, in int connectionPriority);
- void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallbackExt callback);
+ void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallback callback);
void unregisterServer(in int serverIf);
void serverConnect(in int serverIf, in String address, in boolean isDirect, in int transport);
void serverDisconnect(in int serverIf, in String address);
diff --git a/core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
similarity index 90%
rename from core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl
rename to core/java/android/bluetooth/IBluetoothGattCallback.aidl
index 736f4b2..4f85cdd 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -22,7 +22,7 @@
* Callback definitions for interacting with BLE / GATT
* @hide
*/
-oneway interface IBluetoothGattCallbackExt {
+oneway interface IBluetoothGattCallback {
void onClientRegistered(in int status, in int clientIf);
void onClientConnectionState(in int status, in int clientIf,
in boolean connected, in String address);
@@ -37,4 +37,6 @@
void onNotify(in String address, in int handle, in byte[] value);
void onReadRemoteRssi(in String address, in int rssi, in int status);
void onConfigureMTU(in String address, in int mtu, in int status);
+ void onConnectionUpdated(in String address, in int interval, in int latency,
+ in int timeout, in int status);
}
diff --git a/core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl b/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
similarity index 91%
rename from core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl
rename to core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
index 091ffb3..74ee11f 100644
--- a/core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
@@ -21,7 +21,7 @@
* Callback definitions for interacting with BLE / GATT
* @hide
*/
-oneway interface IBluetoothGattServerCallbackExt {
+oneway interface IBluetoothGattServerCallback {
void onServerRegistered(in int status, in int serverIf);
void onServerConnectionState(in int status, in int serverIf,
in boolean connected, in String address);
@@ -42,4 +42,6 @@
void onMtuChanged(in String address, in int mtu);
void onPhyUpdate(in String address, in int txPhy, in int rxPhy, in int status);
void onPhyRead(in String address, in int txPhy, in int rxPhy, in int status);
+ void onConnectionUpdated(in String address, in int interval, in int latency,
+ in int timeout, in int status);
}
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
index 1524022..51571b2 100644
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ b/core/java/android/bluetooth/le/AdvertisingSet.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManager;
import android.bluetooth.le.IAdvertisingSetCallback;
@@ -57,15 +58,23 @@
/**
* Enables Advertising. This method returns immediately, the operation status is
- * delivered
- * through {@code callback.onAdvertisingEnabled()}.
+ * delivered through {@code callback.onAdvertisingEnabled()}.
* <p>
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
*
+ * @param enable whether the advertising should be enabled (true), or disabled (false)
+ * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to
+ * 65535 (655,350 ms)
+ * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
+ * controller shall attempt to send prior to terminating the extended
+ * advertising, even if the duration has not expired. Valid range is
+ * from 1 to 255.
*/
- public void enableAdvertising(boolean enable) {
+ public void enableAdvertising(boolean enable, int duration,
+ int maxExtendedAdvertisingEvents) {
try {
- gatt.enableAdverisingSet(this.advertiserId, enable);
+ gatt.enableAdvertisingSet(this.advertiserId, enable, duration,
+ maxExtendedAdvertisingEvents);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
@@ -77,10 +86,16 @@
* delivered through {@code callback.onAdvertisingDataSet()}.
* <p>
* Advertising data must be empty if non-legacy scannable advertising is used.
+ *
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags. If the
+ * update takes place when the advertising set is enabled, the data can be
+ * maximum 251 bytes long.
*/
- public void setAdvertisingData(AdvertiseData data) {
+ public void setAdvertisingData(AdvertiseData advertiseData) {
try {
- gatt.setAdvertisingData(this.advertiserId, data);
+ gatt.setAdvertisingData(this.advertiserId, advertiseData);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
@@ -90,10 +105,15 @@
* Set/update scan response data. Make sure that data doesn't exceed the size limit for
* specified AdvertisingSetParameters. This method returns immediately, the operation status
* is delivered through {@code callback.onScanResponseDataSet()}.
+ *
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * update takes place when the advertising set is enabled, the data can be
+ * maximum 251 bytes long.
*/
- public void setScanResponseData(AdvertiseData data) {
+ public void setScanResponseData(AdvertiseData scanResponse) {
try {
- gatt.setScanResponseData(this.advertiserId, data);
+ gatt.setScanResponseData(this.advertiserId, scanResponse);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
@@ -103,6 +123,8 @@
* Update advertising parameters associated with this AdvertisingSet. Must be called when
* advertising is not active. This method returns immediately, the operation status is delivered
* through {@code callback.onAdvertisingParametersUpdated}.
+ *
+ * @param parameters advertising set parameters.
*/
public void setAdvertisingParameters(AdvertisingSetParameters parameters) {
try {
@@ -130,10 +152,15 @@
* or after advertising was started with periodic advertising data set. This method returns
* immediately, the operation status is delivered through
* {@code callback.onPeriodicAdvertisingDataSet()}.
+ *
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * update takes place when the periodic advertising is enabled for this set,
+ * the data can be maximum 251 bytes long.
*/
- public void setPeriodicAdvertisingData(AdvertiseData data) {
+ public void setPeriodicAdvertisingData(AdvertiseData periodicData) {
try {
- gatt.setPeriodicAdvertisingData(this.advertiserId, data);
+ gatt.setPeriodicAdvertisingData(this.advertiserId, periodicData);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
@@ -142,10 +169,12 @@
/**
* Used to enable/disable periodic advertising. This method returns immediately, the operation
* status is delivered through {@code callback.onPeriodicAdvertisingEnable()}.
+ *
+ * @param enable whether the periodic advertising should be enabled (true), or disabled (false).
*/
- public void periodicAdvertisingEnable(boolean enable) {
+ public void setPeriodicAdvertisingEnable(boolean enable) {
try {
- gatt.periodicAdvertisingEnable(this.advertiserId, enable);
+ gatt.setPeriodicAdvertisingEnable(this.advertiserId, enable);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
index ceed8d9..fe3b1cd 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
@@ -62,9 +62,10 @@
* null, and status will be set to proper error code.
*
* @param advertisingSet The advertising set that was started or null if error.
+ * @param txPower tx power that will be used for this set.
* @param status Status of the operation.
*/
- public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int status) {}
+ public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {}
/**
* Callback triggered in response to {@link BluetoothLeAdvertiser#stopAdvertisingSet}
@@ -106,10 +107,11 @@
* indicating result of the operation.
*
* @param advertisingSet The advertising set.
+ * @param txPower tx power that will be used for this set.
* @param status Status of the operation.
*/
public void onAdvertisingParametersUpdated(AdvertisingSet advertisingSet,
- int status) {}
+ int txPower, int status) {}
/**
* Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingParameters}
@@ -133,12 +135,12 @@
int status) {}
/**
- * Callback triggered in response to {@link AdvertisingSet#periodicAdvertisingEnable}
+ * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingEnable}
* indicating result of the operation.
*
* @param advertisingSet The advertising set.
* @param status Status of the operation.
*/
- public void onPeriodicAdvertisingEnable(AdvertisingSet advertisingSet, boolean enable,
+ public void onPeriodicAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable,
int status) {}
}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index 03a01e1..7e37157 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.bluetooth.BluetoothAdapter;
import android.os.Parcel;
import android.os.Parcelable;
@@ -116,16 +117,16 @@
private final int primaryPhy;
private final int secondaryPhy;
private final boolean connectable;
+ private final boolean scannable;
private final int interval;
private final int txPowerLevel;
- private final int timeoutMillis;
- private AdvertisingSetParameters(boolean connectable, boolean isLegacy,
+ private AdvertisingSetParameters(boolean connectable, boolean scannable, boolean isLegacy,
boolean isAnonymous, boolean includeTxPower,
int primaryPhy, int secondaryPhy,
- int interval, int txPowerLevel,
- int timeoutMillis) {
+ int interval, int txPowerLevel) {
this.connectable = connectable;
+ this.scannable = scannable;
this.isLegacy = isLegacy;
this.isAnonymous = isAnonymous;
this.includeTxPower = includeTxPower;
@@ -133,11 +134,11 @@
this.secondaryPhy = secondaryPhy;
this.interval = interval;
this.txPowerLevel = txPowerLevel;
- this.timeoutMillis = timeoutMillis;
}
private AdvertisingSetParameters(Parcel in) {
connectable = in.readInt() != 0 ? true : false;
+ scannable = in.readInt() != 0 ? true : false;
isLegacy = in.readInt() != 0 ? true : false;
isAnonymous = in.readInt() != 0 ? true : false;
includeTxPower = in.readInt() != 0 ? true : false;
@@ -145,7 +146,6 @@
secondaryPhy = in.readInt();
interval = in.readInt();
txPowerLevel = in.readInt();
- timeoutMillis = in.readInt();
}
/**
@@ -154,6 +154,11 @@
public boolean isConnectable() { return connectable; }
/**
+ * Returns whether the advertisement will be scannable.
+ */
+ public boolean isScannable() { return scannable; }
+
+ /**
* Returns whether the legacy advertisement will be used.
*/
public boolean isLegacy() { return isLegacy; }
@@ -188,11 +193,6 @@
*/
public int getTxPowerLevel() { return txPowerLevel; }
- /**
- * Returns the advertising time limit in milliseconds.
- */
- public int getTimeout() { return timeoutMillis; }
-
@Override
public String toString() {
return "AdvertisingSetParameters [connectable=" + connectable
@@ -202,8 +202,7 @@
+ ", primaryPhy=" + primaryPhy
+ ", secondaryPhy=" + secondaryPhy
+ ", interval=" + interval
- + ", txPowerLevel=" + txPowerLevel
- + ", timeoutMillis=" + timeoutMillis + "]";
+ + ", txPowerLevel=" + txPowerLevel + "]";
}
@Override
@@ -214,6 +213,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(connectable ? 1 : 0);
+ dest.writeInt(scannable ? 1 : 0);
dest.writeInt(isLegacy ? 1 : 0);
dest.writeInt(isAnonymous ? 1 : 0);
dest.writeInt(includeTxPower ? 1 : 0);
@@ -221,7 +221,6 @@
dest.writeInt(secondaryPhy);
dest.writeInt(interval);
dest.writeInt(txPowerLevel);
- dest.writeInt(timeoutMillis);
}
public static final Parcelable.Creator<AdvertisingSetParameters> CREATOR =
@@ -243,6 +242,7 @@
public static final class Builder {
private boolean connectable = true;
+ private boolean scannable = true;
private boolean isLegacy = false;
private boolean isAnonymous = false;
private boolean includeTxPower = false;
@@ -250,15 +250,14 @@
private int secondaryPhy = PHY_LE_1M;
private int interval = INTERVAL_LOW;
private int txPowerLevel = TX_POWER_MEDIUM;
- private int timeoutMillis = 0;
/**
* Set whether the advertisement type should be connectable or
* non-connectable.
- * Legacy advertisements can be both connectable and scannable. Other
- * advertisements can be connectable only if not scannable.
+ * Legacy advertisements must be both connectable and scannable. Nonlegacy
+ * advertisements can be only scannable or only connectable.
* @param connectable Controls whether the advertisment type will be
- * connectable (true) or non-connectable (false).
+ * connectable (true) or nonconnectable (false).
*/
public Builder setConnectable(boolean connectable) {
this.connectable = connectable;
@@ -266,10 +265,22 @@
}
/**
+ * Set whether the advertisement type should be scannable.
+ * Legacy advertisements must be both connectable and scannable. Nonlegacy
+ * advertisements can be only scannable or only connectable.
+ * @param scannable Controls whether the advertisment type will be
+ * scannable (true) or nonscannable (false).
+ */
+ public Builder setScannable(boolean scannable) {
+ this.scannable = scannable;
+ return this;
+ }
+
+ /**
* When set to true, advertising set will advertise 4.x Spec compliant
* advertisements.
*
- * @param isLegacy wether legacy advertising mode should be used.
+ * @param isLegacy whether legacy advertising mode should be used.
*/
public Builder setLegacyMode(boolean isLegacy) {
this.isLegacy = isLegacy;
@@ -277,25 +288,25 @@
}
/**
- * Set wether advertiser address should be ommited from all packets. If this
+ * Set whether advertiser address should be ommited from all packets. If this
* mode is used, periodic advertising can't be enabled for this set.
*
* This is used only if legacy mode is not used.
*
- * @param isAnonymous wether anonymous advertising should be used.
+ * @param isAnonymous whether anonymous advertising should be used.
*/
- public Builder setAnonymouus(boolean isAnonymous) {
+ public Builder setAnonymous(boolean isAnonymous) {
this.isAnonymous = isAnonymous;
return this;
}
/**
- * Set wether TX power should be included in the extended header.
+ * Set whether TX power should be included in the extended header.
*
* This is used only if legacy mode is not used.
*
- * @param includeTxPower wether TX power should be included in extended
- * header
+ * @param includeTxPower whether TX power should be included in extended
+ * header
*/
public Builder setIncludeTxPower(boolean includeTxPower) {
this.includeTxPower = includeTxPower;
@@ -307,6 +318,8 @@
*
* This is used only if legacy mode is not used.
*
+ * Use {@link BluetoothAdapter#isLeCodedPhySupported} to determine if LE Coded PHY is
+ * supported on this device.
* @param primaryPhy Primary advertising physical channel, can only be
* {@link AdvertisingSetParameters#PHY_LE_1M} or
* {@link AdvertisingSetParameters#PHY_LE_CODED}.
@@ -325,6 +338,10 @@
*
* This is used only if legacy mode is not used.
*
+ * Use {@link BluetoothAdapter#isLeCodedPhySupported} and
+ * {@link BluetoothAdapter#isLe2MPhySupported} to determine if LE Coded PHY or 2M PHY is
+ * supported on this device.
+ *
* @param secondaryPhy Secondary advertising physical channel, can only be
* one of {@link AdvertisingSetParameters#PHY_LE_1M},
* {@link AdvertisingSetParameters#PHY_LE_2M} or
@@ -380,30 +397,38 @@
}
/**
- * Limit advertising to a given amount of time.
- * @param timeoutMillis Advertising time limit. May not exceed 180000
- * milliseconds. A value of 0 will disable the time limit.
- * @throws IllegalArgumentException If the provided timeout is over 180000
- * ms.
- */
- public Builder setTimeout(int timeoutMillis) {
- if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) {
- throw new IllegalArgumentException("timeoutMillis invalid (must be 0-" +
- LIMITED_ADVERTISING_MAX_MILLIS +
- " milliseconds)");
- }
- this.timeoutMillis = timeoutMillis;
- return this;
- }
-
- /**
* Build the {@link AdvertisingSetParameters} object.
*/
public AdvertisingSetParameters build() {
- return new AdvertisingSetParameters(connectable, isLegacy, isAnonymous,
+ if (isLegacy) {
+ if (isAnonymous) {
+ throw new IllegalArgumentException("Legacy advertising can't be anonymous");
+ }
+
+ if (connectable == true && scannable == false) {
+ throw new IllegalArgumentException(
+ "Legacy advertisement can't be connectable and non-scannable");
+ }
+
+ if (includeTxPower) {
+ throw new IllegalArgumentException(
+ "Legacy advertising can't include TX power level in header");
+ }
+ } else {
+ if (connectable && scannable) {
+ throw new IllegalArgumentException(
+ "Advertising can't be both connectable and scannable");
+ }
+
+ if (isAnonymous && connectable) {
+ throw new IllegalArgumentException(
+ "Advertising can't be both connectable and anonymous");
+ }
+ }
+
+ return new AdvertisingSetParameters(connectable, scannable, isLegacy, isAnonymous,
includeTxPower, primaryPhy,
- secondaryPhy, interval, txPowerLevel,
- timeoutMillis);
+ secondaryPhy, interval, txPowerLevel);
}
}
}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index e03c947..a9deb75 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -28,6 +28,7 @@
import android.os.RemoteException;
import android.util.Log;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -49,22 +50,23 @@
private static final String TAG = "BluetoothLeAdvertiser";
- private static final int MAX_ADVERTISING_DATA_BYTES = 31;
+ private static final int MAX_ADVERTISING_DATA_BYTES = 1650;
+ private static final int MAX_LEGACY_ADVERTISING_DATA_BYTES = 31;
// Each fields need one byte for field length and another byte for field type.
private static final int OVERHEAD_BYTES_PER_FIELD = 2;
// Flags field will be set by system.
private static final int FLAGS_FIELD_BYTES = 3;
private static final int MANUFACTURER_SPECIFIC_DATA_LENGTH = 2;
- private static final int SERVICE_DATA_UUID_LENGTH = 2;
private final IBluetoothManager mBluetoothManager;
private final Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
- private final Map<AdvertiseCallback, AdvertiseCallbackWrapper>
- mLeAdvertisers = new HashMap<AdvertiseCallback, AdvertiseCallbackWrapper>();
+ private final Map<AdvertiseCallback, AdvertisingSetCallback>
+ mLegacyAdvertisers = new HashMap<>();
private final Map<AdvertisingSetCallback, IAdvertisingSetCallback>
- advertisingSetCallbackWrappers = new HashMap<>();
- private final Map<Integer, AdvertisingSet> advertisingSets = new HashMap<>();
+ mCallbackWrappers = Collections.synchronizedMap(new HashMap<>());
+ private final Map<Integer, AdvertisingSet>
+ mAdvertisingSets = Collections.synchronizedMap(new HashMap<>());
/**
* Use BluetoothAdapter.getLeAdvertiser() instead.
@@ -109,36 +111,86 @@
public void startAdvertising(AdvertiseSettings settings,
AdvertiseData advertiseData, AdvertiseData scanResponse,
final AdvertiseCallback callback) {
- synchronized (mLeAdvertisers) {
+ synchronized (mLegacyAdvertisers) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
boolean isConnectable = settings.isConnectable();
- if (totalBytes(advertiseData, isConnectable) > MAX_ADVERTISING_DATA_BYTES ||
- totalBytes(scanResponse, false) > MAX_ADVERTISING_DATA_BYTES) {
+ if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES ||
+ totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
return;
}
- if (mLeAdvertisers.containsKey(callback)) {
+ if (mLegacyAdvertisers.containsKey(callback)) {
postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
return;
}
- IBluetoothGatt gatt;
- try {
- gatt = mBluetoothManager.getBluetoothGatt();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
- postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
- return;
+ AdvertisingSetParameters.Builder parameters = new AdvertisingSetParameters.Builder();
+ parameters.setLegacyMode(true);
+ parameters.setConnectable(isConnectable);
+ parameters.setScannable(true); // legacy advertisements we support are always scannable
+ if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_POWER) {
+ parameters.setInterval(1600); // 1s
+ } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_BALANCED) {
+ parameters.setInterval(400); // 250ms
+ } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) {
+ parameters.setInterval(160); // 100ms
}
- AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData,
- scanResponse, settings, gatt);
- wrapper.startRegisteration();
+
+ if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW) {
+ parameters.setTxPowerLevel(-21);
+ } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_LOW) {
+ parameters.setTxPowerLevel(-15);
+ } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM) {
+ parameters.setTxPowerLevel(-7);
+ } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) {
+ parameters.setTxPowerLevel(1);
+ }
+
+ int duration = 0;
+ int timeoutMillis = settings.getTimeout();
+ if (timeoutMillis > 0) {
+ duration = (timeoutMillis < 10) ? 1 : timeoutMillis/10;
+ }
+
+ AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings);
+ mLegacyAdvertisers.put(callback, wrapped);
+ startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null,
+ duration, 0, wrapped);
}
}
+ AdvertisingSetCallback wrapOldCallback(AdvertiseCallback callback, AdvertiseSettings settings) {
+ return new AdvertisingSetCallback() {
+ @Override
+ public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower,
+ int status) {
+ if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
+ postStartFailure(callback, status);
+ return;
+ }
+
+ postStartSuccess(callback, settings);
+ }
+
+ /* Legacy advertiser is disabled on timeout */
+ @Override
+ public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enabled,
+ int status) {
+ if (enabled == true) {
+ Log.e(TAG, "Legacy advertiser should be only disabled on timeout," +
+ " but was enabled!");
+ return;
+ }
+
+ stopAdvertising(callback);
+ }
+
+ };
+ }
+
/**
* Stop Bluetooth LE advertising. The {@code callback} must be the same one use in
* {@link BluetoothLeAdvertiser#startAdvertising}.
@@ -148,58 +200,214 @@
* @param callback {@link AdvertiseCallback} identifies the advertising instance to stop.
*/
public void stopAdvertising(final AdvertiseCallback callback) {
- synchronized (mLeAdvertisers) {
+ synchronized (mLegacyAdvertisers) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
- AdvertiseCallbackWrapper wrapper = mLeAdvertisers.get(callback);
+ AdvertisingSetCallback wrapper = mLegacyAdvertisers.get(callback);
if (wrapper == null) return;
- wrapper.stopAdvertising();
+
+ stopAdvertisingSet(wrapper);
}
}
/**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onNewAdvertisingSet()}.
- * <p>
- * @param parameters advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted.
- * @param scanResponse Scan response associated with the advertisement data.
- * @param periodicData Periodic advertising data.
- * @param callback Callback for advertising set.
- */
+ * Creates a new advertising set. If operation succeed, device will start advertising. This
+ * method returns immediately, the operation status is delivered through
+ * {@code callback.onAdvertisingSetStarted()}.
+ * <p>
+ * @param parameters advertising set parameters.
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags.
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
+ * not be started.
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param callback Callback for advertising set.
+ * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
+ * size, or unsupported advertising PHY is selected, or when attempt to use
+ * Periodic Advertising feature is made when it's not supported by the
+ * controller.
+ */
public void startAdvertisingSet(AdvertisingSetParameters parameters,
AdvertiseData advertiseData, AdvertiseData scanResponse,
PeriodicAdvertisingParameters periodicParameters,
AdvertiseData periodicData, AdvertisingSetCallback callback) {
- startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, callback, new Handler(Looper.getMainLooper()));
+ startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
+ periodicData, 0, 0, callback, new Handler(Looper.getMainLooper()));
}
/**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onNewAdvertisingSet()}.
- * <p>
- * @param parameters advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted.
- * @param scanResponse Scan response associated with the advertisement data.
- * @param periodicData Periodic advertising data.
- * @param callback Callback for advertising set.
- * @param handler thread upon which the callbacks will be invoked.
- */
+ * Creates a new advertising set. If operation succeed, device will start advertising. This
+ * method returns immediately, the operation status is delivered through
+ * {@code callback.onAdvertisingSetStarted()}.
+ * <p>
+ * @param parameters advertising set parameters.
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags.
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
+ * not be started.
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param callback Callback for advertising set.
+ * @param handler thread upon which the callbacks will be invoked.
+ * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
+ * size, or unsupported advertising PHY is selected, or when attempt to use
+ * Periodic Advertising feature is made when it's not supported by the
+ * controller.
+ */
public void startAdvertisingSet(AdvertisingSetParameters parameters,
AdvertiseData advertiseData, AdvertiseData scanResponse,
PeriodicAdvertisingParameters periodicParameters,
AdvertiseData periodicData, AdvertisingSetCallback callback,
Handler handler) {
- BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
+ startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
+ periodicData, 0, 0, callback, handler);
+ }
+ /**
+ * Creates a new advertising set. If operation succeed, device will start advertising. This
+ * method returns immediately, the operation status is delivered through
+ * {@code callback.onAdvertisingSetStarted()}.
+ * <p>
+ * @param parameters advertising set parameters.
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags.
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
+ * not be started.
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to
+ * 65535 (655,350 ms). 0 means advertising should continue until stopped.
+ * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
+ * controller shall attempt to send prior to terminating the extended
+ * advertising, even if the duration has not expired. Valid range is
+ * from 1 to 255. 0 means no maximum.
+ * @param callback Callback for advertising set.
+ * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
+ * size, or unsupported advertising PHY is selected, or when attempt to use
+ * Periodic Advertising feature is made when it's not supported by the
+ * controller.
+ */
+ public void startAdvertisingSet(AdvertisingSetParameters parameters,
+ AdvertiseData advertiseData, AdvertiseData scanResponse,
+ PeriodicAdvertisingParameters periodicParameters,
+ AdvertiseData periodicData, int duration,
+ int maxExtendedAdvertisingEvents,
+ AdvertisingSetCallback callback) {
+ startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
+ periodicData, duration, maxExtendedAdvertisingEvents, callback,
+ new Handler(Looper.getMainLooper()));
+ }
+
+ /**
+ * Creates a new advertising set. If operation succeed, device will start advertising. This
+ * method returns immediately, the operation status is delivered through
+ * {@code callback.onAdvertisingSetStarted()}.
+ * <p>
+ * @param parameters Advertising set parameters.
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags.
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
+ * @param periodicParameters Periodic advertisng parameters. If null, periodic advertising will
+ * not be started.
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
+ * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to
+ * 65535 (655,350 ms). 0 means advertising should continue until stopped.
+ * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
+ * controller shall attempt to send prior to terminating the extended
+ * advertising, even if the duration has not expired. Valid range is
+ * from 1 to 255. 0 means no maximum.
+ * @param callback Callback for advertising set.
+ * @param handler Thread upon which the callbacks will be invoked.
+ * @throws IllegalArgumentException When any of the data parameter exceed the maximum allowable
+ * size, or unsupported advertising PHY is selected, or when attempt to use
+ * Periodic Advertising feature is made when it's not supported by the
+ * controller, or when maxExtendedAdvertisingEvents is used on a controller
+ * that doesn't support the LE Extended Advertising
+ */
+ public void startAdvertisingSet(AdvertisingSetParameters parameters,
+ AdvertiseData advertiseData, AdvertiseData scanResponse,
+ PeriodicAdvertisingParameters periodicParameters,
+ AdvertiseData periodicData, int duration,
+ int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback,
+ Handler handler) {
+ BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
+ boolean isConnectable = parameters.isConnectable();
+ if (parameters.isLegacy()) {
+ if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
+ throw new IllegalArgumentException("Legacy advertising data too big");
+ }
+
+ if (totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
+ throw new IllegalArgumentException("Legacy scan response data too big");
+ }
+ } else {
+ boolean supportCodedPhy = mBluetoothAdapter.isLeCodedPhySupported();
+ boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported();
+ int pphy = parameters.getPrimaryPhy();
+ int sphy = parameters.getSecondaryPhy();
+ if (pphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy) {
+ throw new IllegalArgumentException("Unsupported primary PHY selected");
+ }
+
+ if ((sphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy)
+ || (sphy == AdvertisingSetParameters.PHY_LE_2M && !support2MPhy)) {
+ throw new IllegalArgumentException("Unsupported secondary PHY selected");
+ }
+
+ int maxData = mBluetoothAdapter.getLeMaximumAdvertisingDataLength();
+ if (totalBytes(advertiseData, isConnectable) > maxData) {
+ throw new IllegalArgumentException("Advertising data too big");
+ }
+
+ if (totalBytes(scanResponse, false) > maxData) {
+ throw new IllegalArgumentException("Scan response data too big");
+ }
+
+ if (totalBytes(periodicData, false) > maxData) {
+ throw new IllegalArgumentException("Periodic advertising data too big");
+ }
+
+ boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported();
+ if (periodicParameters != null && periodicParameters.getEnable() && !supportPeriodic) {
+ throw new IllegalArgumentException(
+ "Controller does not support LE Periodic Advertising");
+ }
+ }
+
+ if (maxExtendedAdvertisingEvents < 0 || maxExtendedAdvertisingEvents > 255) {
+ throw new IllegalArgumentException(
+ "maxExtendedAdvertisingEvents out of range: " + maxExtendedAdvertisingEvents);
+ }
+
+ if (maxExtendedAdvertisingEvents != 0 &&
+ !mBluetoothAdapter.isLePeriodicAdvertisingSupported()) {
+ throw new IllegalArgumentException(
+ "Can't use maxExtendedAdvertisingEvents with controller that don't support " +
+ "LE Extended Advertising");
+ }
+
+ if (duration < 0 || duration > 65535) {
+ throw new IllegalArgumentException("duration out of range: " + duration);
+ }
+
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
@@ -209,11 +417,14 @@
}
IAdvertisingSetCallback wrapped = wrap(callback, handler);
- advertisingSetCallbackWrappers.put(callback, wrapped);
+ if (mCallbackWrappers.putIfAbsent(callback, wrapped) != null) {
+ throw new IllegalArgumentException(
+ "callback instance already associated with advertising");
+ }
try {
gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, wrapped);
+ periodicData, duration, maxExtendedAdvertisingEvents, wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to start advertising set - ", e);
throw new IllegalStateException("Failed to start advertising set");
@@ -229,10 +440,9 @@
throw new IllegalArgumentException("callback cannot be null");
}
- IAdvertisingSetCallback wrapped = advertisingSetCallbackWrappers.remove(callback);
+ IAdvertisingSetCallback wrapped = mCallbackWrappers.remove(callback);
if (wrapped == null) {
- throw new IllegalArgumentException(
- "callback does not represent valid registered callback.");
+ return;
}
IBluetoothGatt gatt;
@@ -251,7 +461,9 @@
* @hide
*/
public void cleanup() {
- mLeAdvertisers.clear();
+ mLegacyAdvertisers.clear();
+ mCallbackWrappers.clear();
+ mAdvertisingSets.clear();
}
// Compute the size of advertisement data or scan resp
@@ -289,7 +501,8 @@
}
}
for (ParcelUuid uuid : data.getServiceData().keySet()) {
- size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH
+ int uuidLen = BluetoothUuid.uuidToBytes(uuid).length;
+ size += OVERHEAD_BYTES_PER_FIELD + uuidLen
+ byteLength(data.getServiceData().get(uuid));
}
for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) {
@@ -311,246 +524,117 @@
IAdvertisingSetCallback wrap(AdvertisingSetCallback callback, Handler handler) {
return new IAdvertisingSetCallback.Stub() {
- public void onAdvertisingSetStarted(int advertiserId, int status) {
+ @Override
+ public void onAdvertisingSetStarted(int advertiserId, int txPower, int status) {
handler.post(new Runnable() {
@Override
public void run() {
if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
- callback.onAdvertisingSetStarted(null, status);
- advertisingSetCallbackWrappers.remove(callback);
+ callback.onAdvertisingSetStarted(null, 0, status);
+ mCallbackWrappers.remove(callback);
return;
}
AdvertisingSet advertisingSet =
new AdvertisingSet(advertiserId, mBluetoothManager);
- advertisingSets.put(advertiserId, advertisingSet);
- callback.onAdvertisingSetStarted(advertisingSet, status);
+ mAdvertisingSets.put(advertiserId, advertisingSet);
+ callback.onAdvertisingSetStarted(advertisingSet, txPower, status);
}
});
}
+ @Override
public void onAdvertisingSetStopped(int advertiserId) {
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingSetStopped(advertisingSet);
- advertisingSets.remove(advertiserId);
- advertisingSetCallbackWrappers.remove(callback);
+ mAdvertisingSets.remove(advertiserId);
+ mCallbackWrappers.remove(callback);
}
});
}
+ @Override
public void onAdvertisingEnabled(int advertiserId, boolean enabled, int status) {
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingEnabled(advertisingSet, enabled, status);
}
});
}
+ @Override
public void onAdvertisingDataSet(int advertiserId, int status) {
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingDataSet(advertisingSet, status);
}
});
}
+ @Override
public void onScanResponseDataSet(int advertiserId, int status) {
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onScanResponseDataSet(advertisingSet, status);
}
});
}
- public void onAdvertisingParametersUpdated(int advertiserId, int status) {
+ @Override
+ public void onAdvertisingParametersUpdated(int advertiserId, int txPower, int status) {
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
- callback.onAdvertisingParametersUpdated(advertisingSet, status);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
+ callback.onAdvertisingParametersUpdated(advertisingSet, txPower, status);
}
});
}
+ @Override
public void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) {
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onPeriodicAdvertisingParametersUpdated(advertisingSet, status);
}
});
}
+ @Override
public void onPeriodicAdvertisingDataSet(int advertiserId, int status) {
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onPeriodicAdvertisingDataSet(advertisingSet, status);
}
});
}
- public void onPeriodicAdvertisingEnable(int advertiserId, boolean enable, int status) {
+ @Override
+ public void onPeriodicAdvertisingEnabled(int advertiserId, boolean enable, int status) {
handler.post(new Runnable() {
@Override
public void run() {
- AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
- callback.onPeriodicAdvertisingEnable(advertisingSet, enable, status);
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
+ callback.onPeriodicAdvertisingEnabled(advertisingSet, enable, status);
}
});
}
};
}
- /**
- * Bluetooth GATT interface callbacks for advertising.
- */
- private class AdvertiseCallbackWrapper extends IAdvertiserCallback.Stub {
- private static final int LE_CALLBACK_TIMEOUT_MILLIS = 2000;
- private final AdvertiseCallback mAdvertiseCallback;
- private final AdvertiseData mAdvertisement;
- private final AdvertiseData mScanResponse;
- private final AdvertiseSettings mSettings;
- private final IBluetoothGatt mBluetoothGatt;
-
- // mAdvertiserId -1: not registered
- // -2: advertise stopped or registration timeout
- // >=0: registered and advertising started
- private int mAdvertiserId;
- private boolean mIsAdvertising = false;
- private int registrationError = AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR;
-
- public AdvertiseCallbackWrapper(AdvertiseCallback advertiseCallback,
- AdvertiseData advertiseData, AdvertiseData scanResponse,
- AdvertiseSettings settings,
- IBluetoothGatt bluetoothGatt) {
- mAdvertiseCallback = advertiseCallback;
- mAdvertisement = advertiseData;
- mScanResponse = scanResponse;
- mSettings = settings;
- mBluetoothGatt = bluetoothGatt;
- mAdvertiserId = -1;
- }
-
- public void startRegisteration() {
- synchronized (this) {
- if (mAdvertiserId == -2) return;
-
- try {
- mBluetoothGatt.registerAdvertiser(this);
- wait(LE_CALLBACK_TIMEOUT_MILLIS);
- } catch (InterruptedException | RemoteException e) {
- Log.e(TAG, "Failed to start registeration", e);
- }
- if (mAdvertiserId >= 0 && mIsAdvertising) {
- mLeAdvertisers.put(mAdvertiseCallback, this);
- } else if (mAdvertiserId < 0) {
-
- // Registration timeout, reset mClientIf to -2 so no subsequent operations can
- // proceed.
- if (mAdvertiserId == -1) mAdvertiserId = -2;
- // Post internal error if registration failed.
- postStartFailure(mAdvertiseCallback, registrationError);
- } else {
- // Unregister application if it's already registered but advertise failed.
- try {
- mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
- mAdvertiserId = -2;
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception when unregistering", e);
- }
- }
- }
- }
-
- public void stopAdvertising() {
- synchronized (this) {
- try {
- mBluetoothGatt.stopMultiAdvertising(mAdvertiserId);
- wait(LE_CALLBACK_TIMEOUT_MILLIS);
- } catch (InterruptedException | RemoteException e) {
- Log.e(TAG, "Failed to stop advertising", e);
- }
- // Advertise callback should have been removed from LeAdvertisers when
- // onMultiAdvertiseCallback was called. In case onMultiAdvertiseCallback is never
- // invoked and wait timeout expires, remove callback here.
- if (mLeAdvertisers.containsKey(mAdvertiseCallback)) {
- mLeAdvertisers.remove(mAdvertiseCallback);
- }
- }
- }
-
- /**
- * Advertiser interface registered - app is ready to go
- */
- @Override
- public void onAdvertiserRegistered(int status, int advertiserId) {
- Log.d(TAG, "onAdvertiserRegistered() - status=" + status + " advertiserId=" + advertiserId);
- synchronized (this) {
- if (status == BluetoothGatt.GATT_SUCCESS) {
- try {
- if (mAdvertiserId == -2) {
- // Registration succeeds after timeout, unregister advertiser.
- mBluetoothGatt.unregisterAdvertiser(advertiserId);
- } else {
- mAdvertiserId = advertiserId;
- mBluetoothGatt.startMultiAdvertising(mAdvertiserId, mAdvertisement,
- mScanResponse, mSettings);
- }
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "failed to start advertising", e);
- }
- } else if (status == AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) {
- registrationError = status;
- }
- // Registration failed.
- mAdvertiserId = -2;
- notifyAll();
- }
- }
-
- @Override
- public void onMultiAdvertiseCallback(int status, boolean isStart,
- AdvertiseSettings settings) {
- synchronized (this) {
- if (isStart) {
- if (status == AdvertiseCallback.ADVERTISE_SUCCESS) {
- // Start success
- mIsAdvertising = true;
- postStartSuccess(mAdvertiseCallback, settings);
- } else {
- // Start failure.
- postStartFailure(mAdvertiseCallback, status);
- }
- } else {
- // unregister advertiser for stop.
- try {
- mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
- mAdvertiserId = -2;
- mIsAdvertising = false;
- mLeAdvertisers.remove(mAdvertiseCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception when unregistering", e);
- }
- }
- notifyAll();
- }
-
- }
- }
-
private void postStartFailure(final AdvertiseCallback callback, final int error) {
mHandler.post(new Runnable() {
@Override
diff --git a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
index 4b0a111..2c9f4ba 100644
--- a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
+++ b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
@@ -20,13 +20,13 @@
* @hide
*/
oneway interface IAdvertisingSetCallback {
- void onAdvertisingSetStarted(in int advertiserId, in int status);
+ void onAdvertisingSetStarted(in int advertiserId, in int tx_power, in int status);
void onAdvertisingSetStopped(in int advertiserId);
void onAdvertisingEnabled(in int advertiserId, in boolean enable, in int status);
void onAdvertisingDataSet(in int advertiserId, in int status);
void onScanResponseDataSet(in int advertiserId, in int status);
- void onAdvertisingParametersUpdated(in int advertiserId, in int status);
+ void onAdvertisingParametersUpdated(in int advertiserId, in int tx_power, in int status);
void onPeriodicAdvertisingParametersUpdated(in int advertiserId, in int status);
void onPeriodicAdvertisingDataSet(in int advertiserId, in int status);
- void onPeriodicAdvertisingEnable(in int advertiserId, in boolean enable, in int status);
+ void onPeriodicAdvertisingEnabled(in int advertiserId, in boolean enable, in int status);
}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
index 6616231..364b575 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
@@ -23,6 +23,7 @@
* advertising operation status.
*
* @see PeriodicAdvertisingManager#createSync
+ * @hide
*/
public abstract class PeriodicAdvertisingCallback {
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
index 12c8a8c..d9c2d88 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
@@ -37,6 +37,7 @@
* <p>
* <b>Note:</b> Most of the methods here require
* {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ * @hide
*/
public final class PeriodicAdvertisingManager {
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
index ebc92bd..149540c 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
@@ -93,7 +93,7 @@
private int interval = INTERVAL_MAX;
/**
- * Set wether the Periodic Advertising should be enabled for this set.
+ * Set whether the Periodic Advertising should be enabled for this set.
*/
public Builder setEnable(boolean enable) {
this.enable = enable;
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
index 3ff4ca5..51b93cb 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
@@ -24,6 +24,7 @@
/**
* PeriodicAdvertisingReport for Bluetooth LE synchronized advertising.
+ * @hide
*/
public final class PeriodicAdvertisingReport implements Parcelable {
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
index 583ddd2..745cd16 100644
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ b/core/java/android/bluetooth/le/ScanResult.java
@@ -67,12 +67,12 @@
public static final int SID_NOT_PRESENT = 0xFF;
/**
- * Mask for checking wether event type represents legacy advertisement.
+ * Mask for checking whether event type represents legacy advertisement.
*/
private static final int ET_LEGACY_MASK = 0x10;
/**
- * Mask for checking wether event type represents connectable advertisement.
+ * Mask for checking whether event type represents connectable advertisement.
*/
private static final int ET_CONNECTABLE_MASK = 0x01;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b7876d9..2ce22b4 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1083,18 +1083,7 @@
* @hide
*/
public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
- /**
- * Activity action: Activate the current SIM card. If SIM cards do not require activation,
- * sending this intent is a no-op.
- * <p>Input: No data should be specified. get*Extra may have an optional
- * {@link #EXTRA_SIM_ACTIVATION_RESPONSE} field containing a PendingIntent through which to
- * send the activation result.
- * <p>Output: nothing.
- * @hide
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SIM_ACTIVATION_REQUEST =
- "android.intent.action.SIM_ACTIVATION_REQUEST";
+
/**
* Activity Action: Main entry point for carrier setup apps.
* <p>Carrier apps that provide an implementation for this action may be invoked to configure
diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl
new file mode 100644
index 0000000..0aa3ce6
--- /dev/null
+++ b/core/java/android/net/IIpSecService.aidl
@@ -0,0 +1,46 @@
+/*
+** Copyright 2017, 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.net;
+
+import android.net.Network;
+import android.net.IpSecConfig;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * @hide
+ */
+interface IIpSecService
+{
+ Bundle reserveSecurityParameterIndex(
+ int direction, in String remoteAddress, int requestedSpi, in IBinder binder);
+
+ void releaseSecurityParameterIndex(int resourceId);
+
+ Bundle openUdpEncapsulationSocket(int port, in IBinder binder);
+
+ void closeUdpEncapsulationSocket(in ParcelFileDescriptor socket);
+
+ Bundle createTransportModeTransform(in IpSecConfig c, in IBinder binder);
+
+ void deleteTransportModeTransform(int transformId);
+
+ void applyTransportModeTransform(in ParcelFileDescriptor socket, int transformId);
+
+ void removeTransportModeTransform(in ParcelFileDescriptor socket, int transformId);
+}
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index da5cb37..7fea4a2 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -164,6 +164,8 @@
private static boolean isTruncationLengthValid(String algo, int truncLenBits) {
switch (algo) {
+ case ALGO_CRYPT_AES_CBC:
+ return (truncLenBits == 128 || truncLenBits == 192 || truncLenBits == 256);
case ALGO_AUTH_HMAC_MD5:
return (truncLenBits >= 96 && truncLenBits <= 128);
case ALGO_AUTH_HMAC_SHA1:
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index b58bf42..13dc19f 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -23,7 +23,7 @@
/** @hide */
public final class IpSecConfig implements Parcelable {
- private static final String TAG = IpSecConfig.class.getSimpleName();
+ private static final String TAG = "IpSecConfig";
//MODE_TRANSPORT or MODE_TUNNEL
int mode;
@@ -43,13 +43,13 @@
int spi;
// Encryption Algorithm
- IpSecAlgorithm encryptionAlgo;
+ IpSecAlgorithm encryption;
// Authentication Algorithm
- IpSecAlgorithm authenticationAlgo;
+ IpSecAlgorithm authentication;
}
- Flow[] flow = new Flow[2];
+ Flow[] flow = new Flow[] {new Flow(), new Flow()};
// For tunnel mode IPv4 UDP Encapsulation
// IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
@@ -57,17 +57,15 @@
int encapLocalPort;
int encapRemotePort;
- // An optional protocol to match with the selector
- int selectorProto;
-
- // A bitmask of FEATURE_* indicating which of the fields
- // of this class are valid.
- long features;
-
// An interval, in seconds between the NattKeepalive packets
int nattKeepaliveInterval;
- public InetAddress getLocalIp() {
+ // Transport or Tunnel
+ public int getMode() {
+ return mode;
+ }
+
+ public InetAddress getLocalAddress() {
return localAddress;
}
@@ -75,19 +73,19 @@
return flow[direction].spi;
}
- public InetAddress getRemoteIp() {
+ public InetAddress getRemoteAddress() {
return remoteAddress;
}
- public IpSecAlgorithm getEncryptionAlgo(int direction) {
- return flow[direction].encryptionAlgo;
+ public IpSecAlgorithm getEncryption(int direction) {
+ return flow[direction].encryption;
}
- public IpSecAlgorithm getAuthenticationAlgo(int direction) {
- return flow[direction].authenticationAlgo;
+ public IpSecAlgorithm getAuthentication(int direction) {
+ return flow[direction].authentication;
}
- Network getNetwork() {
+ public Network getNetwork() {
return network;
}
@@ -103,18 +101,10 @@
return encapRemotePort;
}
- public int getSelectorProto() {
- return selectorProto;
- }
-
- int getNattKeepaliveInterval() {
+ public int getNattKeepaliveInterval() {
return nattKeepaliveInterval;
}
- public boolean hasProperty(int featureBits) {
- return (features & featureBits) == featureBits;
- }
-
// Parcelable Methods
@Override
@@ -124,31 +114,25 @@
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeLong(features);
// TODO: Use a byte array or other better method for storing IPs that can also include scope
out.writeString((localAddress != null) ? localAddress.getHostAddress() : null);
// TODO: Use a byte array or other better method for storing IPs that can also include scope
out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null);
out.writeParcelable(network, flags);
out.writeInt(flow[IpSecTransform.DIRECTION_IN].spi);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryptionAlgo, flags);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authenticationAlgo, flags);
+ out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags);
+ out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags);
out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spi);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryptionAlgo, flags);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authenticationAlgo, flags);
+ out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags);
+ out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags);
out.writeInt(encapType);
out.writeInt(encapLocalPort);
out.writeInt(encapRemotePort);
- out.writeInt(selectorProto);
}
// Package Private: Used by the IpSecTransform.Builder;
// there should be no public constructor for this object
- IpSecConfig() {
- flow[IpSecTransform.DIRECTION_IN].spi = 0;
- flow[IpSecTransform.DIRECTION_OUT].spi = 0;
- nattKeepaliveInterval = 0; //FIXME constant
- }
+ IpSecConfig() {}
private static InetAddress readInetAddressFromParcel(Parcel in) {
String addrString = in.readString();
@@ -164,24 +148,22 @@
}
private IpSecConfig(Parcel in) {
- features = in.readLong();
localAddress = readInetAddressFromParcel(in);
remoteAddress = readInetAddressFromParcel(in);
network = (Network) in.readParcelable(Network.class.getClassLoader());
flow[IpSecTransform.DIRECTION_IN].spi = in.readInt();
- flow[IpSecTransform.DIRECTION_IN].encryptionAlgo =
+ flow[IpSecTransform.DIRECTION_IN].encryption =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_IN].authenticationAlgo =
+ flow[IpSecTransform.DIRECTION_IN].authentication =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
flow[IpSecTransform.DIRECTION_OUT].spi = in.readInt();
- flow[IpSecTransform.DIRECTION_OUT].encryptionAlgo =
+ flow[IpSecTransform.DIRECTION_OUT].encryption =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_OUT].authenticationAlgo =
+ flow[IpSecTransform.DIRECTION_OUT].authentication =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
encapType = in.readInt();
encapLocalPort = in.readInt();
encapRemotePort = in.readInt();
- selectorProto = in.readInt();
}
public static final Parcelable.Creator<IpSecConfig> CREATOR =
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 2c544e9..6852beb 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -17,10 +17,11 @@
import static com.android.internal.util.Preconditions.checkNotNull;
-import android.annotation.SystemApi;
-import android.content.Context;
-import android.os.INetworkManagementService;
+import android.annotation.NonNull;
+import android.os.Binder;
+import android.os.Bundle;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.util.AndroidException;
import dalvik.system.CloseGuard;
import java.io.FileDescriptor;
@@ -41,6 +42,29 @@
private static final String TAG = "IpSecManager";
/**
+ * The Security Parameter Index, SPI, 0 indicates an unknown or invalid index.
+ *
+ * <p>No IPsec packet may contain an SPI of 0.
+ */
+ public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
+
+ /** @hide */
+ public interface Status {
+ public static final int OK = 0;
+ public static final int RESOURCE_UNAVAILABLE = 1;
+ public static final int SPI_UNAVAILABLE = 2;
+ }
+
+ /** @hide */
+ public static final String KEY_STATUS = "status";
+ /** @hide */
+ public static final String KEY_RESOURCE_ID = "resourceId";
+ /** @hide */
+ public static final String KEY_SPI = "spi";
+ /** @hide */
+ public static final int INVALID_RESOURCE_ID = 0;
+
+ /**
* Indicates that the combination of remote InetAddress and SPI was non-unique for a given
* request. If encountered, selection of a new SPI is required before a transform may be
* created. Note, this should happen very rarely if the SPI is chosen to be sufficiently random
@@ -79,42 +103,30 @@
}
}
- private final Context mContext;
- private final INetworkManagementService mService;
+ private final IIpSecService mService;
public static final class SecurityParameterIndex implements AutoCloseable {
- private final Context mContext;
- private final InetAddress mDestinationAddress;
+ private final IIpSecService mService;
+ private final InetAddress mRemoteAddress;
private final CloseGuard mCloseGuard = CloseGuard.get();
- private int mSpi;
+ private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
+ private int mResourceId;
/** Return the underlying SPI held by this object */
public int getSpi() {
return mSpi;
}
- private SecurityParameterIndex(Context context, InetAddress destinationAddress, int spi)
- throws ResourceUnavailableException, SpiUnavailableException {
- mContext = context;
- mDestinationAddress = destinationAddress;
- mSpi = spi;
- mCloseGuard.open("open");
- }
-
/**
* Release an SPI that was previously reserved.
*
- * <p>Release an SPI for use by other users in the system. This will fail if the SPI is
- * currently in use by an IpSecTransform.
- *
- * @param destinationAddress SPIs must be unique for each combination of SPI and destination
- * address. Thus, the destinationAddress to which the SPI will communicate must be
- * supplied.
- * @param spi the previously reserved SPI to be freed.
+ * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is
+ * applied to an IpSecTransform, it will become unusable for future transforms but should
+ * still be closed to ensure system resources are released.
*/
@Override
public void close() {
- mSpi = INVALID_SECURITY_PARAMETER_INDEX; // TODO: Invalid SPI
+ mSpi = INVALID_SECURITY_PARAMETER_INDEX;
mCloseGuard.close();
}
@@ -126,23 +138,61 @@
close();
}
+
+ private SecurityParameterIndex(
+ @NonNull IIpSecService service, int direction, InetAddress remoteAddress, int spi)
+ throws ResourceUnavailableException, SpiUnavailableException {
+ mService = service;
+ mRemoteAddress = remoteAddress;
+ try {
+ Bundle result =
+ mService.reserveSecurityParameterIndex(
+ direction, remoteAddress.getHostAddress(), spi, new Binder());
+
+ if (result == null) {
+ throw new NullPointerException("Received null response from IpSecService");
+ }
+
+ int status = result.getInt(KEY_STATUS);
+ switch (status) {
+ case Status.OK:
+ break;
+ case Status.RESOURCE_UNAVAILABLE:
+ throw new ResourceUnavailableException(
+ "No more SPIs may be allocated by this requester.");
+ case Status.SPI_UNAVAILABLE:
+ throw new SpiUnavailableException("Requested SPI is unavailable", spi);
+ default:
+ throw new RuntimeException(
+ "Unknown status returned by IpSecService: " + status);
+ }
+ mSpi = result.getInt(KEY_SPI);
+ mResourceId = result.getInt(KEY_RESOURCE_ID);
+
+ if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) {
+ throw new RuntimeException("Invalid SPI returned by IpSecService: " + status);
+ }
+
+ if (mResourceId == INVALID_RESOURCE_ID) {
+ throw new RuntimeException(
+ "Invalid Resource ID returned by IpSecService: " + status);
+ }
+
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ mCloseGuard.open("open");
+ }
}
/**
- * The Security Parameter Index, SPI, 0 indicates an unknown or invalid index.
- *
- * <p>No IPsec packet may contain an SPI of 0.
- */
- public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
-
- /**
- * Reserve an SPI for traffic bound towards the specified destination address.
+ * Reserve an SPI for traffic bound towards the specified remote address.
*
* <p>If successful, this SPI is guaranteed available until released by a call to {@link
* SecurityParameterIndex#close()}.
*
- * @param destinationAddress SPIs must be unique for each combination of SPI and destination
- * address.
+ * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
+ * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress.
* @param requestedSpi the requested SPI, or '0' to allocate a random SPI.
* @return the reserved SecurityParameterIndex
* @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
@@ -150,9 +200,9 @@
* @throws SpiUnavailableException indicating that a particular SPI cannot be reserved
*/
public SecurityParameterIndex reserveSecurityParameterIndex(
- InetAddress destinationAddress, int requestedSpi)
+ int direction, InetAddress remoteAddress, int requestedSpi)
throws SpiUnavailableException, ResourceUnavailableException {
- return new SecurityParameterIndex(mContext, destinationAddress, requestedSpi);
+ return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi);
}
/**
@@ -190,7 +240,13 @@
}
/* Call down to activate a transform */
- private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {}
+ private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
+ try {
+ mService.applyTransportModeTransform(pfd, transform.getResourceId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/**
* Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to
@@ -203,7 +259,6 @@
* @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
* @hide
*/
- @SystemApi
public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
/**
@@ -235,7 +290,13 @@
}
/* Call down to activate a transform */
- private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {}
+ private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
+ try {
+ mService.removeTransportModeTransform(pfd, transform.getResourceId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/**
* Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of
@@ -248,7 +309,6 @@
* network
* @hide
*/
- @SystemApi
public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
/**
@@ -260,19 +320,19 @@
*/
public static final class UdpEncapsulationSocket implements AutoCloseable {
private final FileDescriptor mFd;
- private final Context mContext;
+ private final IIpSecService mService;
private final CloseGuard mCloseGuard = CloseGuard.get();
- private UdpEncapsulationSocket(Context context, int port)
+ private UdpEncapsulationSocket(@NonNull IIpSecService service, int port)
throws ResourceUnavailableException {
- mContext = context;
+ mService = service;
mCloseGuard.open("constructor");
// TODO: go down to the kernel and get a socket on the specified
mFd = new FileDescriptor();
}
- private UdpEncapsulationSocket(Context context) throws ResourceUnavailableException {
- mContext = context;
+ private UdpEncapsulationSocket(IIpSecService service) throws ResourceUnavailableException {
+ mService = service;
mCloseGuard.open("constructor");
// TODO: go get a random socket on a random port
mFd = new FileDescriptor();
@@ -339,7 +399,7 @@
public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
throws IOException, ResourceUnavailableException {
// Temporary code
- return new UdpEncapsulationSocket(mContext, port);
+ return new UdpEncapsulationSocket(mService, port);
}
/**
@@ -363,7 +423,7 @@
public UdpEncapsulationSocket openUdpEncapsulationSocket()
throws IOException, ResourceUnavailableException {
// Temporary code
- return new UdpEncapsulationSocket(mContext);
+ return new UdpEncapsulationSocket(mService);
}
/**
@@ -372,8 +432,7 @@
* @param context the application context for this manager
* @hide
*/
- public IpSecManager(Context context, INetworkManagementService service) {
- mContext = checkNotNull(context, "missing context");
+ public IpSecManager(IIpSecService service) {
mService = checkNotNull(service, "missing service");
}
}
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index d6dd28be..801e98c 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -15,11 +15,21 @@
*/
package android.net;
+import static android.net.IpSecManager.INVALID_RESOURCE_ID;
+import static android.net.IpSecManager.KEY_RESOURCE_ID;
+import static android.net.IpSecManager.KEY_STATUS;
+
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.Context;
-import android.system.ErrnoException;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Log;
+import com.android.internal.util.Preconditions;
import dalvik.system.CloseGuard;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -86,39 +96,64 @@
@Retention(RetentionPolicy.SOURCE)
public @interface EncapType {}
- /**
- * Sentinel for an invalid transform (means that this transform is inactive).
- *
- * @hide
- */
- public static final int INVALID_TRANSFORM_ID = -1;
-
private IpSecTransform(Context context, IpSecConfig config) {
mContext = context;
mConfig = config;
- mTransformId = INVALID_TRANSFORM_ID;
+ mResourceId = INVALID_RESOURCE_ID;
+ }
+
+ private IIpSecService getIpSecService() {
+ IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE);
+ if (b == null) {
+ throw new RemoteException("Failed to connect to IpSecService")
+ .rethrowAsRuntimeException();
+ }
+
+ return IIpSecService.Stub.asInterface(b);
+ }
+
+ private void checkResultStatusAndThrow(int status)
+ throws IOException, IpSecManager.ResourceUnavailableException,
+ IpSecManager.SpiUnavailableException {
+ switch (status) {
+ case IpSecManager.Status.OK:
+ return;
+ // TODO: Pass Error string back from bundle so that errors can be more specific
+ case IpSecManager.Status.RESOURCE_UNAVAILABLE:
+ throw new IpSecManager.ResourceUnavailableException(
+ "Failed to allocate a new IpSecTransform");
+ case IpSecManager.Status.SPI_UNAVAILABLE:
+ Log.wtf(TAG, "Attempting to use an SPI that was somehow not reserved");
+ // Fall through
+ default:
+ throw new IllegalStateException(
+ "Failed to Create a Transform with status code " + status);
+ }
}
private IpSecTransform activate()
throws IOException, IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException {
- int transformId;
synchronized (this) {
- //try {
- transformId = INVALID_TRANSFORM_ID;
- //} catch (RemoteException e) {
- // throw e.rethrowFromSystemServer();
- //}
+ try {
+ IIpSecService svc = getIpSecService();
+ Bundle result = svc.createTransportModeTransform(mConfig, new Binder());
+ int status = result.getInt(KEY_STATUS);
+ checkResultStatusAndThrow(status);
+ mResourceId = result.getInt(KEY_RESOURCE_ID, INVALID_RESOURCE_ID);
- if (transformId < 0) {
- throw new ErrnoException("addTransform", -transformId).rethrowAsIOException();
+ /* Keepalive will silently fail if not needed by the config; but, if needed and
+ * it fails to start, we need to bail because a transform will not be reliable
+ * to use if keepalive is expected to offload and fails.
+ */
+ // FIXME: if keepalive fails, we need to fail spectacularly
+ startKeepalive(mContext);
+ Log.d(TAG, "Added Transform with Id " + mResourceId);
+ mCloseGuard.open("build");
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
}
-
- startKeepalive(mContext); // Will silently fail if not required
- mTransformId = transformId;
- Log.d(TAG, "Added Transform with Id " + transformId);
}
- mCloseGuard.open("build");
return this;
}
@@ -133,21 +168,27 @@
* transform is no longer needed.
*/
public void close() {
- Log.d(TAG, "Removing Transform with Id " + mTransformId);
+ Log.d(TAG, "Removing Transform with Id " + mResourceId);
// Always safe to attempt cleanup
- if (mTransformId == INVALID_TRANSFORM_ID) {
+ if (mResourceId == INVALID_RESOURCE_ID) {
+ mCloseGuard.close();
return;
}
- //try {
- stopKeepalive();
- //} catch (RemoteException e) {
- // transform.setTransformId(transformId);
- // throw e.rethrowFromSystemServer();
- //} finally {
- mTransformId = INVALID_TRANSFORM_ID;
- //}
- mCloseGuard.close();
+ try {
+ /* Order matters here because the keepalive is best-effort but could fail in some
+ * horrible way to be removed if the wifi (or cell) subsystem has crashed, and we
+ * still want to clear out the transform.
+ */
+ IIpSecService svc = getIpSecService();
+ svc.deleteTransportModeTransform(mResourceId);
+ stopKeepalive();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ } finally {
+ mResourceId = INVALID_RESOURCE_ID;
+ mCloseGuard.close();
+ }
}
@Override
@@ -164,7 +205,7 @@
}
private final IpSecConfig mConfig;
- private int mTransformId;
+ private int mResourceId;
private final Context mContext;
private final CloseGuard mCloseGuard = CloseGuard.get();
private ConnectivityManager.PacketKeepalive mKeepalive;
@@ -200,6 +241,7 @@
/* Package */
void startKeepalive(Context c) {
+ // FIXME: NO_KEEPALIVE needs to be a constant
if (mConfig.getNattKeepaliveInterval() == 0) {
return;
}
@@ -208,7 +250,7 @@
(ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
if (mKeepalive != null) {
- Log.e(TAG, "Keepalive already started for this IpSecTransform.");
+ Log.wtf(TAG, "Keepalive already started for this IpSecTransform.");
return;
}
@@ -218,10 +260,11 @@
mConfig.getNetwork(),
mConfig.getNattKeepaliveInterval(),
mKeepaliveCallback,
- mConfig.getLocalIp(),
+ mConfig.getLocalAddress(),
mConfig.getEncapLocalPort(),
- mConfig.getRemoteIp());
+ mConfig.getRemoteAddress());
try {
+ // FIXME: this is still a horrible way to fudge the synchronous callback
mKeepaliveSyncLock.wait(2000);
} catch (InterruptedException e) {
}
@@ -232,6 +275,11 @@
}
/* Package */
+ int getResourceId() {
+ return mResourceId;
+ }
+
+ /* Package */
void stopKeepalive() {
if (mKeepalive == null) {
return;
@@ -247,16 +295,6 @@
}
}
- /* Package */
- void setTransformId(int transformId) {
- mTransformId = transformId;
- }
-
- /* Package */
- int getTransformId() {
- return mTransformId;
- }
-
/**
* Builder object to facilitate the creation of IpSecTransform objects.
*
@@ -280,7 +318,7 @@
*/
public IpSecTransform.Builder setEncryption(
@TransformDirection int direction, IpSecAlgorithm algo) {
- mConfig.flow[direction].encryptionAlgo = algo;
+ mConfig.flow[direction].encryption = algo;
return this;
}
@@ -295,7 +333,7 @@
*/
public IpSecTransform.Builder setAuthentication(
@TransformDirection int direction, IpSecAlgorithm algo) {
- mConfig.flow[direction].authenticationAlgo = algo;
+ mConfig.flow[direction].authentication = algo;
return this;
}
@@ -305,32 +343,9 @@
* given destination address.
*
* <p>Care should be chosen when selecting an SPI to ensure that is is as unique as
- * possible. Random number generation is a reasonable approach to selecting an SPI. For
- * outbound SPIs, they must be reserved by calling {@link
- * IpSecManager#reserveSecurityParameterIndex(InetAddress, int)}. Otherwise, Transforms will
- * fail to build.
- *
- * <p>Unless an SPI is set for a given direction, traffic in that direction will be
- * sent/received without any IPsec applied.
- *
- * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
- * @param spi a unique 32-bit integer to identify transformed traffic
- */
- public IpSecTransform.Builder setSpi(@TransformDirection int direction, int spi) {
- mConfig.flow[direction].spi = spi;
- return this;
- }
-
- /**
- * Set the SPI, which uniquely identifies a particular IPsec session from others. Because
- * IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a
- * given destination address.
- *
- * <p>Care should be chosen when selecting an SPI to ensure that is is as unique as
- * possible. Random number generation is a reasonable approach to selecting an SPI. For
- * outbound SPIs, they must be reserved by calling {@link
- * IpSecManager#reserveSecurityParameterIndex(InetAddress, int)}. Otherwise, Transforms will
- * fail to activate.
+ * possible. To reserve a value call {@link IpSecManager#reserveSecurityParameterIndex(int,
+ * InetAddress, int)}. Otherwise, SPI collisions would prevent a transform from being
+ * activated. IpSecManager#reserveSecurityParameterIndex(int, InetAddres$s, int)}.
*
* <p>Unless an SPI is set for a given direction, traffic in that direction will be
* sent/received without any IPsec applied.
@@ -341,6 +356,8 @@
*/
public IpSecTransform.Builder setSpi(
@TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) {
+ // TODO: convert to using the resource Id of the SPI. Then build() can validate
+ // the owner in the IpSecService
mConfig.flow[direction].spi = spi.getSpi();
return this;
}
@@ -447,7 +464,6 @@
* properties is invalid.
* @hide
*/
- @SystemApi
public IpSecTransform buildTunnelModeTransform(
InetAddress localAddress, InetAddress remoteAddress) {
//FIXME: argument validation here
@@ -463,7 +479,8 @@
*
* @param context current Context
*/
- public Builder(Context context) {
+ public Builder(@NonNull Context context) {
+ Preconditions.checkNotNull(context);
mContext = context;
mConfig = new IpSecConfig();
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 8e24caf..bd8af4d 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -428,14 +428,13 @@
*/
public static boolean contains(File dir, File file) {
if (dir == null || file == null) return false;
+ return contains(dir.getAbsolutePath(), file.getAbsolutePath());
+ }
- String dirPath = dir.getAbsolutePath();
- String filePath = file.getAbsolutePath();
-
+ public static boolean contains(String dirPath, String filePath) {
if (dirPath.equals(filePath)) {
return true;
}
-
if (!dirPath.endsWith("/")) {
dirPath += "/";
}
diff --git a/core/java/android/os/HidlSupport.java b/core/java/android/os/HidlSupport.java
new file mode 100644
index 0000000..7dec4d7
--- /dev/null
+++ b/core/java/android/os/HidlSupport.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.IntStream;
+
+/** @hide */
+public class HidlSupport {
+ /**
+ * Similar to Objects.deepEquals, but also take care of lists.
+ * Two objects of HIDL types are considered equal if:
+ * 1. Both null
+ * 2. Both non-null, and of the same class, and:
+ * 2.1 Both are primitive arrays / enum arrays, elements are equal using == check
+ * 2.2 Both are object arrays, elements are checked recursively
+ * 2.3 Both are Lists, elements are checked recursively
+ * 2.4 (If both are collections other than lists or maps, throw an error)
+ * 2.5 lft.equals(rgt) returns true
+ */
+ public static boolean deepEquals(Object lft, Object rgt) {
+ if (lft == rgt) {
+ return true;
+ }
+ if (lft == null || rgt == null) {
+ return false;
+ }
+
+ Class<?> lftClazz = lft.getClass();
+ Class<?> rgtClazz = rgt.getClass();
+ if (lftClazz != rgtClazz) {
+ return false;
+ }
+
+ if (lftClazz.isArray()) {
+ Class<?> lftElementType = lftClazz.getComponentType();
+ if (lftElementType != rgtClazz.getComponentType()) {
+ return false;
+ }
+
+ if (lftElementType.isPrimitive()) {
+ return Objects.deepEquals(lft, rgt);
+ }
+
+ Object[] lftArray = (Object[])lft;
+ Object[] rgtArray = (Object[])rgt;
+ return (lftArray.length == rgtArray.length) &&
+ IntStream.range(0, lftArray.length).allMatch(
+ i -> deepEquals(lftArray[i], rgtArray[i]));
+ }
+
+ if (lft instanceof List<?>) {
+ List<Object> lftList = (List<Object>)lft;
+ List<Object> rgtList = (List<Object>)rgt;
+ if (lftList.size() != rgtList.size()) {
+ return false;
+ }
+
+ Iterator<Object> lftIter = lftList.iterator();
+ return rgtList.stream()
+ .allMatch(rgtElement -> deepEquals(lftIter.next(), rgtElement));
+ }
+
+ throwErrorIfUnsupportedType(lft);
+
+ return lft.equals(rgt);
+ }
+
+ /**
+ * Similar to Arrays.deepHashCode, but also take care of lists.
+ */
+ public static int deepHashCode(Object o) {
+ if (o == null) {
+ return 0;
+ }
+ Class<?> clazz = o.getClass();
+ if (clazz.isArray()) {
+ Class<?> elementType = clazz.getComponentType();
+ if (elementType.isPrimitive()) {
+ return primitiveArrayHashCode(o);
+ }
+ return Arrays.hashCode(Arrays.stream((Object[])o)
+ .mapToInt(element -> deepHashCode(element))
+ .toArray());
+ }
+
+ if (o instanceof List<?>) {
+ return Arrays.hashCode(((List<Object>)o).stream()
+ .mapToInt(element -> deepHashCode(element))
+ .toArray());
+ }
+
+ throwErrorIfUnsupportedType(o);
+
+ return o.hashCode();
+ }
+
+ private static void throwErrorIfUnsupportedType(Object o) {
+ if (o instanceof Collection<?> && !(o instanceof List<?>)) {
+ throw new UnsupportedOperationException(
+ "Cannot check equality on collections other than lists: " +
+ o.getClass().getName());
+ }
+
+ if (o instanceof Map<?, ?>) {
+ throw new UnsupportedOperationException(
+ "Cannot check equality on maps");
+ }
+ }
+
+ private static int primitiveArrayHashCode(Object o) {
+ Class<?> elementType = o.getClass().getComponentType();
+ if (elementType == boolean.class) {
+ return Arrays.hashCode(((boolean[])o));
+ }
+ if (elementType == byte.class) {
+ return Arrays.hashCode(((byte[])o));
+ }
+ if (elementType == char.class) {
+ return Arrays.hashCode(((char[])o));
+ }
+ if (elementType == double.class) {
+ return Arrays.hashCode(((double[])o));
+ }
+ if (elementType == float.class) {
+ return Arrays.hashCode(((float[])o));
+ }
+ if (elementType == int.class) {
+ return Arrays.hashCode(((int[])o));
+ }
+ if (elementType == long.class) {
+ return Arrays.hashCode(((long[])o));
+ }
+ if (elementType == short.class) {
+ return Arrays.hashCode(((short[])o));
+ }
+ // Should not reach here.
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index a265dd0..94fd5b0 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -219,6 +219,7 @@
public native final void writeStatus(int status);
public native final void verifySuccess();
public native final void releaseTemporaryStorage();
+ public native final void release();
public native final void send();
diff --git a/core/java/android/os/IBatteryPropertiesRegistrar.aidl b/core/java/android/os/IBatteryPropertiesRegistrar.aidl
index fd01802..468b58b 100644
--- a/core/java/android/os/IBatteryPropertiesRegistrar.aidl
+++ b/core/java/android/os/IBatteryPropertiesRegistrar.aidl
@@ -27,4 +27,5 @@
void registerListener(IBatteryPropertiesListener listener);
void unregisterListener(IBatteryPropertiesListener listener);
int getProperty(in int id, out BatteryProperty prop);
+ oneway void scheduleUpdate();
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index d48431a..4f4152c 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -483,7 +483,7 @@
}
final String filenameArg = "--update_package=" + filename + "\n";
- final String localeArg = "--locale=" + Locale.getDefault().toString() + "\n";
+ final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() + "\n";
final String securityArg = "--security\n";
String command = filenameArg + localeArg;
@@ -531,7 +531,7 @@
}
final String filenameArg = "--update_package=" + filename + "\n";
- final String localeArg = "--locale=" + Locale.getDefault().toString() + "\n";
+ final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() + "\n";
final String securityArg = "--security\n";
String command = filenameArg + localeArg;
@@ -646,7 +646,7 @@
reasonArg = "--reason=" + sanitizeArg(reason);
}
- final String localeArg = "--locale=" + Locale.getDefault().toString();
+ final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() ;
bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg);
}
@@ -665,7 +665,7 @@
reasonArg = "--reason=" + sanitizeArg(reason);
}
- final String localeArg = "--locale=" + Locale.getDefault().toString();
+ final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() ;
bootCommand(context, "--wipe_cache", reasonArg, localeArg);
}
@@ -690,7 +690,7 @@
final String filename = packageFile.getCanonicalPath();
final String filenameArg = "--wipe_package=" + filename;
- final String localeArg = "--locale=" + Locale.getDefault().toString();
+ final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() ;
bootCommand(context, "--wipe_ab", filenameArg, reasonArg, localeArg);
}
@@ -728,6 +728,10 @@
int timeTotal = -1;
int uncryptTime = -1;
int sourceVersion = -1;
+ int temperature_start = -1;
+ int temperature_end = -1;
+ int temperature_max = -1;
+
while ((line = in.readLine()) != null) {
// Here is an example of lines in last_install:
// ...
@@ -772,6 +776,12 @@
} else if (line.startsWith("bytes_stashed")) {
bytesStashedInMiB = (bytesStashedInMiB == -1) ? scaled :
bytesStashedInMiB + scaled;
+ } else if (line.startsWith("temperature_start")) {
+ temperature_start = scaled;
+ } else if (line.startsWith("temperature_end")) {
+ temperature_end = scaled;
+ } else if (line.startsWith("temperature_max")) {
+ temperature_max = scaled;
}
}
@@ -791,6 +801,15 @@
if (bytesStashedInMiB != -1) {
MetricsLogger.histogram(context, "ota_stashed_in_MiBs", bytesStashedInMiB);
}
+ if (temperature_start != -1) {
+ MetricsLogger.histogram(context, "ota_temperature_start", temperature_start);
+ }
+ if (temperature_end != -1) {
+ MetricsLogger.histogram(context, "ota_temperature_end", temperature_end);
+ }
+ if (temperature_max != -1) {
+ MetricsLogger.histogram(context, "ota_temperature_max", temperature_max);
+ }
} catch (IOException e) {
Log.e(TAG, "Failed to read lines in last_install", e);
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 2bf3c2c..c520917 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -35,6 +35,12 @@
private static final String TAG = "SystemProperties";
private static final boolean TRACK_KEY_ACCESS = false;
+ /**
+ * Android O removed the property name length limit, but com.amazon.kindle 7.8.1.5
+ * uses reflection to read this whenever text is selected (http://b/36095274).
+ */
+ public static final int PROP_NAME_MAX = Integer.MAX_VALUE;
+
public static final int PROP_VALUE_MAX = 91;
private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 6a10743..203b8dd 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -600,6 +600,10 @@
mPopup.setWindowLayoutType(mDropDownWindowLayoutType);
if (mPopup.isShowing()) {
+ if (!getAnchorView().isAttachedToWindow()) {
+ //Don't update position if the anchor view is detached from window.
+ return;
+ }
final int widthSpec;
if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
// The call to PopupWindow's update method below can accept -1 for any
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index dbbebbe7..aced75d 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -17,6 +17,11 @@
package com.android.internal.os;
import android.os.Process;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructCapUserData;
+import android.system.StructCapUserHeader;
import android.util.Slog;
import com.android.internal.os.Zygote.MethodAndArgsCaller;
import dalvik.system.VMRuntime;
@@ -119,6 +124,7 @@
command.append(' ');
command.append(targetSdkVersion);
Zygote.appendQuotedShellArgs(command, args);
+ preserveCapabilities();
Zygote.execShell(command.toString());
}
@@ -139,6 +145,74 @@
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from wrapper");
}
- RuntimeInit.applicationInit(targetSdkVersion, argv, null);
+ // Check whether the first argument is a "-cp" in argv, and assume the next argument is the
+ // classpath. If found, create a PathClassLoader and use it for applicationInit.
+ ClassLoader classLoader = null;
+ if (argv != null && argv.length > 2 && argv[0].equals("-cp")) {
+ classLoader = ZygoteInit.createPathClassLoader(argv[1], targetSdkVersion);
+
+ // Install this classloader as the context classloader, too.
+ Thread.currentThread().setContextClassLoader(classLoader);
+
+ // Remove the classpath from the arguments.
+ String removedArgs[] = new String[argv.length - 2];
+ System.arraycopy(argv, 2, removedArgs, 0, argv.length - 2);
+ argv = removedArgs;
+ }
+
+ RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
+ }
+
+ /**
+ * Copy current capabilities to ambient capabilities. This is required for apps using
+ * capabilities, as execv will re-evaluate the capability set, and the set of sh is
+ * empty. Ambient capabilities have to be set to inherit them effectively.
+ *
+ * Note: This is BEST EFFORT ONLY. In case capabilities can't be raised, this function
+ * will silently return. In THIS CASE ONLY, as this is a development feature, it
+ * is better to return and try to run anyways, instead of blocking the wrapped app.
+ * This is acceptable here as failure will leave the wrapped app with strictly less
+ * capabilities, which may make it crash, but not exceed its allowances.
+ */
+ private static void preserveCapabilities() {
+ StructCapUserHeader header = new StructCapUserHeader(
+ OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
+ StructCapUserData[] data;
+ try {
+ data = Os.capget(header);
+ } catch (ErrnoException e) {
+ Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capget", e);
+ return;
+ }
+
+ if (data[0].permitted != data[0].inheritable ||
+ data[1].permitted != data[1].inheritable) {
+ data[0] = new StructCapUserData(data[0].effective, data[0].permitted,
+ data[0].permitted);
+ data[1] = new StructCapUserData(data[1].effective, data[1].permitted,
+ data[1].permitted);
+ try {
+ Os.capset(header, data);
+ } catch (ErrnoException e) {
+ Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capset", e);
+ return;
+ }
+ }
+
+ for (int i = 0; i < 64; i++) {
+ int dataIndex = OsConstants.CAP_TO_INDEX(i);
+ int capMask = OsConstants.CAP_TO_MASK(i);
+ if ((data[dataIndex].inheritable & capMask) != 0) {
+ try {
+ Os.prctl(OsConstants.PR_CAP_AMBIENT, OsConstants.PR_CAP_AMBIENT_RAISE, i, 0,
+ 0);
+ } catch (ErrnoException ex) {
+ // Only log here. Try to run the wrapped application even without this
+ // ambient capability. It may crash after fork, but at least we'll try.
+ Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed to raise ambient capability "
+ + i, ex);
+ }
+ }
+ }
}
}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 59416dd..e065843 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -100,6 +100,8 @@
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, String instructionSet, String appDataDir) {
VM_HOOKS.preFork();
+ // Resets nice priority for zygote process.
+ resetNicePriority();
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, instructionSet, appDataDir);
@@ -144,6 +146,8 @@
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
VM_HOOKS.preFork();
+ // Resets nice priority for zygote process.
+ resetNicePriority();
int pid = nativeForkSystemServer(
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
// Enable tracing as soon as we enter the system_server.
@@ -173,6 +177,14 @@
VM_HOOKS.postForkChild(debugFlags, isSystemServer, instructionSet);
}
+ /**
+ * Resets the calling thread priority to the default value (Thread.NORM_PRIORITY
+ * or nice value 0). This updates both the priority value in java.lang.Thread and
+ * the nice value (setpriority).
+ */
+ static void resetNicePriority() {
+ Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
+ }
/**
* Executes "/system/bin/sh -c <command>" using the exec() system call.
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 1e0a998..e560c0c7 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -449,7 +449,8 @@
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
- System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
+ System.arraycopy(args, 0, amendedArgs, 2, args.length);
+ args = amendedArgs;
}
WrapperInit.execApplication(parsedArgs.invokeWith,
@@ -458,8 +459,7 @@
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
- cl = createSystemServerClassLoader(systemServerClasspath,
- parsedArgs.targetSdkVersion);
+ cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
@@ -474,15 +474,14 @@
}
/**
- * Creates a PathClassLoader for the system server. It also creates
- * a shared namespace associated with the classloader to let it access
- * platform-private native libraries.
+ * Creates a PathClassLoader for the given class path that is associated with a shared
+ * namespace, i.e., this classloader can access platform-private native libraries. The
+ * classloader will use java.library.path as the native library path.
*/
- private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
- int targetSdkVersion) {
+ static PathClassLoader createPathClassLoader(String classPath, int targetSdkVersion) {
String libraryPath = System.getProperty("java.library.path");
- return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
+ return PathClassLoaderFactory.createClassLoader(classPath,
libraryPath,
libraryPath,
ClassLoader.getSystemClassLoader(),
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index d67cef3..8d9630f 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -2070,8 +2070,6 @@
* @param args
*/
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- // Cannot just invoke pw.println(this.toString()) because if the
- // resulting string is to long it won't be displayed.
pw.println(getName() + ":");
pw.println(" total records=" + getLogRecCount());
for (int i = 0; i < getLogRecSize(); i++) {
@@ -2083,12 +2081,15 @@
@Override
public String toString() {
- StringWriter sr = new StringWriter();
- PrintWriter pr = new PrintWriter(sr);
- dump(null, pr, null);
- pr.flush();
- pr.close();
- return sr.toString();
+ String name = "(null)";
+ String state = "(null)";
+ try {
+ name = mName.toString();
+ state = mSmHandler.getCurrentState().getName().toString();
+ } catch (NullPointerException npe) {
+ // Will use default(s) initialized above.
+ }
+ return "name=" + name + " state=" + state;
}
/**
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 1bd2333..678041f 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -404,6 +404,11 @@
signalExceptionForError(env, err);
}
+static void JHwParcel_native_release(
+ JNIEnv *env, jobject thiz) {
+ JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
+}
+
static void JHwParcel_native_releaseTemporaryStorage(
JNIEnv *env, jobject thiz) {
JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
@@ -955,6 +960,10 @@
{ "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
(void *)JHwParcel_native_writeBuffer },
+
+ { "release", "()V",
+ (void *)JHwParcel_native_release },
+
};
namespace android {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3498108..ac9e636 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -155,24 +155,6 @@
}
}
-// Resets nice priority for zygote process. Zygote priority can be set
-// to high value during boot phase to speed it up. We want to ensure
-// zygote is running at normal priority before childs are forked from it.
-//
-// This ends up being called repeatedly before each fork(), but there's
-// no real harm in that.
-static void ResetNicePriority(JNIEnv* env) {
- errno = 0;
- int prio = getpriority(PRIO_PROCESS, 0);
- if (prio == -1 && errno != 0) {
- ALOGW("getpriority failed: %s\n", strerror(errno));
- }
- if (prio != 0 && setpriority(PRIO_PROCESS, 0, 0) != 0) {
- ALOGE("setpriority(%d, 0, 0) failed: %s", PRIO_PROCESS, strerror(errno));
- RuntimeAbort(env, __LINE__, "setpriority failed");
- }
-}
-
// Sets the SIGCHLD handler back to default behavior in zygote children.
static void UnsetSigChldHandler() {
struct sigaction sa;
@@ -364,6 +346,11 @@
return false;
}
+ // Handle force_mount_namespace with MOUNT_EXTERNAL_NONE.
+ if (mount_mode == MOUNT_EXTERNAL_NONE) {
+ return true;
+ }
+
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));
@@ -512,8 +499,6 @@
RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
}
- ResetNicePriority(env);
-
pid_t pid = fork();
if (pid == 0) {
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 9660de4..956b724 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -26,7 +26,9 @@
#include <sys/un.h>
#include <unistd.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include <android-base/strings.h>
// Static whitelist of open paths that the zygote is allowed to keep open.
@@ -65,9 +67,10 @@
return true;
}
- static const std::string kFrameworksPrefix = "/system/framework/";
- static const std::string kJarSuffix = ".jar";
- if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) {
+ static const char* kFrameworksPrefix = "/system/framework/";
+ static const char* kJarSuffix = ".jar";
+ if (android::base::StartsWith(path, kFrameworksPrefix)
+ && android::base::EndsWith(path, kJarSuffix)) {
return true;
}
@@ -79,28 +82,31 @@
// /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
// /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
// See AssetManager.cpp for more details on overlay-subdir.
- static const std::string kOverlayDir = "/system/vendor/overlay/";
- static const std::string kVendorOverlayDir = "/vendor/overlay";
- static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/";
- static const std::string kApkSuffix = ".apk";
+ static const char* kOverlayDir = "/system/vendor/overlay/";
+ static const char* kVendorOverlayDir = "/vendor/overlay";
+ static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
+ static const char* kApkSuffix = ".apk";
- if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir)
- || StartsWith(path, kVendorOverlayDir))
- && EndsWith(path, kApkSuffix)
+ if ((android::base::StartsWith(path, kOverlayDir)
+ || android::base::StartsWith(path, kOverlaySubdir)
+ || android::base::StartsWith(path, kVendorOverlayDir))
+ && android::base::EndsWith(path, kApkSuffix)
&& path.find("/../") == std::string::npos) {
return true;
}
- static const std::string kOverlayIdmapPrefix = "/data/resource-cache/";
- static const std::string kOverlayIdmapSuffix = ".apk@idmap";
- if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix)
+ static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
+ static const char* kOverlayIdmapSuffix = ".apk@idmap";
+ if (android::base::StartsWith(path, kOverlayIdmapPrefix)
+ && android::base::EndsWith(path, kOverlayIdmapSuffix)
&& path.find("/../") == std::string::npos) {
return true;
}
// All regular files that are placed under this path are whitelisted automatically.
- static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
- if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) {
+ static const char* kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
+ if (android::base::StartsWith(path, kZygoteWhitelistPath)
+ && path.find("/../") == std::string::npos) {
return true;
}
@@ -111,24 +117,6 @@
: whitelist_() {
}
-// TODO: Call android::base::StartsWith instead of copying the code here.
-// static
-bool FileDescriptorWhitelist::StartsWith(const std::string& str,
- const std::string& prefix) {
- return str.compare(0, prefix.size(), prefix) == 0;
-}
-
-// TODO: Call android::base::EndsWith instead of copying the code here.
-// static
-bool FileDescriptorWhitelist::EndsWith(const std::string& str,
- const std::string& suffix) {
- if (suffix.size() > str.size()) {
- return false;
- }
-
- return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
-}
-
FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
// static
@@ -174,7 +162,8 @@
}
std::string file_path;
- if (!Readlink(fd, &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;
}
@@ -299,30 +288,6 @@
is_sock(false) {
}
-// TODO: Call android::base::Readlink instead of copying the code here.
-// static
-bool FileDescriptorInfo::Readlink(const int fd, std::string* result) {
- char path[64];
- snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
-
- // Code copied from android::base::Readlink starts here :
-
- // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer,
- // and truncates to whatever size you do supply, so it can't be used to query.
- // We could call lstat first, but that would introduce a race condition that
- // we couldn't detect.
- // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
- char buf[4096];
- ssize_t len = readlink(path, buf, sizeof(buf));
- if (len == -1) {
- PLOG(ERROR) << "Readlink on " << fd << " failed.";
- return false;
- }
-
- result->assign(buf, len);
- return true;
-}
-
// static
bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
sockaddr_storage ss;
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index 03298c3..a39e387 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -59,10 +59,6 @@
private:
FileDescriptorWhitelist();
- static bool StartsWith(const std::string& str, const std::string& prefix);
-
- static bool EndsWith(const std::string& str, const std::string& suffix);
-
static FileDescriptorWhitelist* instance_;
std::vector<std::string> whitelist_;
@@ -99,8 +95,6 @@
FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
int fd_flags, int fs_flags, off_t offset);
- static bool Readlink(const int fd, std::string* result);
-
// Returns the locally-bound name of the socket |fd|. Returns true
// iff. all of the following hold :
//
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7d4f99d..c582f4e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -307,6 +307,10 @@
<protected-broadcast android:name="android.net.wifi.STATE_CHANGE" />
<protected-broadcast android:name="android.net.wifi.LINK_CONFIGURATION_CHANGED" />
<protected-broadcast android:name="android.net.wifi.CONFIGURED_NETWORKS_CHANGE" />
+ <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT" />
+ <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_ICON" />
+ <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST" />
+ <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION" />
<protected-broadcast android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
<protected-broadcast android:name="android.net.wifi.supplicant.STATE_CHANGE" />
<protected-broadcast android:name="android.net.wifi.p2p.STATE_CHANGED" />
@@ -1300,7 +1304,7 @@
<permission android:name="android.permission.CONNECTIVITY_INTERNAL"
android:protectionLevel="signature|privileged" />
- <!-- Allows an internal user to use restricted Networks.
+ <!-- @SystemApi Allows an internal user to use restricted Networks.
@hide -->
<permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"
android:protectionLevel="signature|privileged" />
diff --git a/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png b/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png
new file mode 100644
index 0000000..d704951
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png b/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png
new file mode 100644
index 0000000..5dfc89e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png b/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png
new file mode 100644
index 0000000..a648b0b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png
Binary files differ
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4408bf8..beb495de 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1393,6 +1393,9 @@
<!-- Boolean indicating if current platform supports BLE peripheral mode -->
<bool name="config_bluetooth_le_peripheral_mode_supported">false</bool>
+ <!-- Boolean indicating if current platform supports HFP inband ringing -->
+ <bool name="config_bluetooth_hfp_inband_ringing_support">false</bool>
+
<!-- Max number of scan filters supported by blutooth controller. 0 if the
device does not support hardware scan filters-->
<integer translatable="false" name="config_bluetooth_max_scan_filters">0</integer>
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index f07fe70..513bdd1 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -75,7 +75,7 @@
<item>ce-RU</item> <!-- Chechen (Russia) -->
<item>cgg-UG</item> <!-- Chiga (Uganda) -->
<item>chr-US</item> <!-- Cherokee (United States) -->
- <item>cs-CZ</item> <!-- Czech (Czech Republic) -->
+ <item>cs-CZ</item> <!-- Czech (Czechia) -->
<item>cy-GB</item> <!-- Welsh (United Kingdom) -->
<item>da-DK</item> <!-- Danish (Denmark) -->
<item>da-GL</item> <!-- Danish (Greenland) -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4231698..6b63913 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -187,22 +187,23 @@
<!-- Displayed to tell the user that they cannot change the caller ID setting. -->
<string name="CLIRPermanent">You can\'t change the caller ID setting.</string>
- <!-- Displayed to tell the user that data service is blocked by access control. -->
- <string name="RestrictedOnData">Data service is blocked.</string>
- <!-- Displayed to tell the user that emergency service is blocked by access control. -->
- <string name="RestrictedOnEmergency">Emergency service is blocked.</string>
- <!-- Displayed to tell the user that normal service is blocked by access control. -->
- <string name="RestrictedOnNormal">Voice service is blocked.</string>
- <!-- Displayed to tell the user that all emergency and normal voice services are blocked by access control. -->
- <string name="RestrictedOnAllVoice">All voice services are blocked.</string>
- <!-- Displayed to tell the user that sms service is blocked by access control. -->
- <string name="RestrictedOnSms">SMS service is blocked.</string>
- <!-- Displayed to tell the user that voice/data service is blocked by access control. -->
- <string name="RestrictedOnVoiceData">Voice/data services are blocked.</string>
- <!-- Displayed to tell the user that voice and sms service are blocked by access control. -->
- <string name="RestrictedOnVoiceSms">Voice/SMS services are blocked.</string>
- <!-- Displayed to tell the user that all service is blocked by access control. -->
- <string name="RestrictedOnAll">All voice/data/SMS services are blocked.</string>
+ <!-- Notification title to tell the user that data service is blocked by access control. -->
+ <string name="RestrictedOnDataTitle">No data service</string>
+ <!-- Notification title to tell the user that emergency service is blocked by access control. -->
+ <string name="RestrictedOnEmergencyTitle">No emergency service</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>
+
+ <!-- Notification content to tell the user that data service is blocked by access control. -->
+ <string name="RestrictedOnDataContent">Your carrier has temporarily suspended data service at this location</string>
+ <!-- Notification content to tell the user that emergency service is blocked by access control. -->
+ <string name="RestrictedOnEmergencyContent">Your carrier has temporarily suspended emergency calls at this location</string>
+ <!-- Notification content to tell the user that normal service is blocked by access control. -->
+ <string name="RestrictedOnNormalContent">Your carrier has temporarily suspended voice calls at this location</string>
+ <!-- Notification content to tell the user that all emergency and normal voice services are blocked by access control. -->
+ <string name="RestrictedOnAllVoiceContent">Your carrier has temporarily suspended voice and emergency calls at this location</string>
<!-- Displayed to tell the user that peer changed TTY mode -->
<string name="peerTtyModeFull">Peer requested TTY Mode FULL</string>
@@ -4441,4 +4442,25 @@
<!-- Label used by Telephony code, assigned as the display name for conference calls [CHAR LIMIT=60] -->
<string name="conference_call">Conference Call</string>
+
+ <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for earthquake -->
+ <string name="etws_primary_default_message_earthquake">Stay calm and seek shelter nearby.</string>
+
+ <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for Tsunami -->
+ <string name="etws_primary_default_message_tsunami">Evacuate immediately from coastal regions and riverside areas to a safer place such as high ground.</string>
+
+ <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for earthquake and Tsunami -->
+ <string name="etws_primary_default_message_earthquake_and_tsunami">Stay calm and seek shelter nearby.</string>
+
+ <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for test -->
+ <string name="etws_primary_default_message_test">Emergency messages test</string>
+
+ <!-- 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>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index dbeda0b..5df8998 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -240,6 +240,7 @@
<java-symbol type="bool" name="config_bluetooth_address_validation" />
<java-symbol type="bool" name="config_bluetooth_sco_off_call" />
<java-symbol type="bool" name="config_bluetooth_le_peripheral_mode_supported" />
+ <java-symbol type="bool" name="config_bluetooth_hfp_inband_ringing_support" />
<java-symbol type="bool" name="config_cellBroadcastAppLinks" />
<java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
<java-symbol type="bool" name="config_enableAutoPowerModes" />
@@ -482,10 +483,14 @@
<java-symbol type="string" name="Noon" />
<java-symbol type="string" name="PinMmi" />
<java-symbol type="string" name="PwdMmi" />
- <java-symbol type="string" name="RestrictedOnAllVoice" />
- <java-symbol type="string" name="RestrictedOnData" />
- <java-symbol type="string" name="RestrictedOnEmergency" />
- <java-symbol type="string" name="RestrictedOnNormal" />
+ <java-symbol type="string" name="RestrictedOnAllVoiceTitle" />
+ <java-symbol type="string" name="RestrictedOnDataTitle" />
+ <java-symbol type="string" name="RestrictedOnEmergencyTitle" />
+ <java-symbol type="string" name="RestrictedOnNormalTitle" />
+ <java-symbol type="string" name="RestrictedOnAllVoiceContent" />
+ <java-symbol type="string" name="RestrictedOnDataContent" />
+ <java-symbol type="string" name="RestrictedOnEmergencyContent" />
+ <java-symbol type="string" name="RestrictedOnNormalContent" />
<java-symbol type="string" name="SetupCallDefault" />
<java-symbol type="string" name="accept" />
<java-symbol type="string" name="accessibility_enabled" />
@@ -1290,6 +1295,8 @@
<java-symbol type="drawable" name="ic_sim_card_multi_24px_clr" />
<java-symbol type="drawable" name="ic_sim_card_multi_48px_clr" />
+ <java-symbol type="drawable" name="stat_notify_mmcc_indication_icn" />
+
<java-symbol type="drawable" name="ic_account_circle" />
<java-symbol type="color" name="user_icon_1" />
<java-symbol type="color" name="user_icon_2" />
@@ -1862,6 +1869,10 @@
<java-symbol type="string" name="low_internal_storage_view_text" />
<java-symbol type="string" name="low_internal_storage_view_text_no_boot" />
<java-symbol type="string" name="low_internal_storage_view_title" />
+ <java-symbol type="string" name="mmcc_authentication_reject" />
+ <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="notification_listener_binding_label" />
<java-symbol type="string" name="vr_listener_binding_label" />
<java-symbol type="string" name="condition_provider_service_binding_label" />
@@ -2742,4 +2753,15 @@
<java-symbol type="array" name="config_networkRecommendationPackageNames" />
<java-symbol type="string" name="config_defaultCellBroadcastReceiverPkg" />
+
+ <!-- ETWS primary messages -->
+ <java-symbol type="string" name="etws_primary_default_message_earthquake" />
+
+ <java-symbol type="string" name="etws_primary_default_message_tsunami" />
+
+ <java-symbol type="string" name="etws_primary_default_message_earthquake_and_tsunami" />
+
+ <java-symbol type="string" name="etws_primary_default_message_test" />
+
+ <java-symbol type="string" name="etws_primary_default_message_others" />
</resources>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 29c6b79..1ae922a 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -79,7 +79,7 @@
<!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
<shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
- <!-- Czech Republic: 7-8 digits, starting with 9, plus EU:
+ <!-- Czechia: 7-8 digits, starting with 9, plus EU:
http://www.o2.cz/osobni/en/services-by-alphabet/91670-premium_sms.html -->
<shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
diff --git a/core/res/res/xml/time_zones_by_country.xml b/core/res/res/xml/time_zones_by_country.xml
index a685e2b..6c1ce44 100644
--- a/core/res/res/xml/time_zones_by_country.xml
+++ b/core/res/res/xml/time_zones_by_country.xml
@@ -336,6 +336,10 @@
<timezone code="ck">Pacific/Rarotonga</timezone>
+ <!-- CHILE, -3:00 -->
+
+ <timezone code="cl">America/Punta_Arenas</timezone>
+
<!-- CHILE, -4:00 -->
<timezone code="cl">America/Santiago</timezone>
diff --git a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
index 7a4980a..56e977c 100644
--- a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
+++ b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
@@ -109,7 +109,7 @@
}
public static String expectedSchedulerGroup(int prio) {
- return prio < Process.THREAD_PRIORITY_BACKGROUND ? "/" : "/bg_non_interactive";
+ return "/";
}
public void testPassPriorityToService() throws Exception {
diff --git a/core/tests/utiltests/runtests.sh b/core/tests/utiltests/runtests.sh
new file mode 100755
index 0000000..853119f
--- /dev/null
+++ b/core/tests/utiltests/runtests.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+ echo "You need to source and lunch before you can use this script"
+ exit 1
+fi
+
+echo "Running tests"
+
+set -e # fail early
+
+echo "+ mmma -j32 $ANDROID_BUILD_TOP/frameworks/base/core/tests/utiltests"
+# NOTE Don't actually run the command above since this shell doesn't inherit functions from the
+# caller.
+make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk MODULES-IN-frameworks-base-core-tests-utiltests
+
+set -x # print commands
+
+adb root
+adb wait-for-device
+
+adb install -r -g "$OUT/data/app/FrameworksUtilTests/FrameworksUtilTests.apk"
+
+adb shell am instrument -w "$@" 'com.android.frameworks.utiltests/android.support.test.runner.AndroidJUnitRunner'
diff --git a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
index d29b572..eb2a516 100644
--- a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
@@ -80,6 +80,66 @@
}
/**
+ * Tests {@link StateMachine#toString()}.
+ */
+ class StateMachineToStringTest extends StateMachine {
+ StateMachineToStringTest(String name) {
+ super(name);
+ }
+ }
+
+ class ExampleState extends State {
+ String mName;
+
+ ExampleState(String name) {
+ mName = name;
+ }
+
+ @Override
+ public String getName() {
+ return mName;
+ }
+ }
+
+ @SmallTest
+ public void testToStringSucceedsEvenIfMachineHasNoStates() throws Exception {
+ StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
+ assertTrue(stateMachine.toString().contains("TestStateMachine"));
+ }
+
+ @SmallTest
+ public void testToStringSucceedsEvenIfStateHasNoName() throws Exception {
+ StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
+ State exampleState = new ExampleState(null);
+ stateMachine.addState(exampleState);
+ stateMachine.setInitialState(exampleState);
+ stateMachine.start();
+ assertTrue(stateMachine.toString().contains("TestStateMachine"));
+ assertTrue(stateMachine.toString().contains("(null)"));
+ }
+
+ @SmallTest
+ public void testToStringIncludesMachineAndStateNames() throws Exception {
+ StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
+ State exampleState = new ExampleState("exampleState");
+ stateMachine.addState(exampleState);
+ stateMachine.setInitialState(exampleState);
+ stateMachine.start();
+ assertTrue(stateMachine.toString().contains("TestStateMachine"));
+ assertTrue(stateMachine.toString().contains("exampleState"));
+ }
+
+ @SmallTest
+ public void testToStringDoesNotContainMultipleLines() throws Exception {
+ StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
+ State exampleState = new ExampleState("exampleState");
+ stateMachine.addState(exampleState);
+ stateMachine.setInitialState(exampleState);
+ stateMachine.start();
+ assertFalse(stateMachine.toString().contains("\n"));
+ }
+
+ /**
* Tests {@link StateMachine#quit()}.
*/
class StateMachineQuitTest extends StateMachine {
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index e10db05..38d2a58 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -4320,6 +4320,7 @@
if (curOff > (dtohl(entry.type->header.size)-sizeof(ResTable_map))) {
ALOGW("ResTable_map at %d is beyond type chunk data %d",
(int)curOff, dtohl(entry.type->header.size));
+ free(set);
return BAD_TYPE;
}
map = (const ResTable_map*)(((const uint8_t*)entry.type) + curOff);
@@ -4332,6 +4333,7 @@
if (grp->dynamicRefTable.lookupResourceId(&newName) != NO_ERROR) {
ALOGE("Failed resolving ResTable_map name at %d with ident 0x%08x",
(int) curOff, (int) newName);
+ free(set);
return UNKNOWN_ERROR;
}
}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 760a2d1..56a5737 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -29,6 +29,7 @@
import android.net.Uri;
import android.os.BatteryManager;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio;
import android.provider.MediaStore.Files;
@@ -133,6 +134,8 @@
private int mBatteryLevel;
private int mBatteryScale;
+ private int mDeviceType;
+
static {
System.loadLibrary("media_jni");
}
@@ -195,6 +198,7 @@
}
initDeviceProperties(context);
+ mDeviceType = SystemProperties.getInt("sys.usb.mtp.device_type", 0);
mCloseGuard.open("close");
}
@@ -710,6 +714,7 @@
MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL,
+ MtpConstants.DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE,
};
}
@@ -869,6 +874,10 @@
outStringValue[imageSize.length()] = 0;
return MtpConstants.RESPONSE_OK;
+ case MtpConstants.DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE:
+ outIntValue[0] = mDeviceType;
+ return MtpConstants.RESPONSE_OK;
+
// DEVICE_PROPERTY_BATTERY_LEVEL is implemented in the JNI code
default:
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 34a7f7c..f7f79169 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -76,6 +76,7 @@
static jfieldID field_context;
static jfieldID field_batteryLevel;
static jfieldID field_batteryScale;
+static jfieldID field_deviceType;
// MtpPropertyList fields
static jfieldID field_mCount;
@@ -1030,6 +1031,7 @@
{ MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
{ MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
{ MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT8 },
+ { MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE, MTP_TYPE_UINT32 },
};
bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
@@ -1209,6 +1211,10 @@
result->setFormRange(0, env->GetIntField(mDatabase, field_batteryScale), 1);
result->mCurrentValue.u.u8 = (uint8_t)env->GetIntField(mDatabase, field_batteryLevel);
break;
+ case MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE:
+ result = new MtpProperty(property, MTP_TYPE_UINT32);
+ result->mCurrentValue.u.u32 = (uint32_t)env->GetIntField(mDatabase, field_deviceType);
+ break;
}
checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -1388,6 +1394,11 @@
ALOGE("Can't find MtpDatabase.mBatteryScale");
return -1;
}
+ field_deviceType = env->GetFieldID(clazz, "mDeviceType", "I");
+ if (field_deviceType == NULL) {
+ ALOGE("Can't find MtpDatabase.mDeviceType");
+ return -1;
+ }
// now set up fields for MtpPropertyList class
clazz = env->FindClass("android/mtp/MtpPropertyList");
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index 2e642ec..e450283 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -25,19 +25,26 @@
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS" />
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
- <application android:label="@string/app_name" >
+ <application
+ android:label="@string/app_name"
+ android:directBootAware="true">
<receiver android:name="com.android.carrierdefaultapp.CarrierDefaultBroadcastReceiver">
<intent-filter>
<action android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
</intent-filter>
</receiver>
- <activity android:name="com.android.carrierdefaultapp.CaptivePortalLaunchActivity"
- android:theme="@android:style/Theme.Translucent.NoTitleBar"
- android:excludeFromRecents="true"/>
<service android:name="com.android.carrierdefaultapp.ProvisionObserver"
android:permission="android.permission.BIND_JOB_SERVICE"/>
+ <activity
+ android:name="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
+ android:label="@string/action_bar_label"
+ android:theme="@style/AppTheme"
+ android:configChanges="keyboardHidden|orientation|screenSize" >
+ <intent-filter>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/packages/CarrierDefaultApp/assets/quantum_ic_warning_amber_96.png b/packages/CarrierDefaultApp/assets/quantum_ic_warning_amber_96.png
new file mode 100644
index 0000000..08294ce
--- /dev/null
+++ b/packages/CarrierDefaultApp/assets/quantum_ic_warning_amber_96.png
Binary files differ
diff --git a/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml b/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
index dc54fe2..75aa405 100644
--- a/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
+++ b/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
@@ -22,4 +22,4 @@
<path
android:fillColor="#757575"
android:pathData="M18,2h-8L4.02,8 4,20c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,4c0,-1.1 -0.9,-2 -2,-2zM13,17h-2v-2h2v2zM13,13h-2L11,8h2v5z"/>
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/CarrierDefaultApp/res/layout/activity_captive_portal_login.xml b/packages/CarrierDefaultApp/res/layout/activity_captive_portal_login.xml
new file mode 100644
index 0000000..528576b
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/layout/activity_captive_portal_login.xml
@@ -0,0 +1,34 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
+ tools:ignore="MergeRootFrame">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/url_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="20sp"
+ android:singleLine="true" />
+
+ <ProgressBar
+ android:id="@+id/progress_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="?android:attr/progressBarStyleHorizontal" />
+
+ <WebView
+ android:id="@+id/webview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentBottom="false"
+ android:layout_alignParentRight="false" />
+
+</LinearLayout>
+</FrameLayout>
diff --git a/packages/CarrierDefaultApp/res/values/dimens.xml b/packages/CarrierDefaultApp/res/values/dimens.xml
index a3c5049..1ea8c35 100644
--- a/packages/CarrierDefaultApp/res/values/dimens.xml
+++ b/packages/CarrierDefaultApp/res/values/dimens.xml
@@ -1,3 +1,6 @@
<resources>
<dimen name="glif_icon_size">32dp</dimen>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
</resources>
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index fe5669d..f9342b7 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -1,14 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">CarrierDefaultApp</string>
- <string name="android_system_label">Android System</string>
+ <string name="android_system_label">Mobile Carrier</string>
<string name="portal_notification_id">Mobile data has run out</string>
- <string name="no_data_notification_id">No Mobile data service</string>
- <string name="portal_notification_detail">Tap to add funds to your %s SIM</string>
+ <string name="no_data_notification_id">Your mobile data has been deactivated</string>
+ <string name="portal_notification_detail">Tap to visit the %s website</string>
<string name="no_data_notification_detail">Please contact your service provider %s</string>
- <string name="progress_dialogue_network_connection">Connecting to captive portal...</string>
- <string name="alert_dialogue_network_timeout">Network timeout, would you like to retry?</string>
- <string name="alert_dialogue_network_timeout_title">Network unavailable</string>
- <string name="quit">Quit</string>
- <string name="wait">Wait</string>
+ <string name="action_bar_label">Sign in to mobile network</string>
+ <string name="ssl_error_warning">The network you’re trying to join has security issues.</string>
+ <string name="ssl_error_example">For example, the login page may not belong to the organization shown.</string>
+ <string name="ssl_error_continue">Continue anyway via browser</string>
</resources>
diff --git a/packages/CarrierDefaultApp/res/values/styles.xml b/packages/CarrierDefaultApp/res/values/styles.xml
index 3d26915..939c1aa 100644
--- a/packages/CarrierDefaultApp/res/values/styles.xml
+++ b/packages/CarrierDefaultApp/res/values/styles.xml
@@ -1,3 +1,16 @@
<resources>
- <style name="AlertDialog" parent="android:Theme.Material.Light.Dialog.Alert"/>
+ <style name="AppBaseTheme" parent="@android:style/Theme.Material.Settings">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ <!-- Setting's theme's accent color makes ProgressBar useless, reset back. -->
+ <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
+ </style>
</resources>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java
deleted file mode 100644
index b7fde12..0000000
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java
+++ /dev/null
@@ -1,233 +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 com.android.carrierdefaultapp;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.CaptivePortal;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.NetworkRequest;
-import android.os.Bundle;
-import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
-import android.telephony.SubscriptionManager;
-import android.text.TextUtils;
-import android.net.ICaptivePortal;
-import android.view.ContextThemeWrapper;
-import android.view.WindowManager;
-import com.android.carrierdefaultapp.R;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.util.ArrayUtils;
-
-import static android.net.CaptivePortal.APP_RETURN_DISMISSED;
-
-/**
- * Activity that launches in response to the captive portal notification
- * @see com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION
- * This activity requests network connection if there is no available one, launches the
- * {@link com.android.captiveportallogin portalApp} and keeps track of the portal activation result.
- */
-public class CaptivePortalLaunchActivity extends Activity {
- private static final String TAG = CaptivePortalLaunchActivity.class.getSimpleName();
- private static final boolean DBG = true;
- public static final int NETWORK_REQUEST_TIMEOUT_IN_MS = 5 * 1000;
-
- private ConnectivityManager mCm = null;
- private ConnectivityManager.NetworkCallback mCb = null;
- /* Progress dialogue when request network connection for captive portal */
- private AlertDialog mProgressDialog = null;
- /* Alert dialogue when network request is timeout */
- private AlertDialog mAlertDialog = null;
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mCm = ConnectivityManager.from(this);
- // Check network connection before loading portal
- Network network = getNetworkForCaptivePortal();
- NetworkInfo nwInfo = mCm.getNetworkInfo(network);
- if (nwInfo == null || !nwInfo.isConnected()) {
- if (DBG) logd("Network unavailable, request restricted connection");
- requestNetwork(getIntent());
- } else {
- launchCaptivePortal(getIntent(), network);
- }
- }
-
- // show progress dialog during network connecting
- private void showConnectingProgressDialog() {
- mProgressDialog = new ProgressDialog(getApplicationContext());
- mProgressDialog.setMessage(getString(R.string.progress_dialogue_network_connection));
- mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- mProgressDialog.show();
- }
-
- // if network request is timeout, show alert dialog with two option: cancel & wait
- private void showConnectionTimeoutAlertDialog() {
- mAlertDialog = new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AlertDialog))
- .setMessage(getString(R.string.alert_dialogue_network_timeout))
- .setTitle(getString(R.string.alert_dialogue_network_timeout_title))
- .setNegativeButton(getString(R.string.quit),
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // cancel
- dismissDialog(mAlertDialog);
- finish();
- }
- })
- .setPositiveButton(getString(R.string.wait),
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // wait, request network again
- dismissDialog(mAlertDialog);
- requestNetwork(getIntent());
- }
- })
- .create();
- mAlertDialog.show();
- }
-
- private void requestNetwork(final Intent intent) {
- NetworkRequest request = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .build();
-
- mCb = new ConnectivityManager.NetworkCallback() {
- @Override
- public void onAvailable(Network network) {
- if (DBG) logd("Network available: " + network);
- dismissDialog(mProgressDialog);
- mCm.bindProcessToNetwork(network);
- launchCaptivePortal(intent, network);
- }
-
- @Override
- public void onUnavailable() {
- if (DBG) logd("Network unavailable");
- dismissDialog(mProgressDialog);
- showConnectionTimeoutAlertDialog();
- }
- };
- showConnectingProgressDialog();
- mCm.requestNetwork(request, mCb, NETWORK_REQUEST_TIMEOUT_IN_MS);
- }
-
- private void releaseNetworkRequest() {
- logd("release Network Request");
- if (mCb != null) {
- mCm.unregisterNetworkCallback(mCb);
- mCb = null;
- }
- }
-
- private void dismissDialog(AlertDialog dialog) {
- if (dialog != null) {
- dialog.dismiss();
- }
- }
-
- private Network getNetworkForCaptivePortal() {
- Network[] info = mCm.getAllNetworks();
- if (!ArrayUtils.isEmpty(info)) {
- for (Network nw : info) {
- final NetworkCapabilities nc = mCm.getNetworkCapabilities(nw);
- if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
- && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
- return nw;
- }
- }
- }
- return null;
- }
-
- private void launchCaptivePortal(final Intent intent, Network network) {
- String redirectUrl = intent.getStringExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY);
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
- SubscriptionManager.getDefaultVoiceSubscriptionId());
- if (TextUtils.isEmpty(redirectUrl) || !matchUrl(redirectUrl, subId)) {
- loge("Launch portal fails due to incorrect redirection URL: " +
- Rlog.pii(TAG, redirectUrl));
- return;
- }
- final Intent portalIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
- portalIntent.putExtra(ConnectivityManager.EXTRA_NETWORK, network);
- portalIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
- new CaptivePortal(new ICaptivePortal.Stub() {
- @Override
- public void appResponse(int response) {
- logd("portal response code: " + response);
- releaseNetworkRequest();
- if (response == APP_RETURN_DISMISSED) {
- // Upon success http response code, trigger re-evaluation
- CarrierActionUtils.applyCarrierAction(
- CarrierActionUtils.CARRIER_ACTION_ENABLE_RADIO, intent,
- getApplicationContext());
- CarrierActionUtils.applyCarrierAction(
- CarrierActionUtils.CARRIER_ACTION_ENABLE_METERED_APNS, intent,
- getApplicationContext());
- CarrierActionUtils.applyCarrierAction(
- CarrierActionUtils.CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS,
- intent, getApplicationContext());
- }
- }
- }));
- portalIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, redirectUrl);
- portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- if (DBG) logd("launching portal");
- startActivity(portalIntent);
- finish();
- }
-
- // match configured redirection url
- private boolean matchUrl(String url, int subId) {
- CarrierConfigManager configManager = getApplicationContext()
- .getSystemService(CarrierConfigManager.class);
- String[] redirectURLs = configManager.getConfigForSubId(subId).getStringArray(
- CarrierConfigManager.KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY);
- if (ArrayUtils.isEmpty(redirectURLs)) {
- if (DBG) logd("match is unnecessary without any configured redirection url");
- return true;
- }
- for (String redirectURL : redirectURLs) {
- if (url.startsWith(redirectURL)) {
- return true;
- }
- }
- if (DBG) loge("no match found for configured redirection url");
- return false;
- }
-
- private static void logd(String s) {
- Rlog.d(TAG, s);
- }
-
- private static void loge(String s) {
- Rlog.d(TAG, s);
- }
-}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
new file mode 100644
index 0000000..ec4c00e
--- /dev/null
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2017 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.carrierdefaultapp;
+
+import android.app.Activity;
+import android.app.LoadedApk;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.Proxy;
+import android.net.TrafficStats;
+import android.net.Uri;
+import android.net.http.SslError;
+import android.os.Bundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.TypedValue;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.ArrayUtils;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Random;
+
+/**
+ * Activity that launches in response to the captive portal notification
+ * @see com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION
+ * This activity requests network connection if there is no available one before loading the real
+ * portal page and apply carrier actions on the portal activation result.
+ */
+public class CaptivePortalLoginActivity extends Activity {
+ private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName();
+ private static final boolean DBG = true;
+
+ private static final int SOCKET_TIMEOUT_MS = 10 * 1000;
+ private static final int NETWORK_REQUEST_TIMEOUT_MS = 5 * 1000;
+
+ private URL mUrl;
+ private Network mNetwork;
+ private NetworkCallback mNetworkCallback;
+ private ConnectivityManager mCm;
+ private WebView mWebView;
+ private MyWebViewClient mWebViewClient;
+ private boolean mLaunchBrowser = false;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mCm = ConnectivityManager.from(this);
+ mUrl = getUrlForCaptivePortal();
+ if (mUrl == null) {
+ done(false);
+ return;
+ }
+ if (DBG) logd(String.format("onCreate for %s", mUrl.toString()));
+ setContentView(R.layout.activity_captive_portal_login);
+ getActionBar().setDisplayShowHomeEnabled(false);
+
+ mWebView = (WebView) findViewById(R.id.webview);
+ mWebView.clearCache(true);
+ WebSettings webSettings = mWebView.getSettings();
+ webSettings.setJavaScriptEnabled(true);
+ webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
+ mWebViewClient = new MyWebViewClient();
+ mWebView.setWebViewClient(mWebViewClient);
+ mWebView.setWebChromeClient(new MyWebChromeClient());
+
+ mNetwork = getNetworkForCaptivePortal();
+ if (mNetwork == null) {
+ requestNetworkForCaptivePortal();
+ } else {
+ mCm.bindProcessToNetwork(mNetwork);
+ // Start initial page load so WebView finishes loading proxy settings.
+ // Actual load of mUrl is initiated by MyWebViewClient.
+ mWebView.loadData("", "text/html", null);
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ WebView myWebView = (WebView) findViewById(R.id.webview);
+ if (myWebView.canGoBack() && mWebViewClient.allowBack()) {
+ myWebView.goBack();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ releaseNetworkRequest();
+ if (mLaunchBrowser) {
+ // Give time for this network to become default. After 500ms just proceed.
+ for (int i = 0; i < 5; i++) {
+ // TODO: This misses when mNetwork underlies a VPN.
+ if (mNetwork.equals(mCm.getActiveNetwork())) break;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ final String url = mUrl.toString();
+ if (DBG) logd("starting activity with intent ACTION_VIEW for " + url);
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
+ }
+ }
+
+ // Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
+ private void setWebViewProxy() {
+ LoadedApk loadedApk = getApplication().mLoadedApk;
+ try {
+ Field receiversField = LoadedApk.class.getDeclaredField("mReceivers");
+ receiversField.setAccessible(true);
+ ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
+ for (Object receiverMap : receivers.values()) {
+ for (Object rec : ((ArrayMap) receiverMap).keySet()) {
+ Class clazz = rec.getClass();
+ if (clazz.getName().contains("ProxyChangeListener")) {
+ Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class,
+ Intent.class);
+ Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
+ onReceiveMethod.invoke(rec, getApplicationContext(), intent);
+ Log.v(TAG, "Prompting WebView proxy reload.");
+ }
+ }
+ }
+ } catch (Exception e) {
+ loge("Exception while setting WebView proxy: " + e);
+ }
+ }
+
+ private void done(boolean success) {
+ if (DBG) logd(String.format("Result success %b for %s", success, mUrl.toString()));
+ if (success) {
+ // Trigger re-evaluation upon success http response code
+ CarrierActionUtils.applyCarrierAction(
+ CarrierActionUtils.CARRIER_ACTION_ENABLE_RADIO, getIntent(),
+ getApplicationContext());
+ CarrierActionUtils.applyCarrierAction(
+ CarrierActionUtils.CARRIER_ACTION_ENABLE_METERED_APNS, getIntent(),
+ getApplicationContext());
+ CarrierActionUtils.applyCarrierAction(
+ CarrierActionUtils.CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS, getIntent(),
+ getApplicationContext());
+
+ }
+ finishAndRemoveTask();
+ }
+
+ private URL getUrlForCaptivePortal() {
+ String url = getIntent().getStringExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY);
+ if (url.isEmpty()) {
+ url = mCm.getCaptivePortalServerUrl();
+ }
+ final CarrierConfigManager configManager = getApplicationContext()
+ .getSystemService(CarrierConfigManager.class);
+ final int subId = getIntent().getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ SubscriptionManager.getDefaultVoiceSubscriptionId());
+ final String[] portalURLs = configManager.getConfigForSubId(subId).getStringArray(
+ CarrierConfigManager.KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY);
+ if (!ArrayUtils.isEmpty(portalURLs)) {
+ for (String portalUrl : portalURLs) {
+ if (url.startsWith(portalUrl)) {
+ break;
+ }
+ }
+ url = null;
+ }
+ try {
+ return new URL(url);
+ } catch (MalformedURLException e) {
+ loge("Invalid captive portal URL " + url);
+ }
+ return null;
+ }
+
+ private void testForCaptivePortal() {
+ new Thread(new Runnable() {
+ public void run() {
+ // Give time for captive portal to open.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ HttpURLConnection urlConnection = null;
+ int httpResponseCode = 500;
+ TrafficStats.setThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+ try {
+ urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl);
+ urlConnection.setInstanceFollowRedirects(false);
+ urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
+ urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
+ urlConnection.setUseCaches(false);
+ urlConnection.getInputStream();
+ httpResponseCode = urlConnection.getResponseCode();
+ } catch (IOException e) {
+ } finally {
+ if (urlConnection != null) urlConnection.disconnect();
+ }
+ if (httpResponseCode == 204) {
+ done(true);
+ }
+ }
+ }).start();
+ }
+
+ private Network getNetworkForCaptivePortal() {
+ Network[] info = mCm.getAllNetworks();
+ if (!ArrayUtils.isEmpty(info)) {
+ for (Network nw : info) {
+ final NetworkCapabilities nc = mCm.getNetworkCapabilities(nw);
+ if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+ return nw;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void requestNetworkForCaptivePortal() {
+ NetworkRequest request = new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .build();
+
+ mNetworkCallback = new ConnectivityManager.NetworkCallback() {
+ @Override
+ public void onAvailable(Network network) {
+ if (DBG) logd("Network available: " + network);
+ mCm.bindProcessToNetwork(network);
+ mNetwork = network;
+ runOnUiThreadIfNotFinishing(() -> {
+ // Start initial page load so WebView finishes loading proxy settings.
+ // Actual load of mUrl is initiated by MyWebViewClient.
+ mWebView.loadData("", "text/html", null);
+ });
+ }
+
+ @Override
+ public void onUnavailable() {
+ if (DBG) logd("Network unavailable");
+ runOnUiThreadIfNotFinishing(() -> {
+ // Instead of not loading anything in webview, simply load the page and return
+ // HTTP error page in the absence of network connection.
+ mWebView.loadUrl(mUrl.toString());
+ });
+ }
+ };
+ logd("request Network for captive portal");
+ mCm.requestNetwork(request, mNetworkCallback, NETWORK_REQUEST_TIMEOUT_MS);
+ }
+
+ private void releaseNetworkRequest() {
+ logd("release Network for captive portal");
+ if (mNetworkCallback != null) {
+ mCm.unregisterNetworkCallback(mNetworkCallback);
+ mNetworkCallback = null;
+ mNetwork = null;
+ }
+ }
+
+ private class MyWebViewClient extends WebViewClient {
+ private static final String INTERNAL_ASSETS = "file:///android_asset/";
+ private final String mBrowserBailOutToken = Long.toString(new Random().nextLong());
+ // How many Android device-independent-pixels per scaled-pixel
+ // dp/sp = (px/sp) / (px/dp) = (1/sp) / (1/dp)
+ private final float mDpPerSp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 1,
+ getResources().getDisplayMetrics())
+ / TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
+ getResources().getDisplayMetrics());
+ private int mPagesLoaded;
+
+ // If we haven't finished cleaning up the history, don't allow going back.
+ public boolean allowBack() {
+ return mPagesLoaded > 1;
+ }
+
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ if (url.contains(mBrowserBailOutToken)) {
+ mLaunchBrowser = true;
+ done(false);
+ return;
+ }
+ // The first page load is used only to cause the WebView to
+ // fetch the proxy settings. Don't update the URL bar, and
+ // don't check if the captive portal is still there.
+ if (mPagesLoaded == 0) return;
+ // For internally generated pages, leave URL bar listing prior URL as this is the URL
+ // the page refers to.
+ if (!url.startsWith(INTERNAL_ASSETS)) {
+ final TextView myUrlBar = (TextView) findViewById(R.id.url_bar);
+ myUrlBar.setText(url);
+ }
+ if (mNetwork != null) {
+ testForCaptivePortal();
+ }
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ mPagesLoaded++;
+ if (mPagesLoaded == 1) {
+ // Now that WebView has loaded at least one page we know it has read in the proxy
+ // settings. Now prompt the WebView read the Network-specific proxy settings.
+ setWebViewProxy();
+ // Load the real page.
+ view.loadUrl(mUrl.toString());
+ return;
+ } else if (mPagesLoaded == 2) {
+ // Prevent going back to empty first page.
+ view.clearHistory();
+ }
+ if (mNetwork != null) {
+ testForCaptivePortal();
+ }
+ }
+
+ // Convert Android device-independent-pixels (dp) to HTML size.
+ private String dp(int dp) {
+ // HTML px's are scaled just like dp's, so just add "px" suffix.
+ return Integer.toString(dp) + "px";
+ }
+
+ // Convert Android scaled-pixels (sp) to HTML size.
+ private String sp(int sp) {
+ // Convert sp to dp's.
+ float dp = sp * mDpPerSp;
+ // Apply a scale factor to make things look right.
+ dp *= 1.3;
+ // Convert dp's to HTML size.
+ return dp((int) dp);
+ }
+
+ // A web page consisting of a large broken lock icon to indicate SSL failure.
+ private final String SSL_ERROR_HTML = "<html><head><style>"
+ + "body { margin-left:" + dp(48) + "; margin-right:" + dp(48) + "; "
+ + "margin-top:" + dp(96) + "; background-color:#fafafa; }"
+ + "img { width:" + dp(48) + "; height:" + dp(48) + "; }"
+ + "div.warn { font-size:" + sp(16) + "; margin-top:" + dp(16) + "; "
+ + " opacity:0.87; line-height:1.28; }"
+ + "div.example { font-size:" + sp(14) + "; margin-top:" + dp(16) + "; "
+ + " opacity:0.54; line-height:1.21905; }"
+ + "a { font-size:" + sp(14) + "; text-decoration:none; text-transform:uppercase; "
+ + " margin-top:" + dp(24) + "; display:inline-block; color:#4285F4; "
+ + " height:" + dp(48) + "; font-weight:bold; }"
+ + "</style></head><body><p><img src=quantum_ic_warning_amber_96.png><br>"
+ + "<div class=warn>%s</div>"
+ + "<div class=example>%s</div>" + "<a href=%s>%s</a></body></html>";
+
+ @Override
+ public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+ Log.w(TAG, "SSL error (error: " + error.getPrimaryError() + " host: "
+ // Only show host to avoid leaking private info.
+ + Uri.parse(error.getUrl()).getHost() + " certificate: "
+ + error.getCertificate() + "); displaying SSL warning.");
+ final String html = String.format(SSL_ERROR_HTML, getString(R.string.ssl_error_warning),
+ getString(R.string.ssl_error_example), mBrowserBailOutToken,
+ getString(R.string.ssl_error_continue));
+ view.loadDataWithBaseURL(INTERNAL_ASSETS, html, "text/HTML", "UTF-8", null);
+ }
+
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ if (url.startsWith("tel:")) {
+ startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private class MyWebChromeClient extends WebChromeClient {
+ @Override
+ public void onProgressChanged(WebView view, int newProgress) {
+ final ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+ myProgressBar.setProgress(newProgress);
+ }
+ }
+
+ private void runOnUiThreadIfNotFinishing(Runnable r) {
+ if (!isFinishing()) {
+ runOnUiThread(r);
+ }
+ }
+
+ private static void logd(String s) {
+ Rlog.d(TAG, s);
+ }
+
+ private static void loge(String s) {
+ Rlog.d(TAG, s);
+ }
+
+}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index d9bd2fc..73ff3a9 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -112,8 +112,10 @@
logd("onShowCaptivePortalNotification");
final NotificationManager notificationMgr = context.getSystemService(
NotificationManager.class);
- Intent portalIntent = new Intent(context, CaptivePortalLaunchActivity.class);
+ Intent portalIntent = new Intent(context, CaptivePortalLoginActivity.class);
portalIntent.putExtras(intent);
+ portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
+ | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, portalIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = getNotification(context, R.string.portal_notification_id,
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/LaunchCaptivePortalActivityTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/LaunchCaptivePortalActivityTest.java
deleted file mode 100644
index 8a18d72..0000000
--- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/LaunchCaptivePortalActivityTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.android.carrierdefaultapp;
-
-import android.annotation.TargetApi;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.NetworkRequest;
-
-import com.android.internal.telephony.TelephonyIntents;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-public class LaunchCaptivePortalActivityTest extends
- CarrierDefaultActivityTestCase<CaptivePortalLaunchActivity> {
-
- @Mock
- private ConnectivityManager mCm;
- @Mock
- private NetworkInfo mNetworkInfo;
- @Mock
- private Network mNetwork;
-
- @Captor
- private ArgumentCaptor<Integer> mInt;
- @Captor
- private ArgumentCaptor<NetworkRequest> mNetworkReq;
-
- private NetworkCapabilities mNetworkCapabilities;
-
- public LaunchCaptivePortalActivityTest() {
- super(CaptivePortalLaunchActivity.class);
- }
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
- injectSystemService(ConnectivityManager.class, mCm);
- }
-
- @After
- public void tearDown() throws Exception {
- super.tearDown();
- }
-
- @Override
- protected Intent createActivityIntent() {
- Intent intent = new Intent(getInstrumentation().getTargetContext(),
- CaptivePortalLaunchActivity.class);
- intent.putExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY, "url");
- return intent;
- }
-
- @Test
- public void testWithoutInternetConnection() throws Throwable {
- startActivity();
- TestContext.waitForMs(100);
- verify(mCm, atLeast(1)).requestNetwork(mNetworkReq.capture(), any(), mInt.capture());
- // verify network request
- assert(mNetworkReq.getValue().networkCapabilities.hasCapability(
- NetworkCapabilities.NET_CAPABILITY_INTERNET));
- assert(mNetworkReq.getValue().networkCapabilities.hasTransport(
- NetworkCapabilities.TRANSPORT_CELLULAR));
- assertFalse(mNetworkReq.getValue().networkCapabilities.hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED));
- assertEquals(CaptivePortalLaunchActivity.NETWORK_REQUEST_TIMEOUT_IN_MS,
- (int) mInt.getValue());
- // verify captive portal app is not launched due to unavailable network
- assertNull(getStartedActivityIntent());
- stopActivity();
- }
-
- @Test
- public void testWithInternetConnection() throws Throwable {
- // Mock internet connection
- mNetworkCapabilities = new NetworkCapabilities()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- doReturn(new Network[]{mNetwork}).when(mCm).getAllNetworks();
- doReturn(mNetworkCapabilities).when(mCm).getNetworkCapabilities(eq(mNetwork));
- doReturn(mNetworkInfo).when(mCm).getNetworkInfo(eq(mNetwork));
- doReturn(true).when(mNetworkInfo).isConnected();
-
- startActivity();
- TestContext.waitForMs(100);
- // verify there is no network request with internet connection
- verify(mCm, times(0)).requestNetwork(any(), any(), anyInt());
- // verify captive portal app is launched
- assertNotNull(getStartedActivityIntent());
- assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN,
- getStartedActivityIntent().getAction());
- stopActivity();
- }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index a9f6dc9..4c8c036 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1625,7 +1625,7 @@
*/
public void reportSimUnlocked(int subId) {
if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
- int slotId = SubscriptionManager.getSlotId(subId);
+ int slotId = SubscriptionManager.getSlotIndex(subId);
handleSimStateChange(subId, slotId, State.READY);
}
@@ -1794,7 +1794,7 @@
for (int i = 0; i < list.size(); i++) {
final SubscriptionInfo info = list.get(i);
final int id = info.getSubscriptionId();
- int slotId = SubscriptionManager.getSlotId(id);
+ int slotId = SubscriptionManager.getSlotIndex(id);
if (state == getSimState(id) && bestSlotId > slotId ) {
resultId = id;
bestSlotId = slotId;
diff --git a/packages/Osu/src/com/android/MainActivity.java b/packages/Osu/src/com/android/MainActivity.java
index 7e7d49a..9bcc390 100644
--- a/packages/Osu/src/com/android/MainActivity.java
+++ b/packages/Osu/src/com/android/MainActivity.java
@@ -246,6 +246,8 @@
case WifiManager.SCAN_RESULTS_AVAILABLE_ACTION:
mOsuManager.pushScanResults(wifiManager.getScanResults());
break;
+ // TODO(b/32883320): use updated intent.
+ /*
case WifiManager.PASSPOINT_WNM_FRAME_RECEIVED_ACTION:
long bssid = bundle.getLong(WifiManager.EXTRA_PASSPOINT_WNM_BSSID);
String url = bundle.getString(WifiManager.EXTRA_PASSPOINT_WNM_URL);
@@ -282,6 +284,7 @@
bundle.getString(WifiManager.EXTRA_PASSPOINT_ICON_FILE),
bundle.getByteArray(WifiManager.EXTRA_PASSPOINT_ICON_DATA));
break;
+ */
case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
mOsuManager.networkConfigChange((WifiConfiguration)
intent.getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION));
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 1f432de..13ec722 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -102,6 +102,19 @@
<!-- Bluetooth settings -->
+ <!-- Titles for Bluetooth AVRCP Versions -->
+ <string-array name="bluetooth_avrcp_versions">
+ <item>AVRCP 1.4 (Default)</item>
+ <item>AVRCP 1.5</item>
+ <item>AVRCP 1.6</item>
+ </string-array>
+
+ <!-- Values for Bluetooth AVRCP Versions -->
+ <string-array name="bluetooth_avrcp_version_values">
+ <item>avrcp14</item>
+ <item>avrcp15</item>
+ <item>avrcp16</item>
+ </string-array>
<!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=50] -->
<string-array name="bluetooth_a2dp_codec_titles">
@@ -111,6 +124,8 @@
<item>aptX</item>
<item>aptX HD</item>
<item>LDAC</item>
+ <item>Enable Optional Codecs</item>
+ <item>Disable Optional Codecs</item>
</string-array>
<!-- Values for Bluetooth Audio Codec selection preference. -->
@@ -121,6 +136,8 @@
<item>2</item>
<item>3</item>
<item>4</item>
+ <item>5</item>
+ <item>6</item>
</string-array>
<!-- Summaries for Bluetooth Audio Codec selection preference. [CHAR LIMIT=50]-->
@@ -131,6 +148,8 @@
<item>aptX</item>
<item>aptX HD</item>
<item>LDAC</item>
+ <item>Enable Optional Codecs</item>
+ <item>Disable Optional Codecs</item>
</string-array>
<!-- Titles for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=50] -->
@@ -210,6 +229,7 @@
<item>Optimized for Audio Quality (990kbps/909kbps)</item>
<item>Balanced Audio And Connection Quality (660kbps/606kbps)</item>
<item>Optimized for Connection Quality (330kbps/303kbps)</item>
+ <item>Best Effort (Adaptive Bit Rate)</item>
</string-array>
<!-- Values for Bluetooth Audio Codec LDAC Playback Quaility selection preference. -->
@@ -217,6 +237,7 @@
<item>1000</item>
<item>1001</item>
<item>1002</item>
+ <item>1003</item>
</string-array>
<!-- Summaries for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=70]-->
@@ -224,6 +245,7 @@
<item>Optimized for Audio Quality</item>
<item>Balanced Audio And Connection Quality</item>
<item>Optimized for Connection Quality</item>
+ <item>Best Effort (Adaptive Bit Rate)</item>
</string-array>
<!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] -->
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 064059b..3973a43 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -430,6 +430,11 @@
<!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume">Disable absolute volume</string>
+ <!-- UI debug setting: Select Bluetooth AVRCP Version -->
+ <string name="bluetooth_select_avrcp_version_string">Bluetooth AVRCP Version</string>
+ <!-- UI debug setting: Select Bluetooth AVRCP Version -->
+ <string name="bluetooth_select_avrcp_version_dialog_title">Select Bluetooth AVRCP Version</string>
+
<!-- UI debug setting: Select Bluetooth Audio Codec -->
<string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string>
<!-- UI debug setting: Select Bluetooth Audio Codec -->
diff --git a/packages/SettingsLib/res/xml/timezones.xml b/packages/SettingsLib/res/xml/timezones.xml
index 4426495..12d31cf 100644
--- a/packages/SettingsLib/res/xml/timezones.xml
+++ b/packages/SettingsLib/res/xml/timezones.xml
@@ -21,7 +21,7 @@
<timezone id="America/St_Johns"></timezone>
<timezone id="America/Recife"></timezone>
<timezone id="America/Sao_Paulo"></timezone>
- <timezone id="America/Buenos_Aires"></timezone>
+ <timezone id="America/Argentina/Buenos_Aires"></timezone>
<timezone id="America/Godthab"></timezone>
<timezone id="America/Montevideo"></timezone>
<timezone id="Atlantic/South_Georgia"></timezone>
@@ -58,11 +58,11 @@
<timezone id="Asia/Karachi"></timezone>
<timezone id="Asia/Oral"></timezone>
<timezone id="Asia/Yekaterinburg"></timezone>
- <timezone id="Asia/Calcutta"></timezone>
+ <timezone id="Asia/Kolkata"></timezone>
<timezone id="Asia/Colombo"></timezone>
- <timezone id="Asia/Katmandu"></timezone>
+ <timezone id="Asia/Kathmandu"></timezone>
<timezone id="Asia/Almaty"></timezone>
- <timezone id="Asia/Rangoon"></timezone>
+ <timezone id="Asia/Yangon"></timezone>
<timezone id="Asia/Krasnoyarsk"></timezone>
<timezone id="Asia/Bangkok"></timezone>
<timezone id="Asia/Jakarta"></timezone>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index f0ec1078..a803e60 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -649,7 +649,11 @@
}
if (comparator != null) {
- Collections.sort(filteredApps, comparator);
+ synchronized (mEntriesMap) {
+ // Locking to ensure that the background handler does not mutate
+ // the size of AppEntries used for ordering while sorting.
+ Collections.sort(filteredApps, comparator);
+ }
}
synchronized (mRebuildSync) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 3435d1d..0a32f19 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -394,9 +394,13 @@
// the given ScanResult. This is used for showing that a given AP
// (ScanResult) is available via a Passpoint provider (provider friendly
// name).
- WifiConfiguration config = mWifiManager.getMatchingWifiConfig(result);
- if (config != null) {
- accessPoint.update(config);
+ try {
+ WifiConfiguration config = mWifiManager.getMatchingWifiConfig(result);
+ if (config != null) {
+ accessPoint.update(config);
+ }
+ } catch (UnsupportedOperationException e) {
+ // Passpoint not supported on the device.
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e00178f..144d439 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -398,10 +398,12 @@
removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
// We will update when the automation service dies.
- UserState userState = getCurrentUserStateLocked();
- if (!userState.isUiAutomationSuppressingOtherServices()) {
- if (readConfigurationForUserStateLocked(userState)) {
- onUserStateChangedLocked(userState);
+ synchronized (mLock) {
+ UserState userState = getCurrentUserStateLocked();
+ if (!userState.isUiAutomationSuppressingOtherServices()) {
+ if (readConfigurationForUserStateLocked(userState)) {
+ onUserStateChangedLocked(userState);
+ }
}
}
} else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
diff --git a/services/core/Android.mk b/services/core/Android.mk
index a61743d..898eb7e 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -19,7 +19,7 @@
system/netd/server/binder
LOCAL_JAVA_LIBRARIES := services.net telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update2
+LOCAL_STATIC_JAVA_LIBRARIES := tzdata_shared2 tzdata_update2
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
ifneq ($(INCREMENTAL_BUILDS),)
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 5e9cf74..c7c133d 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -76,15 +76,21 @@
private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
- private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED";
- private static final String EXTRA_ACTION="action";
+
private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid";
private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address";
private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name";
+
+ private static final int ACTIVE_LOG_MAX_SIZE = 20;
+ private static final int CRASH_LOG_MAX_SIZE = 100;
private static final String REASON_AIRPLANE_MODE = "airplane mode";
+ private static final String REASON_RESTARTED = "automatic restart";
+ private static final String REASON_START_CRASH = "turn-on crash";
private static final String REASON_SYSTEM_BOOT = "system boot";
+ private static final String REASON_UNEXPECTED = "unexpected crash";
+ private static final String REASON_USER_SWITCH = "user switch";
+
private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
- private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save
//Maximum msec to wait for service restart
private static final int SERVICE_RESTART_TIME_MS = 200;
//Maximum msec to wait for restart due to error
@@ -149,6 +155,10 @@
private boolean mQuietEnable = false;
private boolean mEnable;
+ private CharSequence timeToLog(long timestamp) {
+ return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
+ }
+
/**
* Used for tracking apps that enabled / disabled Bluetooth.
*/
@@ -168,13 +178,15 @@
}
public String toString() {
- return android.text.format.DateFormat.format("MM-dd HH:mm:ss ", mTimestamp) +
- (mEnable ? " Enabled " : " Disabled ") + " by " + mPackageName;
+ return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ") + " by "
+ + mPackageName;
}
}
private LinkedList<ActiveLog> mActiveLogs;
+ private LinkedList<Long> mCrashTimestamps;
+ private int mCrashes;
// configuration from external IBinder call which is used to
// synchronize with broadcast receiver.
@@ -308,6 +320,8 @@
com.android.internal.R.bool.config_permissionReviewRequired);
mActiveLogs = new LinkedList<ActiveLog>();
+ mCrashTimestamps = new LinkedList<Long>();
+ mCrashes = 0;
mBluetooth = null;
mBluetoothBinder = null;
mBluetoothGatt = null;
@@ -1565,6 +1579,9 @@
mBluetoothLock.writeLock().unlock();
}
+ // log the unexpected crash
+ addCrashLog();
+ addActiveLog(REASON_UNEXPECTED, false);
if (mEnable) {
mEnable = false;
// Send a Bluetooth Restart message
@@ -1600,6 +1617,7 @@
it doesnt change when IBluetooth
service restarts */
mEnable = true;
+ addActiveLog(REASON_RESTARTED, true);
handleEnable(mQuietEnable);
break;
}
@@ -1654,6 +1672,7 @@
unbindAllBluetoothProfileServices();
// disable
+ addActiveLog(REASON_USER_SWITCH, false);
handleDisable();
// Pbap service need receive STATE_TURNING_OFF intent to close
bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
@@ -1691,6 +1710,7 @@
mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
mState = BluetoothAdapter.STATE_OFF;
// enable
+ addActiveLog(REASON_USER_SWITCH, true);
handleEnable(mQuietEnable);
} else if (mBinding || mBluetooth != null) {
Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
@@ -1945,13 +1965,21 @@
private void addActiveLog(String packageName, boolean enable) {
synchronized (mActiveLogs) {
- if (mActiveLogs.size() > 10) {
+ if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
mActiveLogs.remove();
}
mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis()));
}
}
+ private void addCrashLog() {
+ synchronized (mCrashTimestamps) {
+ if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) mCrashTimestamps.removeFirst();
+ mCrashTimestamps.add(System.currentTimeMillis());
+ mCrashes++;
+ }
+ }
+
private void recoverBluetoothServiceFromError(boolean clearBle) {
Slog.e(TAG,"recoverBluetoothServiceFromError");
try {
@@ -1969,6 +1997,7 @@
SystemClock.sleep(500);
// disable
+ addActiveLog(REASON_START_CRASH, false);
handleDisable();
waitForOnOff(false, true);
@@ -2070,6 +2099,12 @@
}
}
+ writer.println("Bluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
+ if (mCrashes == CRASH_LOG_MAX_SIZE) writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
+ for (Long time : mCrashTimestamps) {
+ writer.println(" " + timeToLog(time.longValue()));
+ }
+
String bleAppString = "No BLE Apps registered.";
if (mBleApps.size() == 1) {
bleAppString = "1 BLE App registered:";
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 13a6cd6..34cb6c9 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -96,7 +96,6 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -208,6 +207,8 @@
// See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
private final int mReleasePendingIntentDelayMs;
+ private MockableSystemProperties mSystemProperties;
+
private Tethering mTethering;
private final PermissionMonitor mPermissionMonitor;
@@ -692,6 +693,8 @@
IpConnectivityLog logger) {
if (DBG) log("ConnectivityService starting up");
+ mSystemProperties = getSystemProperties();
+
mMetricsLog = logger;
mDefaultRequest = createInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());
@@ -709,7 +712,7 @@
mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
- mLingerDelayMs = SystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
+ mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
mContext = checkNotNull(context, "missing Context");
mNetd = checkNotNull(netManager, "missing INetworkManagementService");
@@ -736,7 +739,7 @@
mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
// TODO: What is the "correct" way to do determine if this is a wifi only device?
- boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false);
+ boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
log("wifiOnly=" + wifiOnly);
String[] naStrings = context.getResources().getStringArray(
com.android.internal.R.array.networkAttributes);
@@ -789,8 +792,8 @@
}
}
- mTestMode = SystemProperties.get("cm.test.mode").equals("true")
- && SystemProperties.get("ro.build.type").equals("eng");
+ mTestMode = mSystemProperties.get("cm.test.mode").equals("true")
+ && mSystemProperties.get("ro.build.type").equals("eng");
mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager,
IoThread.get().getLooper(), new MockableSystemProperties());
@@ -1817,8 +1820,8 @@
// Overridden for testing purposes to avoid writing to SystemProperties.
@VisibleForTesting
- protected int getDefaultTcpRwnd() {
- return SystemProperties.getInt(DEFAULT_TCP_RWND_KEY, 0);
+ protected MockableSystemProperties getSystemProperties() {
+ return new MockableSystemProperties();
}
private void updateTcpBufferSizes(NetworkAgentInfo nai) {
@@ -1856,10 +1859,11 @@
}
Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.TCP_DEFAULT_INIT_RWND, getDefaultTcpRwnd());
+ Settings.Global.TCP_DEFAULT_INIT_RWND,
+ mSystemProperties.getInt("net.tcp.default_init_rwnd", 0));
final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
if (rwndValue != 0) {
- SystemProperties.set(sysctlKey, rwndValue.toString());
+ mSystemProperties.set(sysctlKey, rwndValue.toString());
}
}
@@ -1883,7 +1887,7 @@
@Override
public int getRestoreDefaultNetworkDelay(int networkType) {
- String restoreDefaultNetworkDelayStr = SystemProperties.get(
+ String restoreDefaultNetworkDelayStr = mSystemProperties.get(
NETWORK_RESTORE_DELAY_PROP_NAME);
if(restoreDefaultNetworkDelayStr != null &&
restoreDefaultNetworkDelayStr.length() != 0) {
@@ -3037,11 +3041,21 @@
@Override
public boolean isTetheringSupported() {
enforceTetherAccessPermission();
- int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
+ int defaultVal = (mSystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.TETHER_SUPPORTED, defaultVal) != 0)
&& !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
- return tetherEnabledInSettings && mUserManager.isAdminUser() &&
+
+ // Elevate to system UID to avoid caller requiring MANAGE_USERS permission.
+ boolean adminUser = false;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ adminUser = mUserManager.isAdminUser();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ return tetherEnabledInSettings && adminUser &&
mTethering.hasTetherableConfiguration();
}
@@ -3708,8 +3722,6 @@
vpn.setAlwaysOnPackage(null, false);
return false;
}
-
- vpn.saveAlwaysOnPackage();
}
return true;
}
@@ -3870,15 +3882,6 @@
}
userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId);
mVpns.put(userId, userVpn);
-
- final ContentResolver cr = mContext.getContentResolver();
- String alwaysOnPackage = Settings.Secure.getStringForUser(cr,
- Settings.Secure.ALWAYS_ON_VPN_APP, userId);
- final boolean alwaysOnLockdown = Settings.Secure.getIntForUser(cr,
- Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, /* default */ 0, userId) != 0;
- if (alwaysOnPackage != null) {
- userVpn.setAlwaysOnPackage(alwaysOnPackage, alwaysOnLockdown);
- }
}
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
updateLockdownVpn();
@@ -4539,9 +4542,28 @@
} catch (Exception e) {
loge("Exception in setDnsConfigurationForNetwork: " + e);
}
+ final NetworkAgentInfo defaultNai = getDefaultNetwork();
+ if (defaultNai != null && defaultNai.network.netId == netId) {
+ setDefaultDnsSystemProperties(dnses);
+ }
flushVmDnsCache();
}
+ private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
+ int last = 0;
+ for (InetAddress dns : dnses) {
+ ++last;
+ String key = "net.dns" + last;
+ String value = dns.getHostAddress();
+ mSystemProperties.set(key, value);
+ }
+ for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+ String key = "net.dns" + i;
+ mSystemProperties.set(key, "");
+ }
+ mNumDnsEntries = last;
+ }
+
private String getNetworkPermission(NetworkCapabilities nc) {
// TODO: make these permission strings AIDL constants instead.
if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
@@ -4758,6 +4780,7 @@
notifyLockdownVpn(newNetwork);
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
+ setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
new file mode 100644
index 0000000..a7ce95b
--- /dev/null
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) 2017 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;
+
+import static android.Manifest.permission.DUMP;
+import static android.net.IpSecManager.INVALID_RESOURCE_ID;
+import static android.net.IpSecManager.KEY_RESOURCE_ID;
+import static android.net.IpSecManager.KEY_SPI;
+import static android.net.IpSecManager.KEY_STATUS;
+
+import android.content.Context;
+import android.net.IIpSecService;
+import android.net.INetd;
+import android.net.IpSecAlgorithm;
+import android.net.IpSecConfig;
+import android.net.IpSecManager;
+import android.net.IpSecTransform;
+import android.net.util.NetdService;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/** @hide */
+public class IpSecService extends IIpSecService.Stub {
+ private static final String TAG = "IpSecService";
+ private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final String NETD_SERVICE_NAME = "netd";
+ private static final int[] DIRECTIONS =
+ new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN};
+
+ /** Binder context for this service */
+ private final Context mContext;
+
+ private Object mLock = new Object();
+
+ private static final int NETD_FETCH_TIMEOUT = 5000; //ms
+
+ private AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0);
+
+ private abstract class ManagedResource implements IBinder.DeathRecipient {
+ final int pid;
+ final int uid;
+ private IBinder mBinder;
+
+ ManagedResource(IBinder binder) {
+ super();
+ mBinder = binder;
+ pid = Binder.getCallingPid();
+ uid = Binder.getCallingUid();
+
+ try {
+ mBinder.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ binderDied();
+ }
+ }
+
+ /**
+ * When this record is no longer needed for managing system resources this function should
+ * unlink all references held by the record to allow efficient garbage collection.
+ */
+ public final void release() {
+ //Release all the underlying system resources first
+ releaseResources();
+
+ if (mBinder != null) {
+ mBinder.unlinkToDeath(this, 0);
+ }
+ mBinder = null;
+
+ //remove this record so that it can be cleaned up
+ nullifyRecord();
+ }
+
+ /**
+ * If the Binder object dies, this function is called to free the system resources that are
+ * being managed by this record and to subsequently release this record for garbage
+ * collection
+ */
+ public final void binderDied() {
+ release();
+ }
+
+ /**
+ * Implement this method to release all object references contained in the subclass to allow
+ * efficient garbage collection of the record. This should remove any references to the
+ * record from all other locations that hold a reference as the record is no longer valid.
+ */
+ protected abstract void nullifyRecord();
+
+ /**
+ * Implement this method to release all system resources that are being protected by this
+ * record. Once the resources are released, the record should be invalidated and no longer
+ * used by calling releaseRecord()
+ */
+ protected abstract void releaseResources();
+ };
+
+ private final class TransformRecord extends ManagedResource {
+ private IpSecConfig mConfig;
+ private int mResourceId;
+
+ TransformRecord(IpSecConfig config, int resourceId, IBinder binder) {
+ super(binder);
+ mConfig = config;
+ mResourceId = resourceId;
+ }
+
+ public IpSecConfig getConfig() {
+ return mConfig;
+ }
+
+ @Override
+ protected void releaseResources() {
+ for (int direction : DIRECTIONS) {
+ try {
+ getNetdInstance()
+ .ipSecDeleteSecurityAssociation(
+ mResourceId,
+ direction,
+ (mConfig.getLocalAddress() != null)
+ ? mConfig.getLocalAddress().getHostAddress()
+ : "",
+ (mConfig.getRemoteAddress() != null)
+ ? mConfig.getRemoteAddress().getHostAddress()
+ : "",
+ mConfig.getSpi(direction));
+ } 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);
+ }
+ }
+ }
+
+ @Override
+ protected void nullifyRecord() {
+ mConfig = null;
+ mResourceId = INVALID_RESOURCE_ID;
+ }
+ }
+
+ private final class SpiRecord extends ManagedResource {
+ private final int mDirection;
+ private final String mLocalAddress;
+ private final String mRemoteAddress;
+ private final IBinder mBinder;
+ private int mSpi;
+ private int mResourceId;
+
+ SpiRecord(
+ int resourceId,
+ int direction,
+ String localAddress,
+ String remoteAddress,
+ int spi,
+ IBinder binder) {
+ super(binder);
+ mResourceId = resourceId;
+ mDirection = direction;
+ mLocalAddress = localAddress;
+ mRemoteAddress = remoteAddress;
+ mSpi = spi;
+ mBinder = binder;
+ }
+
+ protected void releaseResources() {
+ try {
+ getNetdInstance()
+ .ipSecDeleteSecurityAssociation(
+ mResourceId, mDirection, mLocalAddress, mRemoteAddress, mSpi);
+ } 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);
+ }
+ }
+
+ protected void nullifyRecord() {
+ mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
+ mResourceId = INVALID_RESOURCE_ID;
+ }
+ }
+
+ @GuardedBy("mSpiRecords")
+ private final SparseArray<SpiRecord> mSpiRecords = new SparseArray<>();
+
+ @GuardedBy("mTransformRecords")
+ private final SparseArray<TransformRecord> mTransformRecords = new SparseArray<>();
+
+ /**
+ * Constructs a new IpSecService instance
+ *
+ * @param context Binder context for this service
+ */
+ private IpSecService(Context context) {
+ mContext = context;
+ }
+
+ static IpSecService create(Context context) throws InterruptedException {
+ final IpSecService service = new IpSecService(context);
+ service.connectNativeNetdService();
+ return service;
+ }
+
+ public void systemReady() {
+ if (isNetdAlive()) {
+ Slog.d(TAG, "IpSecService is ready");
+ } else {
+ Slog.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
+ }
+ }
+
+ private void connectNativeNetdService() {
+ // Avoid blocking the system server to do this
+ Thread t =
+ new Thread(
+ new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ NetdService.get(NETD_FETCH_TIMEOUT);
+ }
+ }
+ });
+ t.run();
+ }
+
+ INetd getNetdInstance() throws RemoteException {
+ final INetd netd = NetdService.getInstance();
+ if (netd == null) {
+ throw new RemoteException("Failed to Get Netd Instance");
+ }
+ return netd;
+ }
+
+ boolean isNetdAlive() {
+ synchronized (mLock) {
+ try {
+ final INetd netd = getNetdInstance();
+ if (netd == null) {
+ return false;
+ }
+ return netd.isAlive();
+ } catch (RemoteException re) {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ /** Get a new SPI and maintain the reservation in the system server */
+ public Bundle reserveSecurityParameterIndex(
+ int direction, String remoteAddress, int requestedSpi, IBinder binder)
+ throws RemoteException {
+ int resourceId = mNextResourceId.getAndIncrement();
+
+ int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
+ String localAddress = "";
+ Bundle retBundle = new Bundle(3);
+ try {
+ spi =
+ getNetdInstance()
+ .ipSecAllocateSpi(
+ resourceId,
+ direction,
+ localAddress,
+ remoteAddress,
+ requestedSpi);
+ Log.d(TAG, "Allocated SPI " + spi);
+ retBundle.putInt(KEY_STATUS, IpSecManager.Status.OK);
+ retBundle.putInt(KEY_RESOURCE_ID, resourceId);
+ retBundle.putInt(KEY_SPI, spi);
+ synchronized (mSpiRecords) {
+ mSpiRecords.put(
+ resourceId,
+ new SpiRecord(
+ resourceId, direction, localAddress, remoteAddress, spi, binder));
+ }
+ } catch (ServiceSpecificException e) {
+ // TODO: Add appropriate checks when other ServiceSpecificException types are supported
+ retBundle.putInt(KEY_STATUS, IpSecManager.Status.SPI_UNAVAILABLE);
+ retBundle.putInt(KEY_RESOURCE_ID, resourceId);
+ retBundle.putInt(KEY_SPI, spi);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ return retBundle;
+ }
+
+ /** Release a previously allocated SPI that has been registered with the system server */
+ @Override
+ public void releaseSecurityParameterIndex(int resourceId) throws RemoteException {}
+
+ /**
+ * Open a socket via the system server and bind it to the specified port (random if port=0).
+ * This will return a PFD to the user that represent a bound UDP socket. The system server will
+ * cache the socket and a record of its owner so that it can and must be freed when no longer
+ * needed.
+ */
+ @Override
+ public Bundle openUdpEncapsulationSocket(int port, IBinder binder) throws RemoteException {
+ return null;
+ }
+
+ /** close a socket that has been been allocated by and registered with the system server */
+ @Override
+ public void closeUdpEncapsulationSocket(ParcelFileDescriptor socket) {}
+
+ /**
+ * Create a transport mode transform, which represent two security associations (one in each
+ * direction) in the kernel. The transform will be cached by the system server and must be freed
+ * when no longer needed. It is possible to free one, deleting the SA from underneath sockets
+ * that are using it, which will result in all of those sockets becoming unable to send or
+ * receive data.
+ */
+ @Override
+ public Bundle createTransportModeTransform(IpSecConfig c, IBinder binder)
+ throws RemoteException {
+ // TODO: Basic input validation here since it's coming over the Binder
+ int resourceId = mNextResourceId.getAndIncrement();
+ for (int direction : DIRECTIONS) {
+ IpSecAlgorithm auth = c.getAuthentication(direction);
+ IpSecAlgorithm crypt = c.getEncryption(direction);
+ try {
+ int result =
+ getNetdInstance()
+ .ipSecAddSecurityAssociation(
+ resourceId,
+ c.getMode(),
+ direction,
+ (c.getLocalAddress() != null)
+ ? c.getLocalAddress().getHostAddress()
+ : "",
+ (c.getRemoteAddress() != null)
+ ? c.getRemoteAddress().getHostAddress()
+ : "",
+ (c.getNetwork() != null)
+ ? c.getNetwork().getNetworkHandle()
+ : 0,
+ c.getSpi(direction),
+ (auth != null) ? auth.getName() : "",
+ (auth != null) ? auth.getKey() : null,
+ (auth != null) ? auth.getTruncationLengthBits() : 0,
+ (crypt != null) ? crypt.getName() : "",
+ (crypt != null) ? crypt.getKey() : null,
+ (crypt != null) ? crypt.getTruncationLengthBits() : 0,
+ c.getEncapType(),
+ c.getEncapLocalPort(),
+ c.getEncapRemotePort());
+ if (result != c.getSpi(direction)) {
+ // TODO: cleanup the first SA if creation of second SA fails
+ Bundle retBundle = new Bundle(2);
+ retBundle.putInt(KEY_STATUS, IpSecManager.Status.SPI_UNAVAILABLE);
+ retBundle.putInt(KEY_RESOURCE_ID, INVALID_RESOURCE_ID);
+ return retBundle;
+ }
+ } catch (ServiceSpecificException e) {
+ // FIXME: get the error code and throw is at an IOException from Errno Exception
+ }
+ }
+ synchronized (mTransformRecords) {
+ mTransformRecords.put(resourceId, new TransformRecord(c, resourceId, binder));
+ }
+
+ Bundle retBundle = new Bundle(2);
+ retBundle.putInt(KEY_STATUS, IpSecManager.Status.OK);
+ retBundle.putInt(KEY_RESOURCE_ID, resourceId);
+ return retBundle;
+ }
+
+ /**
+ * Delete a transport mode transform that was previously allocated by + registered with the
+ * system server. If this is called on an inactive (or non-existent) transform, it will not
+ * return an error. It's safe to de-allocate transforms that may have already been deleted for
+ * other reasons.
+ */
+ @Override
+ public void deleteTransportModeTransform(int resourceId) throws RemoteException {
+ synchronized (mTransformRecords) {
+ TransformRecord record;
+ // We want to non-destructively get so that we can check credentials before removing
+ // this from the records.
+ record = mTransformRecords.get(resourceId);
+
+ if (record == null) {
+ throw new IllegalArgumentException(
+ "Transform " + resourceId + " is not available to be deleted");
+ }
+
+ if (record.pid != Binder.getCallingPid() || record.uid != Binder.getCallingUid()) {
+ throw new SecurityException("Only the owner of an IpSec Transform may delete it!");
+ }
+
+ // TODO: if releaseResources() throws RemoteException, we can try again to clean up on
+ // binder death. Need to make sure that path is actually functional.
+ record.releaseResources();
+ mTransformRecords.remove(resourceId);
+ record.nullifyRecord();
+ }
+ }
+
+ /**
+ * Apply an active transport mode transform to a socket, which will apply the IPsec security
+ * association as a correspondent policy to the provided socket
+ */
+ @Override
+ public void applyTransportModeTransform(ParcelFileDescriptor socket, int resourceId)
+ throws RemoteException {
+
+ synchronized (mTransformRecords) {
+ TransformRecord info;
+ // FIXME: this code should be factored out into a security check + getter
+ info = mTransformRecords.get(resourceId);
+
+ if (info == null) {
+ throw new IllegalArgumentException("Transform " + resourceId + " is not active");
+ }
+
+ // TODO: make this a function.
+ if (info.pid != getCallingPid() || info.uid != getCallingUid()) {
+ throw new SecurityException("Only the owner of an IpSec Transform may apply it!");
+ }
+
+ IpSecConfig c = info.getConfig();
+ try {
+ for (int direction : DIRECTIONS) {
+ getNetdInstance()
+ .ipSecApplyTransportModeTransform(
+ socket.getFileDescriptor(),
+ resourceId,
+ direction,
+ (c.getLocalAddress() != null)
+ ? c.getLocalAddress().getHostAddress()
+ : "",
+ (c.getRemoteAddress() != null)
+ ? c.getRemoteAddress().getHostAddress()
+ : "",
+ c.getSpi(direction));
+ }
+ } catch (ServiceSpecificException e) {
+ // FIXME: get the error code and throw is at an IOException from Errno Exception
+ }
+ }
+ }
+ /**
+ * Remove a transport mode transform from a socket, applying the default (empty) policy. This
+ * will ensure that NO IPsec policy is applied to the socket (would be the equivalent of
+ * applying a policy that performs no IPsec). Today the resourceId parameter is passed but not
+ * used: reserved for future improved input validation.
+ */
+ @Override
+ public void removeTransportModeTransform(ParcelFileDescriptor socket, int resourceId)
+ throws RemoteException {
+ try {
+ getNetdInstance().ipSecRemoveTransportModeTransform(socket.getFileDescriptor());
+ } catch (ServiceSpecificException e) {
+ // FIXME: get the error code and throw is at an IOException from Errno Exception
+ }
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+
+ pw.println("IpSecService Log:");
+ pw.println("NetdNativeService Connection: " + (isNetdAlive() ? "alive" : "dead"));
+ pw.println();
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1feaa72..9a12aeb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3790,8 +3790,13 @@
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// Debuggable apps may include a wrapper script with their library directory.
String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
- if (new File(wrapperFileName).exists()) {
- invokeWith = "/system/bin/logwrapper " + wrapperFileName;
+ StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+ try {
+ if (new File(wrapperFileName).exists()) {
+ invokeWith = "/system/bin/logwrapper " + wrapperFileName;
+ }
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
}
}
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java
index 8c18c46..0412db5 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/services/core/java/com/android/server/am/LockTaskNotify.java
@@ -20,6 +20,8 @@
import android.content.Context;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemClock;
+import android.util.Slog;
import android.view.WindowManager;
import android.widget.Toast;
@@ -31,10 +33,12 @@
*/
public class LockTaskNotify {
private static final String TAG = "LockTaskNotify";
+ private static final long SHOW_TOAST_MINIMUM_INTERVAL = 1000;
private final Context mContext;
private final H mHandler;
private Toast mLastToast;
+ private long mLastShowToastTime;
public LockTaskNotify(Context context) {
mContext = context;
@@ -55,10 +59,16 @@
if (text == null) {
return;
}
+ long showToastTime = SystemClock.elapsedRealtime();
+ if ((showToastTime - mLastShowToastTime) < SHOW_TOAST_MINIMUM_INTERVAL) {
+ Slog.i(TAG, "Ignore toast since it is requested in very short interval.");
+ return;
+ }
if (mLastToast != null) {
mLastToast.cancel();
}
mLastToast = makeAllUserToastAndShow(text);
+ mLastShowToastTime = showToastTime;
}
public void show(boolean starting) {
diff --git a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
index 4f68652..77b86d8 100644
--- a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
+++ b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
@@ -19,7 +19,20 @@
import android.os.SystemProperties;
public class MockableSystemProperties {
+
+ public String get(String key) {
+ return SystemProperties.get(key);
+ }
+
+ public int getInt(String key, int def) {
+ return SystemProperties.getInt(key, def);
+ }
+
public boolean getBoolean(String key, boolean def) {
return SystemProperties.getBoolean(key, def);
}
+
+ public void set(String key, String value) {
+ SystemProperties.set(key, value);
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 58c76ec..46f76b1 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -15,6 +15,7 @@
*/
package com.android.server.connectivity;
+import android.annotation.WorkerThread;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -73,7 +74,7 @@
public static final String KEY_PROXY = "keyProxy";
private String mCurrentPac;
@GuardedBy("mProxyLock")
- private Uri mPacUrl = Uri.EMPTY;
+ private volatile Uri mPacUrl = Uri.EMPTY;
private AlarmManager mAlarmManager;
@GuardedBy("mProxyLock")
@@ -86,29 +87,34 @@
private int mCurrentDelay;
private int mLastPort;
- private boolean mHasSentBroadcast;
- private boolean mHasDownloaded;
+ private volatile boolean mHasSentBroadcast;
+ private volatile boolean mHasDownloaded;
private Handler mConnectivityHandler;
private int mProxyMessage;
/**
- * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
+ * Used for locking when setting mProxyService and all references to mCurrentPac.
*/
private final Object mProxyLock = new Object();
+ /**
+ * Runnable to download PAC script.
+ * The behavior relies on the assamption it always run on mNetThread to guarantee that the
+ * latest data fetched from mPacUrl is stored in mProxyService.
+ */
private Runnable mPacDownloader = new Runnable() {
@Override
+ @WorkerThread
public void run() {
String file;
- synchronized (mProxyLock) {
- if (Uri.EMPTY.equals(mPacUrl)) return;
- try {
- file = get(mPacUrl);
- } catch (IOException ioe) {
- file = null;
- Log.w(TAG, "Failed to load PAC file: " + ioe);
- }
+ final Uri pacUrl = mPacUrl;
+ if (Uri.EMPTY.equals(pacUrl)) return;
+ try {
+ file = get(pacUrl);
+ } catch (IOException ioe) {
+ file = null;
+ Log.w(TAG, "Failed to load PAC file: " + ioe);
}
if (file != null) {
synchronized (mProxyLock) {
@@ -171,9 +177,7 @@
// Allow to send broadcast, nothing to do.
return false;
}
- synchronized (mProxyLock) {
- mPacUrl = proxy.getPacFileUrl();
- }
+ mPacUrl = proxy.getPacFileUrl();
mCurrentDelay = DELAY_1;
mHasSentBroadcast = false;
mHasDownloaded = false;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index a53d19c..693292a 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1584,14 +1584,14 @@
pw.println("Tethering:");
pw.increaseIndent();
- final TetheringConfiguration cfg = mConfig;
- pw.print("preferredUpstreamIfaceTypes:");
- synchronized (mPublicSync) {
- for (Integer netType : cfg.preferredUpstreamIfaceTypes) {
- pw.print(" " + ConnectivityManager.getNetworkTypeName(netType));
- }
- pw.println();
+ pw.println("Configuration:");
+ pw.increaseIndent();
+ final TetheringConfiguration cfg = mConfig;
+ cfg.dump(pw);
+ pw.decreaseIndent();
+
+ synchronized (mPublicSync) {
pw.println("Tether state:");
pw.increaseIndent();
for (int i = 0; i < mTetherStates.size(); i++) {
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a5876dd..584994a 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -32,7 +32,6 @@
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -132,6 +131,7 @@
private NetworkAgent mNetworkAgent;
private final Looper mLooper;
private final NetworkCapabilities mNetworkCapabilities;
+ private final SystemServices mSystemServices;
/**
* Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
@@ -199,7 +199,7 @@
final boolean isPackageRemoved = !intent.getBooleanExtra(
Intent.EXTRA_REPLACING, false);
if (isPackageRemoved) {
- setAndSaveAlwaysOnPackage(null, false);
+ setAlwaysOnPackage(null, false);
}
break;
}
@@ -210,11 +210,18 @@
private boolean mIsPackageIntentReceiverRegistered = false;
public Vpn(Looper looper, Context context, INetworkManagementService netService,
- int userHandle) {
+ @UserIdInt int userHandle) {
+ this(looper, context, netService, userHandle, new SystemServices(context));
+ }
+
+ @VisibleForTesting
+ protected Vpn(Looper looper, Context context, INetworkManagementService netService,
+ int userHandle, SystemServices systemServices) {
mContext = context;
mNetd = netService;
mUserHandle = userHandle;
mLooper = looper;
+ mSystemServices = systemServices;
mPackage = VpnConfig.LEGACY_VPN;
mOwnerUID = getAppUid(mPackage, mUserHandle);
@@ -230,6 +237,8 @@
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+
+ loadAlwaysOnPackage();
}
/**
@@ -268,6 +277,26 @@
*/
public synchronized boolean setAlwaysOnPackage(String packageName, boolean lockdown) {
enforceControlPermissionOrInternalCaller();
+
+ if (setAlwaysOnPackageInternal(packageName, lockdown)) {
+ saveAlwaysOnPackage();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Configures an always-on VPN connection through a specific application, the same as
+ * {@link #setAlwaysOnPackage}.
+ *
+ * Does not perform permission checks. Does not persist any of the changes to storage.
+ *
+ * @param packageName the package to designate as always-on VPN supplier.
+ * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
+ * @return {@code true} if the package has been set as always-on, {@code false} otherwise.
+ */
+ @GuardedBy("this")
+ private boolean setAlwaysOnPackageInternal(String packageName, boolean lockdown) {
if (VpnConfig.LEGACY_VPN.equals(packageName)) {
Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on.");
return false;
@@ -340,13 +369,13 @@
/**
* Save the always-on package and lockdown config into Settings.Secure
*/
- public synchronized void saveAlwaysOnPackage() {
+ @GuardedBy("this")
+ private void saveAlwaysOnPackage() {
final long token = Binder.clearCallingIdentity();
try {
- final ContentResolver cr = mContext.getContentResolver();
- Settings.Secure.putStringForUser(cr, Settings.Secure.ALWAYS_ON_VPN_APP,
+ mSystemServices.settingsSecurePutStringForUser(Settings.Secure.ALWAYS_ON_VPN_APP,
getAlwaysOnPackage(), mUserHandle);
- Settings.Secure.putIntForUser(cr, Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
+ mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
(mLockdown ? 1 : 0), mUserHandle);
} finally {
Binder.restoreCallingIdentity(token);
@@ -354,18 +383,19 @@
}
/**
- * Set and save always-on package and lockdown config
- * @see Vpn#setAlwaysOnPackage(String, boolean)
- * @see Vpn#saveAlwaysOnPackage()
- *
- * @return result of Vpn#setAndSaveAlwaysOnPackage(String, boolean)
+ * Load the always-on package and lockdown config from Settings.Secure
*/
- private synchronized boolean setAndSaveAlwaysOnPackage(String packageName, boolean lockdown) {
- if (setAlwaysOnPackage(packageName, lockdown)) {
- saveAlwaysOnPackage();
- return true;
- } else {
- return false;
+ @GuardedBy("this")
+ private void loadAlwaysOnPackage() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final String alwaysOnPackage = mSystemServices.settingsSecureGetStringForUser(
+ Settings.Secure.ALWAYS_ON_VPN_APP, mUserHandle);
+ final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser(
+ Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserHandle) != 0;
+ setAlwaysOnPackageInternal(alwaysOnPackage, alwaysOnLockdown);
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -1257,11 +1287,7 @@
private void updateAlwaysOnNotification(DetailedState networkState) {
final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
- updateAlwaysOnNotificationInternal(visible);
- }
- @VisibleForTesting
- protected void updateAlwaysOnNotificationInternal(boolean visible) {
final UserHandle user = UserHandle.of(mUserHandle);
final long token = Binder.clearCallingIdentity();
try {
@@ -1271,10 +1297,8 @@
return;
}
final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
- final PendingIntent configIntent = PendingIntent.getActivityAsUser(
- mContext, /* request */ 0, intent,
- PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
- null, user);
+ final PendingIntent configIntent = mSystemServices.pendingIntentGetActivityAsUser(
+ intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, user);
final Notification.Builder builder = new Notification.Builder(mContext)
.setDefaults(0)
.setSmallIcon(R.drawable.vpn_connected)
@@ -1292,6 +1316,58 @@
}
}
+ /**
+ * Facade for system service calls that change, or depend on, state outside of
+ * {@link ConnectivityService} and have hard-to-mock interfaces.
+ *
+ * @see com.android.server.connectivity.VpnTest
+ */
+ @VisibleForTesting
+ public static class SystemServices {
+ private final Context mContext;
+
+ public SystemServices(@NonNull Context context) {
+ mContext = context;
+ }
+
+ /**
+ * @see PendingIntent#getActivityAsUser()
+ */
+ public PendingIntent pendingIntentGetActivityAsUser(
+ Intent intent, int flags, UserHandle user) {
+ return PendingIntent.getActivityAsUser(mContext, 0 /*request*/, intent, flags,
+ null /*options*/, user);
+ }
+
+ /**
+ * @see Settings.Secure#putStringForUser
+ */
+ public void settingsSecurePutStringForUser(String key, String value, int userId) {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(), key, value, userId);
+ }
+
+ /**
+ * @see Settings.Secure#putIntForUser
+ */
+ public void settingsSecurePutIntForUser(String key, int value, int userId) {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userId);
+ }
+
+ /**
+ * @see Settings.Secure#getStringForUser
+ */
+ public String settingsSecureGetStringForUser(String key, int userId) {
+ return Settings.Secure.getStringForUser(mContext.getContentResolver(), key, userId);
+ }
+
+ /**
+ * @see Settings.Secure#getIntForUser
+ */
+ public int settingsSecureGetIntForUser(String key, int def, int userId) {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(), key, def, userId);
+ }
+ }
+
private native int jniCreate(int mtu);
private native String jniGetName(int tun);
private native int jniSetAddresses(String interfaze, String addresses);
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
index dec2f77..8c6430c 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
@@ -16,6 +16,8 @@
package com.android.server.connectivity.tethering;
+import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
+
import android.net.INetd;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -48,7 +50,6 @@
public class IPv6TetheringInterfaceServices {
private static final String TAG = IPv6TetheringInterfaceServices.class.getSimpleName();
private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
- private static final int RFC7421_IP_PREFIX_LENGTH = 64;
private final String mIfName;
private final INetworkManagementService mNMService;
@@ -124,7 +125,7 @@
params.hasDefaultRoute = v6only.hasIPv6DefaultRoute();
for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
- if (linkAddr.getPrefixLength() != RFC7421_IP_PREFIX_LENGTH) continue;
+ if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue;
final IpPrefix prefix = new IpPrefix(
linkAddr.getAddress(), linkAddr.getPrefixLength());
@@ -206,7 +207,7 @@
for (Inet6Address dns : deprecatedDnses) {
final String dnsString = dns.getHostAddress();
try {
- netd.interfaceDelAddress(mIfName, dnsString, RFC7421_IP_PREFIX_LENGTH);
+ netd.interfaceDelAddress(mIfName, dnsString, RFC7421_PREFIX_LENGTH);
} catch (ServiceSpecificException | RemoteException e) {
Log.e(TAG, "Failed to remove local dns IP: " + dnsString, e);
}
@@ -223,7 +224,7 @@
for (Inet6Address dns : addedDnses) {
final String dnsString = dns.getHostAddress();
try {
- netd.interfaceAddAddress(mIfName, dnsString, RFC7421_IP_PREFIX_LENGTH);
+ netd.interfaceAddAddress(mIfName, dnsString, RFC7421_PREFIX_LENGTH);
} catch (ServiceSpecificException | RemoteException e) {
Log.e(TAG, "Failed to add local dns IP: " + dnsString, e);
newDnses.remove(dns);
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 14d06cc..d38beb3 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -22,12 +22,15 @@
import android.content.Context;
import android.content.res.Resources;
+import android.net.ConnectivityManager;
import android.telephony.TelephonyManager;
import android.util.Log;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.StringJoiner;
/**
@@ -97,6 +100,44 @@
return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
}
+ public void dump(PrintWriter pw) {
+ dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
+ dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
+ dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
+
+ pw.print("isDunRequired: ");
+ pw.println(isDunRequired);
+
+ String[] upstreamTypes = null;
+ if (preferredUpstreamIfaceTypes != null) {
+ upstreamTypes = new String[preferredUpstreamIfaceTypes.size()];
+ int i = 0;
+ for (Integer netType : preferredUpstreamIfaceTypes) {
+ upstreamTypes[i] = ConnectivityManager.getNetworkTypeName(netType);
+ i++;
+ }
+ }
+ dumpStringArray(pw, "preferredUpstreamIfaceTypes", upstreamTypes);
+
+ dumpStringArray(pw, "dhcpRanges", dhcpRanges);
+ dumpStringArray(pw, "defaultIPv4DNS", defaultIPv4DNS);
+ }
+
+ private static void dumpStringArray(PrintWriter pw, String label, String[] values) {
+ pw.print(label);
+ pw.print(": ");
+
+ if (values != null) {
+ final StringJoiner sj = new StringJoiner(", ", "[", "]");
+ for (String value : values) { sj.add(value); }
+ pw.print(sj.toString());
+ } else {
+ pw.print("null");
+ }
+
+ pw.println();
+ }
+
private static boolean checkDunRequired(Context ctx) {
final TelephonyManager tm = ctx.getSystemService(TelephonyManager.class);
final int secureSetting =
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 4658c046..060dd73 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -381,6 +381,7 @@
mContext.unregisterReceiver(mTetherReceiver);
mContext.unregisterReceiver(mPollReceiver);
mContext.unregisterReceiver(mRemovedReceiver);
+ mContext.unregisterReceiver(mUserReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 7aa96cf..d364d17 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -49,8 +49,6 @@
private static final boolean DEBUG = false;
- private static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
-
private static final int JOB_IDLE_OPTIMIZE = 800;
private static final int JOB_POST_BOOT_UPDATE = 801;
@@ -292,8 +290,8 @@
PackageManagerService.REASON_BACKGROUND_DEXOPT,
/* force */ false)
: pm.performDexOptSecondary(pkg,
- PackageManagerServiceCompilerMapping.getFullCompilerFilter(),
- /* force */ true);
+ PackageManagerService.REASON_BACKGROUND_DEXOPT,
+ /* force */ false);
if (success) {
// Dexopt succeeded, remove package from the list of failing ones.
synchronized (failedPackageNames) {
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 9418e74..1498693 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -213,6 +213,7 @@
if (getAvailableSpace() > 0) {
dexoptCommandCountExecuted++;
+ Log.d(TAG, "Next command: " + next);
return next;
} else {
if (DEBUG_DEXOPT) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9452219..2b7e9b9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7516,6 +7516,11 @@
return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force);
}
+ public boolean performDexOptSecondary(String packageName, int compileReason,
+ boolean force) {
+ return mDexManager.dexoptSecondaryDex(packageName, compileReason, force);
+ }
+
/**
* Reconcile the information we have about the secondary dex files belonging to
* {@code packagName} and the actual dex files. For all dex files that were
@@ -7738,6 +7743,7 @@
} catch (InstallerException e) {
Slog.w(TAG, String.valueOf(e));
}
+ mDexManager.notifyPackageDataDestroyed(pkg.packageName, userId);
}
}
@@ -9234,9 +9240,9 @@
ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi
+ " (requirer="
- + (requirer == null ? "null" : requirer.pkg.packageName)
+ + (requirer != null ? requirer.pkg : "null")
+ ", scannedPackage="
- + (scannedPackage != null ? scannedPackage.packageName : "null")
+ + (scannedPackage != null ? scannedPackage : "null")
+ ")");
try {
mInstaller.rmdex(ps.codePathString,
@@ -14449,6 +14455,8 @@
}
prepareAppDataAfterInstallLIF(newPackage);
addedPkg = true;
+ mDexManager.notifyPackageUpdated(newPackage.packageName,
+ newPackage.baseCodePath, newPackage.splitCodePaths);
} catch (PackageManagerException e) {
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
@@ -14596,6 +14604,9 @@
updateSettingsLI(newPackage, installerPackageName, allUsers, res, user);
prepareAppDataAfterInstallLIF(newPackage);
+
+ mDexManager.notifyPackageUpdated(newPackage.packageName,
+ newPackage.baseCodePath, newPackage.splitCodePaths);
}
} catch (PackageManagerException e) {
res.setReturnCode(INSTALL_FAILED_INTERNAL_ERROR);
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 01124e2..a904d17 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -22,6 +22,7 @@
import android.content.pm.PackageParser;
import android.os.RemoteException;
import android.os.storage.StorageManager;
+import android.os.UserHandle;
import android.util.Slog;
@@ -179,17 +180,64 @@
}
}
- public void notifyPackageInstalled(PackageInfo info, int userId) {
- cachePackageCodeLocation(info, userId);
+ /**
+ * Notifies that a new package was installed for {@code userId}.
+ * {@code userId} must not be {@code UserHandle.USER_ALL}.
+ *
+ * @throws IllegalArgumentException if {@code userId} is {@code UserHandle.USER_ALL}.
+ */
+ public void notifyPackageInstalled(PackageInfo pi, int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ throw new IllegalArgumentException(
+ "notifyPackageInstalled called with USER_ALL");
+ }
+ cachePackageCodeLocation(pi.packageName, pi.applicationInfo.sourceDir,
+ pi.applicationInfo.splitSourceDirs, pi.applicationInfo.dataDir, userId);
}
- private void cachePackageCodeLocation(PackageInfo info, int userId) {
- PackageCodeLocations pcl = mPackageCodeLocationsCache.get(info.packageName);
- if (pcl != null) {
- pcl.mergeAppDataDirs(info.applicationInfo, userId);
- } else {
- mPackageCodeLocationsCache.put(info.packageName,
- new PackageCodeLocations(info.applicationInfo, userId));
+ /**
+ * Notifies that package {@code packageName} was updated.
+ * This will clear the UsedByOtherApps mark if it exists.
+ */
+ public void notifyPackageUpdated(String packageName, String baseCodePath,
+ String[] splitCodePaths) {
+ cachePackageCodeLocation(packageName, baseCodePath, splitCodePaths, null, /*userId*/ -1);
+ // In case there was an update, write the package use info to disk async.
+ // Note that we do the writing here and not in PackageDexUsage in order to be
+ // consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs
+ // multiple updates in PackaeDexUsage before writing it).
+ if (mPackageDexUsage.clearUsedByOtherApps(packageName)) {
+ mPackageDexUsage.maybeWriteAsync();
+ }
+ }
+
+ /**
+ * Notifies that the user {@code userId} data for package {@code packageName}
+ * was destroyed. This will remove all usage info associated with the package
+ * for the given user.
+ * {@code userId} is allowed to be {@code UserHandle.USER_ALL} in which case
+ * all usage information for the package will be removed.
+ */
+ public void notifyPackageDataDestroyed(String packageName, int userId) {
+ boolean updated = userId == UserHandle.USER_ALL
+ ? mPackageDexUsage.removePackage(packageName)
+ : mPackageDexUsage.removeUserPackage(packageName, userId);
+ // In case there was an update, write the package use info to disk async.
+ // Note that we do the writing here and not in PackageDexUsage in order to be
+ // consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs
+ // multiple updates in PackaeDexUsage before writing it).
+ if (updated) {
+ mPackageDexUsage.maybeWriteAsync();
+ }
+ }
+
+ public void cachePackageCodeLocation(String packageName, String baseCodePath,
+ String[] splitCodePaths, String dataDir, int userId) {
+ PackageCodeLocations pcl = putIfAbsent(mPackageCodeLocationsCache, packageName,
+ new PackageCodeLocations(packageName, baseCodePath, splitCodePaths));
+ pcl.updateCodeLocation(baseCodePath, splitCodePaths);
+ if (dataDir != null) {
+ pcl.mergeAppDataDirs(dataDir, userId);
}
}
@@ -202,7 +250,8 @@
int userId = entry.getKey();
for (PackageInfo pi : packageInfoList) {
// Cache the code locations.
- cachePackageCodeLocation(pi, userId);
+ cachePackageCodeLocation(pi.packageName, pi.applicationInfo.sourceDir,
+ pi.applicationInfo.splitSourceDirs, pi.applicationInfo.dataDir, userId);
// Cache a map from package name to the set of user ids who installed the package.
// We will use it to sync the data and remove obsolete entries from
@@ -230,6 +279,17 @@
* @return true if all secondary dex files were processed successfully (compiled or skipped
* because they don't need to be compiled)..
*/
+ public boolean dexoptSecondaryDex(String packageName, int compilerReason, boolean force) {
+ return dexoptSecondaryDex(packageName,
+ PackageManagerServiceCompilerMapping.getCompilerFilterForReason(compilerReason),
+ force);
+ }
+
+ /**
+ * Perform dexopt on the package {@code packageName} secondary dex files.
+ * @return true if all secondary dex files were processed successfully (compiled or skipped
+ * because they don't need to be compiled)..
+ */
public boolean dexoptSecondaryDex(String packageName, String compilerFilter, boolean force) {
// Select the dex optimizer based on the force parameter.
// Forced compilation is done through ForcedUpdatePackageDexOptimizer which will adjust
@@ -383,7 +443,7 @@
// Ignore framework code.
// TODO(calin): is there a better way to detect it?
if (dexPath.startsWith("/system/framework/")) {
- new DexSearchResult("framework", DEX_SEARCH_NOT_FOUND);
+ return new DexSearchResult("framework", DEX_SEARCH_NOT_FOUND);
}
// First, check if the package which loads the dex file actually owns it.
@@ -425,27 +485,36 @@
*/
private static class PackageCodeLocations {
private final String mPackageName;
- private final String mBaseCodePath;
+ private String mBaseCodePath;
private final Set<String> mSplitCodePaths;
// Maps user id to the application private directory.
private final Map<Integer, Set<String>> mAppDataDirs;
public PackageCodeLocations(ApplicationInfo ai, int userId) {
- mPackageName = ai.packageName;
- mBaseCodePath = ai.sourceDir;
+ this(ai.packageName, ai.sourceDir, ai.splitSourceDirs);
+ mergeAppDataDirs(ai.dataDir, userId);
+ }
+ public PackageCodeLocations(String packageName, String baseCodePath,
+ String[] splitCodePaths) {
+ mPackageName = packageName;
mSplitCodePaths = new HashSet<>();
- if (ai.splitSourceDirs != null) {
- for (String split : ai.splitSourceDirs) {
+ mAppDataDirs = new HashMap<>();
+ updateCodeLocation(baseCodePath, splitCodePaths);
+ }
+
+ public void updateCodeLocation(String baseCodePath, String[] splitCodePaths) {
+ mBaseCodePath = baseCodePath;
+ mSplitCodePaths.clear();
+ if (splitCodePaths != null) {
+ for (String split : splitCodePaths) {
mSplitCodePaths.add(split);
}
}
- mAppDataDirs = new HashMap<>();
- mergeAppDataDirs(ai, userId);
}
- public void mergeAppDataDirs(ApplicationInfo ai, int userId) {
+ public void mergeAppDataDirs(String dataDir, int userId) {
Set<String> dataDirs = putIfAbsent(mAppDataDirs, userId, new HashSet<>());
- dataDirs.add(ai.dataDir);
+ dataDirs.add(dataDir);
}
public int searchDex(String dexPath, int userId) {
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index 3693bce0..8a66f12 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -377,7 +377,34 @@
}
/**
+ * Clears the {@code usesByOtherApps} marker for the package {@code packageName}.
+ * @return true if the package usage info was updated.
+ */
+ public boolean clearUsedByOtherApps(String packageName) {
+ synchronized (mPackageUseInfoMap) {
+ PackageUseInfo packageUseInfo = mPackageUseInfoMap.get(packageName);
+ if (packageUseInfo == null || !packageUseInfo.mIsUsedByOtherApps) {
+ return false;
+ }
+ packageUseInfo.mIsUsedByOtherApps = false;
+ return true;
+ }
+ }
+
+ /**
+ * Remove the usage data associated with package {@code packageName}.
+ * @return true if the package usage was found and removed successfully.
+ */
+ public boolean removePackage(String packageName) {
+ synchronized (mPackageUseInfoMap) {
+ return mPackageUseInfoMap.remove(packageName) != null;
+ }
+ }
+
+ /**
* Remove all the records about package {@code packageName} belonging to user {@code userId}.
+ * If the package is left with no records of secondary dex usage and is not used by other
+ * apps it will be removed as well.
* @return true if the record was found and actually deleted,
* false if the record doesn't exist
*/
@@ -397,6 +424,12 @@
updated = true;
}
}
+ // If no secondary dex info is left and the package is not used by other apps
+ // remove the data since it is now useless.
+ if (packageUseInfo.mDexUseInfoMap.isEmpty() && !packageUseInfo.mIsUsedByOtherApps) {
+ mPackageUseInfoMap.remove(packageName);
+ updated = true;
+ }
return updated;
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index de4a55b..1fca41c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -235,6 +235,15 @@
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
+ //
+ // Default the timezone property to GMT if not set.
+ //
+ String timezoneProperty = SystemProperties.get("persist.sys.timezone");
+ if (timezoneProperty == null || timezoneProperty.isEmpty()) {
+ Slog.w(TAG, "Timezone not set; setting to GMT.");
+ SystemProperties.set("persist.sys.timezone", "GMT");
+ }
+
// If the system has "persist.sys.language" and friends set, replace them with
// "persist.sys.locale". Note that the default locale at this point is calculated
// using the "-Duser.locale" command line flag. That flag is usually populated by
@@ -518,6 +527,7 @@
VibratorService vibrator = null;
IMountService mountService = null;
NetworkManagementService networkManagement = null;
+ IpSecService ipSecService = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
@@ -794,6 +804,15 @@
reportWtf("starting NetworkManagement Service", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+
+ traceBeginAndSlog("StartIpSecService");
+ try {
+ ipSecService = IpSecService.create(context);
+ ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService);
+ } catch (Throwable e) {
+ reportWtf("starting IpSec Service", e);
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
if (!disableNonCoreServices && !disableTextServices) {
@@ -1309,6 +1328,7 @@
final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
final MediaRouterService mediaRouterF = mediaRouter;
final MmsServiceBroker mmsServiceF = mmsService;
+ final IpSecService ipSecServiceF = ipSecService;
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
@@ -1359,6 +1379,13 @@
reportWtf("making Network Managment Service ready", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeIpSecServiceReady");
+ try {
+ if (ipSecServiceF != null) ipSecServiceF.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making IpSec Service ready", e);
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeNetworkStatsServiceReady");
try {
if (networkStatsF != null) networkStatsF.systemReady();
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 76b1c90..745764b 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -605,7 +605,7 @@
}
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- if (args.length > 0 && DUMP_ARG_CONFIRM.equals(args[0])) {
+ if (args != null && args.length > 0 && DUMP_ARG_CONFIRM.equals(args[0])) {
// Execute confirmConfiguration() and take no further action.
confirmConfiguration();
return;
@@ -631,6 +631,13 @@
pw.println();
pw.println(mTag + " connectivity packet log:");
+ pw.println();
+ pw.println("Debug with python and scapy via:");
+ pw.println("shell$ python");
+ pw.println(">>> from scapy import all as scapy");
+ pw.println(">>> scapy.Ether(\"<paste_hex_string>\".decode(\"hex\")).show2()");
+ pw.println();
+
pw.increaseIndent();
mConnectivityPacketLog.readOnlyLocalLog().dump(fd, pw, args);
pw.decreaseIndent();
diff --git a/services/net/java/android/net/util/NetdService.java b/services/net/java/android/net/util/NetdService.java
index 153cb50..6e69ff5 100644
--- a/services/net/java/android/net/util/NetdService.java
+++ b/services/net/java/android/net/util/NetdService.java
@@ -17,7 +17,10 @@
package android.net.util;
import android.net.INetd;
+import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.os.SystemClock;
import android.util.Log;
@@ -27,15 +30,24 @@
public class NetdService {
private static final String TAG = NetdService.class.getSimpleName();
private static final String NETD_SERVICE_NAME = "netd";
+ private static final long BASE_TIMEOUT_MS = 100;
+ private static final long MAX_TIMEOUT_MS = 1000;
+
/**
+ * Return an INetd instance, or null if not available.
+ *
* It is the caller's responsibility to check for a null return value
* and to handle RemoteException errors from invocations on the returned
* interface if, for example, netd dies and is restarted.
*
+ * Returned instances of INetd should not be cached.
+ *
* @return an INetd instance or null.
*/
public static INetd getInstance() {
+ // NOTE: ServiceManager does no caching for the netd service,
+ // because netd is not one of the defined common services.
final INetd netdInstance = INetd.Stub.asInterface(
ServiceManager.getService(NETD_SERVICE_NAME));
if (netdInstance == null) {
@@ -43,4 +55,82 @@
}
return netdInstance;
}
+
+ /**
+ * Blocks for a specified time until an INetd instance is available.
+ *
+ * It is the caller's responsibility to handle RemoteException errors
+ * from invocations on the returned interface if, for example, netd
+ * dies after this interface was returned.
+ *
+ * Returned instances of INetd should not be cached.
+ *
+ * Special values of maxTimeoutMs include: 0, meaning try to obtain an
+ * INetd instance only once, and -1 (or any value less than 0), meaning
+ * try to obtain an INetd instance indefinitely.
+ *
+ * @param maxTimeoutMs the maximum time to spend getting an INetd instance
+ * @return an INetd instance or null if no instance is available
+ * within |maxTimeoutMs| milliseconds.
+ */
+ public static INetd get(long maxTimeoutMs) {
+ if (maxTimeoutMs == 0) return getInstance();
+
+ final long stop = (maxTimeoutMs > 0)
+ ? SystemClock.elapsedRealtime() + maxTimeoutMs
+ : Long.MAX_VALUE;
+
+ long timeoutMs = 0;
+ while (true) {
+ final INetd netdInstance = getInstance();
+ if (netdInstance != null) {
+ return netdInstance;
+ }
+
+ final long remaining = stop - SystemClock.elapsedRealtime();
+ if (remaining <= 0) break;
+
+ // No netdInstance was received; sleep and retry.
+ timeoutMs = Math.min(timeoutMs + BASE_TIMEOUT_MS, MAX_TIMEOUT_MS);
+ timeoutMs = Math.min(timeoutMs, remaining);
+ try {
+ Thread.sleep(timeoutMs);
+ } catch (InterruptedException e) {}
+ }
+ return null;
+ }
+
+ /**
+ * Blocks until an INetd instance is available.
+ *
+ * It is the caller's responsibility to handle RemoteException errors
+ * from invocations on the returned interface if, for example, netd
+ * dies after this interface was returned.
+ *
+ * Returned instances of INetd should not be cached.
+ *
+ * @return an INetd instance.
+ */
+ public static INetd get() {
+ return get(-1);
+ }
+
+ public static interface NetdCommand {
+ void run(INetd netd) throws RemoteException;
+ }
+
+ /**
+ * Blocks until an INetd instance is availabe, and retries until either
+ * the command succeeds or a runtime exception is thrown.
+ */
+ public static void run(NetdCommand cmd) {
+ while (true) {
+ try {
+ cmd.run(get());
+ return;
+ } catch (RemoteException re) {
+ Log.e(TAG, "error communicating with netd: " + re);
+ }
+ }
+ }
}
diff --git a/services/net/java/android/net/util/NetworkConstants.java b/services/net/java/android/net/util/NetworkConstants.java
index 362f757..26f3050 100644
--- a/services/net/java/android/net/util/NetworkConstants.java
+++ b/services/net/java/android/net/util/NetworkConstants.java
@@ -97,6 +97,7 @@
public static final int IPV6_SRC_ADDR_OFFSET = 8;
public static final int IPV6_DST_ADDR_OFFSET = 24;
public static final int IPV6_ADDR_LEN = 16;
+ public static final int RFC7421_PREFIX_LENGTH = 64;
/**
* ICMPv6 constants.
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index 90a2ec0..72fb78e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -16,9 +16,10 @@
package com.android.server.pm.dex;
-import android.os.Build;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.os.Build;
+import android.os.UserHandle;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -57,9 +58,9 @@
private int mUser0;
private int mUser1;
+
@Before
public void setup() {
-
mUser0 = 0;
mUser1 = 1;
@@ -243,6 +244,122 @@
assertSecondaryUse(newPackage, pui, newSecondaries, /*isUsedByOtherApps*/false, mUser0);
}
+ @Test
+ public void testNotifyPackageUpdated() {
+ // Foo loads Bar main apks.
+ notifyDexLoad(mFooUser0, mBarUser0.getBaseAndSplitDexPaths(), mUser0);
+
+ // Bar is used by others now and should be in our records.
+ PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+ assertNotNull(pui);
+ assertTrue(pui.isUsedByOtherApps());
+ assertTrue(pui.getDexUseInfoMap().isEmpty());
+
+ // Notify that bar is updated.
+ mDexManager.notifyPackageUpdated(mBarUser0.getPackageName(),
+ mBarUser0.mPackageInfo.applicationInfo.sourceDir,
+ mBarUser0.mPackageInfo.applicationInfo.splitSourceDirs);
+
+ // The usedByOtherApps flag should be clear now.
+ pui = getPackageUseInfo(mBarUser0);
+ assertNotNull(pui);
+ assertFalse(pui.isUsedByOtherApps());
+ }
+
+ @Test
+ public void testNotifyPackageUpdatedCodeLocations() {
+ // Simulate a split update.
+ String newSplit = mBarUser0.replaceLastSplit();
+ List<String> newSplits = new ArrayList<>();
+ newSplits.add(newSplit);
+
+ // We shouldn't find yet the new split as we didn't notify the package update.
+ notifyDexLoad(mFooUser0, newSplits, mUser0);
+ PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+ assertNull(pui);
+
+ // Notify that bar is updated. splitSourceDirs will contain the updated path.
+ mDexManager.notifyPackageUpdated(mBarUser0.getPackageName(),
+ mBarUser0.mPackageInfo.applicationInfo.sourceDir,
+ mBarUser0.mPackageInfo.applicationInfo.splitSourceDirs);
+
+ // Now, when the split is loaded we will find it and we should mark Bar as usedByOthers.
+ notifyDexLoad(mFooUser0, newSplits, mUser0);
+ pui = getPackageUseInfo(mBarUser0);
+ assertNotNull(pui);
+ assertTrue(pui.isUsedByOtherApps());
+ }
+
+ @Test
+ public void testNotifyPackageDataDestroyForOne() {
+ // Bar loads its own secondary files.
+ notifyDexLoad(mBarUser0, mBarUser0.getSecondaryDexPaths(), mUser0);
+ notifyDexLoad(mBarUser1, mBarUser1.getSecondaryDexPaths(), mUser1);
+
+ mDexManager.notifyPackageDataDestroyed(mBarUser0.getPackageName(), mUser0);
+
+ // Bar should not be around since it was removed for all users.
+ PackageUseInfo pui = getPackageUseInfo(mBarUser1);
+ assertNotNull(pui);
+ assertSecondaryUse(mBarUser1, pui, mBarUser1.getSecondaryDexPaths(),
+ /*isUsedByOtherApps*/false, mUser1);
+ }
+
+ @Test
+ public void testNotifyPackageDataDestroyForeignUse() {
+ // Foo loads its own secondary files.
+ List<String> fooSecondaries = mFooUser0.getSecondaryDexPaths();
+ notifyDexLoad(mFooUser0, fooSecondaries, mUser0);
+
+ // Bar loads Foo main apks.
+ notifyDexLoad(mBarUser0, mFooUser0.getBaseAndSplitDexPaths(), mUser0);
+
+ mDexManager.notifyPackageDataDestroyed(mFooUser0.getPackageName(), mUser0);
+
+ // Foo should still be around since it's used by other apps but with no
+ // secondary dex info.
+ PackageUseInfo pui = getPackageUseInfo(mFooUser0);
+ assertNotNull(pui);
+ assertTrue(pui.isUsedByOtherApps());
+ assertTrue(pui.getDexUseInfoMap().isEmpty());
+ }
+
+ @Test
+ public void testNotifyPackageDataDestroyComplete() {
+ // Foo loads its own secondary files.
+ List<String> fooSecondaries = mFooUser0.getSecondaryDexPaths();
+ notifyDexLoad(mFooUser0, fooSecondaries, mUser0);
+
+ mDexManager.notifyPackageDataDestroyed(mFooUser0.getPackageName(), mUser0);
+
+ // Foo should not be around since all its secondary dex info were deleted
+ // and it is not used by other apps.
+ PackageUseInfo pui = getPackageUseInfo(mFooUser0);
+ assertNull(pui);
+ }
+
+ @Test
+ public void testNotifyPackageDataDestroyForAll() {
+ // Foo loads its own secondary files.
+ notifyDexLoad(mBarUser0, mBarUser0.getSecondaryDexPaths(), mUser0);
+ notifyDexLoad(mBarUser1, mBarUser1.getSecondaryDexPaths(), mUser1);
+
+ mDexManager.notifyPackageDataDestroyed(mBarUser0.getPackageName(), UserHandle.USER_ALL);
+
+ // Bar should not be around since it was removed for all users.
+ PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+ assertNull(pui);
+ }
+
+ @Test
+ public void testNotifyFrameworkLoad() {
+ String frameworkDex = "/system/framework/com.android.location.provider.jar";
+ // Load a dex file from framework.
+ notifyDexLoad(mFooUser0, Arrays.asList(frameworkDex), mUser0);
+ // The dex file should not be recognized as a package.
+ assertNull(mDexManager.getPackageUseInfo(frameworkDex));
+ }
+
private void assertSecondaryUse(TestData testData, PackageUseInfo pui,
List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId) {
for (String dex : secondaries) {
@@ -317,5 +434,12 @@
}
return paths;
}
+
+ String replaceLastSplit() {
+ int length = mPackageInfo.applicationInfo.splitSourceDirs.length;
+ // Add an extra bogus dex extension to simulate a new split name.
+ mPackageInfo.applicationInfo.splitSourceDirs[length - 1] += ".dex";
+ return mPackageInfo.applicationInfo.splitSourceDirs[length - 1];
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
index 19e0bcf..2e99433 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -257,6 +257,30 @@
}
@Test
+ public void testRemovePackage() {
+ // Record Bar secondaries for two different users.
+ assertTrue(record(mBarSecondary1User0));
+ assertTrue(record(mBarSecondary2User1));
+
+ // Remove the package.
+ assertTrue(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName));
+ // Assert that we can't find the package anymore.
+ assertNull(mPackageDexUsage.getPackageUseInfo(mBarSecondary1User0.mPackageName));
+ }
+
+ @Test
+ public void testRemoveNonexistentPackage() {
+ // Record Bar secondaries for two different users.
+ assertTrue(record(mBarSecondary1User0));
+
+ // Remove the package.
+ assertTrue(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName));
+ // Remove the package again. It should return false because the package no longer
+ // has a record in the use info.
+ assertFalse(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName));
+ }
+
+ @Test
public void testRemoveUserPackage() {
// Record Bar secondaries for two different users.
assertTrue(record(mBarSecondary1User0));
@@ -282,6 +306,32 @@
assertPackageDexUsage(null, mBarSecondary2User1);
}
+ @Test
+ public void testClearUsedByOtherApps() {
+ // Write a package which is used by other apps.
+ assertTrue(record(mFooSplit2UsedByOtherApps0));
+ assertTrue(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName));
+
+ // Check that the package is no longer used by other apps.
+ TestData noLongerUsedByOtherApps = new TestData(
+ mFooSplit2UsedByOtherApps0.mPackageName,
+ mFooSplit2UsedByOtherApps0.mDexFile,
+ mFooSplit2UsedByOtherApps0.mOwnerUserId,
+ mFooSplit2UsedByOtherApps0.mLoaderIsa,
+ /*mIsUsedByOtherApps*/false,
+ mFooSplit2UsedByOtherApps0.mPrimaryOrSplit);
+ assertPackageDexUsage(noLongerUsedByOtherApps);
+ }
+
+ @Test
+ public void testClearUsedByOtherAppsNonexistent() {
+ // Write a package which is used by other apps.
+ assertTrue(record(mFooSplit2UsedByOtherApps0));
+ assertTrue(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName));
+ // Clearing again should return false as there should be no update on the use info.
+ assertFalse(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName));
+ }
+
private void assertPackageDexUsage(TestData primary, TestData... secondaries) {
String packageName = primary == null ? secondaries[0].mPackageName : primary.mPackageName;
boolean primaryUsedByOtherApps = primary == null ? false : primary.mUsedByOtherApps;
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 99eb3d2..de5cafb 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -570,8 +570,11 @@
// Set the new USB configuration.
setUsbConfig(functions);
- // Start up dependent services.
- updateUsbStateBroadcastIfNeeded(true);
+ if (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
+ || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP)) {
+ // Start up dependent services.
+ updateUsbStateBroadcastIfNeeded(true);
+ }
if (!waitForState(functions)) {
Slog.e(TAG, "Failed to switch USB config to " + functions);
@@ -743,7 +746,8 @@
}
mMidiEnabled = enabled;
}
- mUsbAlsaManager.setPeripheralMidiState(mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
+ mUsbAlsaManager.setPeripheralMidiState(
+ mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
}
@Override
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 833affa..7998359 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -436,6 +436,18 @@
"android.telecom.extra.ANSWERING_DROPS_FG_CALL";
/**
+ * String connection extra key set on a {@link Connection} in {@link Connection#STATE_RINGING}
+ * state to indicate the name of the third-party app which is responsible for the current
+ * foreground call.
+ * <p>
+ * Used when {@link #EXTRA_ANSWERING_DROPS_FG_CALL} is true to ensure that the default Phone app
+ * is able to inform the user that answering the new incoming call will cause a call owned by
+ * another app to be dropped when the incoming call is answered.
+ */
+ public static final String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME =
+ "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME";
+
+ /**
* Boolean connection extra key on a {@link Connection} which indicates that adding an
* additional call is disallowed.
* @hide
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 3926e20..c42a835 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -310,6 +310,18 @@
}
/**
+ * Sets the label. See {@link PhoneAccount#getLabel()}.
+ *
+ * @param label The label of the phone account.
+ * @return The builder.
+ * @hide
+ */
+ public Builder setLabel(CharSequence label) {
+ this.mLabel = label;
+ return this;
+ }
+
+ /**
* Sets the address. See {@link PhoneAccount#getAddress}.
*
* @param value The address of the phone account.
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index e21b4db..5093a61 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -181,6 +181,18 @@
"android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
/**
+ * Optional extra for {@link #addNewIncomingCall(PhoneAccountHandle, Bundle)} containing an
+ * integer that determines the requested video state for an incoming call.
+ * Valid options:
+ * {@link VideoProfile#STATE_AUDIO_ONLY},
+ * {@link VideoProfile#STATE_BIDIRECTIONAL},
+ * {@link VideoProfile#STATE_RX_ENABLED},
+ * {@link VideoProfile#STATE_TX_ENABLED}.
+ */
+ public static final String EXTRA_INCOMING_VIDEO_STATE =
+ "android.telecom.extra.INCOMING_VIDEO_STATE";
+
+ /**
* The extra used with an {@link android.content.Intent#ACTION_CALL} and
* {@link android.content.Intent#ACTION_DIAL} {@code Intent} to specify a
* {@link PhoneAccountHandle} to use when making the call.
@@ -383,7 +395,11 @@
* <p>
* An {@link InCallService} which receives self-managed calls is free to view and control the
* state of calls in the self-managed {@link ConnectionService}. An example use-case is
- * exposing these calls to a wearable or automotive device via its companion app.
+ * exposing these calls to an automotive device via its companion app.
+ * <p>
+ * This meta-data can only be set for an {@link InCallService} which also sets
+ * {@link #METADATA_IN_CALL_SERVICE_UI}. Only the default phone/dialer app, or a car-mode
+ * {@link InCallService} can see self-managed calls.
* <p>
* See also {@link Connection#PROPERTY_SELF_MANAGED}.
*/
@@ -1277,6 +1293,10 @@
* {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
* {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call.
* <p>
+ * The incoming call you are adding is assumed to have a video state of
+ * {@link VideoProfile#STATE_AUDIO_ONLY}, unless the extra value
+ * {@link #EXTRA_INCOMING_VIDEO_STATE} is specified.
+ * <p>
* Once invoked, this method will cause the system to bind to the {@link ConnectionService}
* associated with the {@link PhoneAccountHandle} and request additional information about the
* call (See {@link ConnectionService#onCreateIncomingConnection}) before starting the incoming
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1076afc..64bb658 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -315,6 +315,14 @@
public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
/**
+ * Flag indicating whether we should downgrade/terminate VT calls and disable VT when
+ * data enabled changed (e.g. reach data limit or turn off data).
+ * @hide
+ */
+ public static final String KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS =
+ "ignore_data_enabled_changed_for_video_calls";
+
+ /**
* Flag specifying whether WFC over IMS should be available for carrier: independent of
* carrier provisioning. If false: hard disabled. If true: then depends on carrier
* provisioning, availability etc.
@@ -640,6 +648,14 @@
"display_hd_audio_property_bool";
/**
+ * Determines whether IMS conference calls are supported by a carrier. When {@code true},
+ * IMS conference calling is supported, {@code false} otherwise.
+ * @hide
+ */
+ public static final String KEY_SUPPORT_IMS_CONFERENCE_CALL_BOOL =
+ "support_ims_conference_call_bool";
+
+ /**
* Determines whether video conference calls are supported by a carrier. When {@code true},
* video calls can be merged into conference calls, {@code false} otherwiwse.
* <p>
@@ -656,6 +672,13 @@
public static final String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
/**
+ * Determines whether the Enhanced 4G LTE toggle will be shown in the settings. When this
+ * option is {@code true}, the toggle will be hidden regardless of whether the device and
+ * carrier supports 4G LTE or not.
+ */
+ public static final String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool";
+
+ /**
* Determine whether IMS apn can be shown.
*/
public static final String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool";
@@ -1135,6 +1158,29 @@
public static final String KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL =
"notify_international_call_on_wfc_bool";
+ /**
+ * Offset to be reduced from rsrp threshold while calculating signal strength level.
+ * @hide
+ */
+ public static final String KEY_LTE_EARFCNS_RSRP_BOOST_INT = "lte_earfcns_rsrp_boost_int";
+
+ /**
+ * List of EARFCN (E-UTRA Absolute Radio Frequency Channel Number,
+ * Reference: 3GPP TS 36.104 5.4.3) inclusive ranges on which lte_rsrp_boost_int
+ * will be applied. Format of the String array is expected to be {"erafcn1_start-earfcn1_end",
+ * "earfcn2_start-earfcn2_end" ... }
+ * @hide
+ */
+ public static final String KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY =
+ "boosted_lte_earfcns_string_array";
+
+ /**
+ * Key identifying if voice call barring notification is required to be shown to the user.
+ * @hide
+ */
+ public static final String KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL =
+ "disable_voice_barring_notification_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -1152,6 +1198,7 @@
sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
+ sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, false);
sDefaults.putBoolean(KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL, false);
@@ -1250,9 +1297,11 @@
sDefaults.putInt(KEY_CDMA_DTMF_TONE_DELAY_INT, 100);
sDefaults.putInt(KEY_CDMA_3WAYCALL_FLASH_DELAY_INT , 0);
sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true);
+ sDefaults.putBoolean(KEY_SUPPORT_IMS_CONFERENCE_CALL_BOOL, true);
sDefaults.putBoolean(KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL, false);
sDefaults.putBoolean(KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL, true);
sDefaults.putBoolean(KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, true);
+ sDefaults.putBoolean(KEY_HIDE_ENHANCED_4G_LTE_BOOL, false);
sDefaults.putBoolean(KEY_HIDE_IMS_APN_BOOL, false);
sDefaults.putBoolean(KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL, false);
sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL, false);
@@ -1341,6 +1390,9 @@
sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL, true);
sDefaults.putBoolean(KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL, false);
+ sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
+ sDefaults.putStringArray(KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY, null);
+ sDefaults.putBoolean(KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 2eba402..0b80d06 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1619,7 +1619,7 @@
//
// Australia: Short codes are six or eight digits in length, starting with the prefix "19"
// followed by an additional four or six digits and two.
- // Czech Republic: Codes are seven digits in length for MO and five (not billed) or
+ // Czechia: Codes are seven digits in length for MO and five (not billed) or
// eight (billed) for MT direction
//
// see http://en.wikipedia.org/wiki/Short_code#Regional_differences for reference
@@ -1896,7 +1896,7 @@
number = extractNetworkPortionAlt(number);
String emergencyNumbers = "";
- int slotId = SubscriptionManager.getSlotId(subId);
+ int slotId = SubscriptionManager.getSlotIndex(subId);
// retrieve the list of emergency numbers
// check read-write ecclist property first
diff --git a/telephony/java/android/telephony/PreciseDisconnectCause.java b/telephony/java/android/telephony/PreciseDisconnectCause.java
index 54ab19d..2516d51 100644
--- a/telephony/java/android/telephony/PreciseDisconnectCause.java
+++ b/telephony/java/android/telephony/PreciseDisconnectCause.java
@@ -25,75 +25,480 @@
public class PreciseDisconnectCause {
/** The disconnect cause is not valid (Not received a disconnect cause)*/
- public static final int NOT_VALID = -1;
+ public static final int NOT_VALID = -1;
/** No disconnect cause provided. Generally a local disconnect or an incoming missed call */
- public static final int NO_DISCONNECT_CAUSE_AVAILABLE = 0;
+ public static final int NO_DISCONNECT_CAUSE_AVAILABLE = 0;
/**
* The destination cannot be reached because the number, although valid,
* is not currently assigned
*/
- public static final int UNOBTAINABLE_NUMBER = 1;
+ public static final int UNOBTAINABLE_NUMBER = 1;
+ /** The user cannot be reached because the network through which the call has been
+ * routed does not serve the destination desired
+ */
+ public static final int NO_ROUTE_TO_DESTINATION = 3;
+ /** The channel most recently identified is not acceptable to the sending entity for
+ * use in this call
+ */
+ public static final int CHANNEL_UNACCEPTABLE = 6;
+ /** The MS has tried to access a service that the MS's network operator or service
+ * provider is not prepared to allow
+ */
+ public static final int OPERATOR_DETERMINED_BARRING = 8;
/** One of the users involved in the call has requested that the call is cleared */
- public static final int NORMAL = 16;
+ public static final int NORMAL = 16;
/** The called user is unable to accept another call */
- public static final int BUSY = 17;
+ public static final int BUSY = 17;
+ /** The user does not respond to a call establishment message with either an alerting
+ * or connect indication within the prescribed period of time allocated
+ */
+ public static final int NO_USER_RESPONDING = 18;
+ /** The user has provided an alerting indication but has not provided a connect
+ * indication within a prescribed period of time
+ */
+ public static final int NO_ANSWER_FROM_USER = 19;
+ /** The equipment sending this cause does not wish to accept this call */
+ public static final int CALL_REJECTED = 21;
/** The called number is no longer assigned */
- public static final int NUMBER_CHANGED = 22;
+ public static final int NUMBER_CHANGED = 22;
+ /** This cause is returned to the network when a mobile station clears an active
+ * call which is being pre-empted by another call with higher precedence
+ */
+ public static final int PREEMPTION = 25;
+ /** The destination indicated by the mobile station cannot be reached because
+ * the interface to the destination is not functioning correctly
+ */
+ public static final int DESTINATION_OUT_OF_ORDER = 27;
+ /** The called party number is not a valid format or is not complete */
+ public static final int INVALID_NUMBER_FORMAT = 28;
+ /** The facility requested by user can not be provided by the network */
+ public static final int FACILITY_REJECTED = 29;
/** Provided in response to a STATUS ENQUIRY message */
- public static final int STATUS_ENQUIRY = 30;
+ public static final int STATUS_ENQUIRY = 30;
/** Reports a normal disconnect only when no other normal cause applies */
- public static final int NORMAL_UNSPECIFIED = 31;
+ public static final int NORMAL_UNSPECIFIED = 31;
/** There is no channel presently available to handle the call */
- public static final int NO_CIRCUIT_AVAIL = 34;
+ public static final int NO_CIRCUIT_AVAIL = 34;
+ /** The network is not functioning correctly and that the condition is likely
+ * to last a relatively long period of time
+ */
+ public static final int NETWORK_OUT_OF_ORDER = 38;
/**
* The network is not functioning correctly and the condition is not likely to last
* a long period of time
*/
- public static final int TEMPORARY_FAILURE = 41;
+ public static final int TEMPORARY_FAILURE = 41;
/** The switching equipment is experiencing a period of high traffic */
- public static final int SWITCHING_CONGESTION = 42;
+ public static final int SWITCHING_CONGESTION = 42;
+ /** The network could not deliver access information to the remote user as requested */
+ public static final int ACCESS_INFORMATION_DISCARDED = 43;
/** The channel cannot be provided */
- public static final int CHANNEL_NOT_AVAIL = 44;
+ public static final int CHANNEL_NOT_AVAIL = 44;
+ /** This cause is used to report a resource unavailable event only when no other
+ * cause in the resource unavailable class applies
+ */
+ public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 44;
/** The requested quality of service (ITU-T X.213) cannot be provided */
- public static final int QOS_NOT_AVAIL = 49;
+ public static final int QOS_NOT_AVAIL = 49;
+ /** The facility could not be provided by the network because the user has no
+ * complete subscription
+ */
+ public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED = 50;
+ /** Incoming calls are not allowed within this CUG */
+ public static final int INCOMING_CALLS_BARRED_WITHIN_CUG = 55;
+ /** The mobile station is not authorized to use bearer capability requested */
+ public static final int BEARER_CAPABILITY_NOT_AUTHORIZED = 57;
/** The requested bearer capability is not available at this time */
- public static final int BEARER_NOT_AVAIL = 58;
+ public static final int BEARER_NOT_AVAIL = 58;
+ /** The service option is not availble at this time */
+ public static final int SERVICE_OPTION_NOT_AVAILABLE = 63;
+ /** The equipment sending this cause does not support the bearer capability requested */
+ public static final int BEARER_SERVICE_NOT_IMPLEMENTED = 65;
/** The call clearing is due to ACM being greater than or equal to ACMmax */
- public static final int ACM_LIMIT_EXCEEDED = 68;
+ public static final int ACM_LIMIT_EXCEEDED = 68;
+ /** The equipment sending this cause does not support the requested facility */
+ public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED = 69;
+ /** The equipment sending this cause only supports the restricted version of
+ * the requested bearer capability
+ */
+ public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70;
+ /** The service requested is not implemented at network */
+ public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79;
+ /** The equipment sending this cause has received a message with a transaction identifier
+ * which is not currently in use on the MS-network interface
+ */
+ public static final int INVALID_TRANSACTION_IDENTIFIER = 81;
+ /** The called user for the incoming CUG call is not a member of the specified CUG */
+ public static final int USER_NOT_MEMBER_OF_CUG = 87;
+ /** The equipment sending this cause has received a request which can't be accomodated */
+ public static final int INCOMPATIBLE_DESTINATION = 88;
+ /** This cause is used to report receipt of a message with semantically incorrect contents */
+ public static final int SEMANTICALLY_INCORRECT_MESSAGE = 95;
+ /** The equipment sending this cause has received a message with a non-semantical
+ * mandatory IE error
+ */
+ public static final int INVALID_MANDATORY_INFORMATION = 96;
+ /** This is sent in response to a message which is not defined, or defined but not
+ * implemented by the equipment sending this cause
+ */
+ public static final int MESSAGE_TYPE_NON_IMPLEMENTED = 97;
+ /** The equipment sending this cause has received a message not compatible with the
+ * protocol state
+ */
+ public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98;
+ /** The equipment sending this cause has received a message which includes information
+ * elements not recognized because its identifier is not defined or it is defined but not
+ * implemented by the equipment sending the cause
+ */
+ public static final int INFORMATION_ELEMENT_NON_EXISTENT = 99;
+ /** The equipment sending this cause has received a message with conditional IE errors */
+ public static final int CONDITIONAL_IE_ERROR = 100;
+ /** The message has been received which is incompatible with the protocol state */
+ public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101;
+ /** The procedure has been initiated by the expiry of a timer in association with
+ * 3GPP TS 24.008 error handling procedures
+ */
+ public static final int RECOVERY_ON_TIMER_EXPIRED = 102;
+ /** This protocol error event is reported only when no other cause in the protocol
+ * error class applies
+ */
+ public static final int PROTOCOL_ERROR_UNSPECIFIED = 111;
+ /** interworking with a network which does not provide causes for actions it takes
+ * thus, the precise cause for a message which is being sent cannot be ascertained
+ */
+ public static final int INTERWORKING_UNSPECIFIED = 127;
/** The call is restricted */
- public static final int CALL_BARRED = 240;
+ public static final int CALL_BARRED = 240;
/** The call is blocked by the Fixed Dialing Number list */
- public static final int FDN_BLOCKED = 241;
+ public static final int FDN_BLOCKED = 241;
/** The given IMSI is not known at the VLR */
/** TS 24.008 cause 4 */
- public static final int IMSI_UNKNOWN_IN_VLR = 242;
+ public static final int IMSI_UNKNOWN_IN_VLR = 242;
/**
* The network does not accept emergency call establishment using an IMEI or not accept attach
* procedure for emergency services using an IMEI
*/
- public static final int IMEI_NOT_ACCEPTED = 243;
+ public static final int IMEI_NOT_ACCEPTED = 243;
+ /** The call cannot be established because RADIO is OFF */
+ public static final int RADIO_OFF = 247;
+ /** The call cannot be established because of no cell coverage */
+ public static final int OUT_OF_SRV = 248;
+ /** The call cannot be established because of no valid SIM */
+ public static final int NO_VALID_SIM = 249;
+ /** The call is dropped or failed internally by modem */
+ public static final int RADIO_INTERNAL_ERROR = 250;
+ /** Call failed because of UE timer expired while waiting for a response from network */
+ public static final int NETWORK_RESP_TIMEOUT = 251;
+ /** Call failed because of a network reject */
+ public static final int NETWORK_REJECT = 252;
+ /** Call failed because of radio access failure. ex. RACH failure */
+ public static final int RADIO_ACCESS_FAILURE = 253;
+ /** Call failed/dropped because of a RLF */
+ public static final int RADIO_LINK_FAILURE = 254;
+ /** Call failed/dropped because of radio link lost */
+ public static final int RADIO_LINK_LOST = 255;
+ /** Call failed because of a radio uplink issue */
+ public static final int RADIO_UPLINK_FAILURE = 256;
+ /** Call failed because of a RRC connection setup failure */
+ public static final int RADIO_SETUP_FAILURE = 257;
+ /** Call failed/dropped because of RRC connection release from NW */
+ public static final int RADIO_RELEASE_NORMAL = 258;
+ /** Call failed/dropped because of RRC abnormally released by modem/network */
+ public static final int RADIO_RELEASE_ABNORMAL = 259;
+ /** Call setup failed because of access class barring */
+ public static final int ACCESS_CLASS_BLOCKED = 260;
+ /** Call failed/dropped because of a network detach */
+ public static final int NETWORK_DETACH = 261;
+
/** MS is locked until next power cycle */
- public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000;
+ public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000;
/** Drop call*/
- public static final int CDMA_DROP = 1001;
+ public static final int CDMA_DROP = 1001;
/** INTERCEPT order received, MS state idle entered */
- public static final int CDMA_INTERCEPT = 1002;
+ public static final int CDMA_INTERCEPT = 1002;
/** MS has been redirected, call is cancelled */
- public static final int CDMA_REORDER = 1003;
+ public static final int CDMA_REORDER = 1003;
/** Service option rejection */
- public static final int CDMA_SO_REJECT = 1004;
+ public static final int CDMA_SO_REJECT = 1004;
/** Requested service is rejected, retry delay is set */
- public static final int CDMA_RETRY_ORDER = 1005;
+ public static final int CDMA_RETRY_ORDER = 1005;
/** Unable to obtain access to the CDMA system */
- public static final int CDMA_ACCESS_FAILURE = 1006;
+ public static final int CDMA_ACCESS_FAILURE = 1006;
/** Not a preempted call */
- public static final int CDMA_PREEMPTED = 1007;
+ public static final int CDMA_PREEMPTED = 1007;
/** Not an emergency call */
- public static final int CDMA_NOT_EMERGENCY = 1008;
+ public static final int CDMA_NOT_EMERGENCY = 1008;
/** Access Blocked by CDMA network */
- public static final int CDMA_ACCESS_BLOCKED = 1009;
+ public static final int CDMA_ACCESS_BLOCKED = 1009;
+
+ /** Mapped from ImsReasonInfo */
+ /* The passed argument is an invalid */
+ public static final int LOCAL_ILLEGAL_ARGUMENT = 1200;
+ // The operation is invoked in invalid call state
+ public static final int LOCAL_ILLEGAL_STATE = 1201;
+ // IMS service internal error
+ public static final int LOCAL_INTERNAL_ERROR = 1202;
+ // IMS service goes down (service connection is lost)
+ public static final int LOCAL_IMS_SERVICE_DOWN = 1203;
+ // No pending incoming call exists
+ public static final int LOCAL_NO_PENDING_CALL = 1204;
+ // Service unavailable; by power off
+ public static final int LOCAL_POWER_OFF = 1205;
+ // Service unavailable; by low battery
+ public static final int LOCAL_LOW_BATTERY = 1206;
+ // Service unavailable; by out of service (data service state)
+ public static final int LOCAL_NETWORK_NO_SERVICE = 1207;
+ /* Service unavailable; by no LTE coverage
+ * (VoLTE is not supported even though IMS is registered)
+ */
+ public static final int LOCAL_NETWORK_NO_LTE_COVERAGE = 1208;
+ /** Service unavailable; by located in roaming area */
+ public static final int LOCAL_NETWORK_ROAMING = 1209;
+ /** Service unavailable; by IP changed */
+ public static final int LOCAL_NETWORK_IP_CHANGED = 1210;
+ /** Service unavailable; other */
+ public static final int LOCAL_SERVICE_UNAVAILABLE = 1211;
+ /* Service unavailable; IMS connection is lost (IMS is not registered) */
+ public static final int LOCAL_NOT_REGISTERED = 1212;
+ /** Max call exceeded */
+ public static final int LOCAL_MAX_CALL_EXCEEDED = 1213;
+ /** Call decline */
+ public static final int LOCAL_CALL_DECLINE = 1214;
+ /** SRVCC is in progress */
+ public static final int LOCAL_CALL_VCC_ON_PROGRESSING = 1215;
+ /** Resource reservation is failed (QoS precondition) */
+ public static final int LOCAL_CALL_RESOURCE_RESERVATION_FAILED = 1216;
+ /** Retry CS call; VoLTE service can't be provided by the network or remote end
+ * Resolve the extra code(EXTRA_CODE_CALL_RETRY_*) if the below code is set
+ */
+ public static final int LOCAL_CALL_CS_RETRY_REQUIRED = 1217;
+ /** Retry VoLTE call; VoLTE service can't be provided by the network temporarily */
+ public static final int LOCAL_CALL_VOLTE_RETRY_REQUIRED = 1218;
+ /** IMS call is already terminated (in TERMINATED state) */
+ public static final int LOCAL_CALL_TERMINATED = 1219;
+ /** Handover not feasible */
+ public static final int LOCAL_HO_NOT_FEASIBLE = 1220;
+
+ /** 1xx waiting timer is expired after sending INVITE request (MO only) */
+ public static final int TIMEOUT_1XX_WAITING = 1221;
+ /** User no answer during call setup operation (MO/MT)
+ * MO : 200 OK to INVITE request is not received,
+ * MT : No action from user after alerting the call
+ */
+ public static final int TIMEOUT_NO_ANSWER = 1222;
+ /** User no answer during call update operation (MO/MT)
+ * MO : 200 OK to re-INVITE request is not received,
+ * MT : No action from user after alerting the call
+ */
+ public static final int TIMEOUT_NO_ANSWER_CALL_UPDATE = 1223;
+
+ /**
+ * STATUSCODE (SIP response code) (IMS -> Telephony)
+ */
+ /** SIP request is redirected */
+ public static final int SIP_REDIRECTED = 1300;
+ /** 4xx responses */
+ /** 400 : Bad Request */
+ public static final int SIP_BAD_REQUEST = 1310;
+ /** 403 : Forbidden */
+ public static final int SIP_FORBIDDEN = 1311;
+ /** 404 : Not Found */
+ public static final int SIP_NOT_FOUND = 1312;
+ /** 415 : Unsupported Media Type
+ * 416 : Unsupported URI Scheme
+ * 420 : Bad Extension
+ */
+ public static final int SIP_NOT_SUPPORTED = 1313;
+ /** 408 : Request Timeout */
+ public static final int SIP_REQUEST_TIMEOUT = 1314;
+ /** 480 : Temporarily Unavailable */
+ public static final int SIP_TEMPRARILY_UNAVAILABLE = 1315;
+ /** 484 : Address Incomplete */
+ public static final int SIP_BAD_ADDRESS = 1316;
+ /** 486 : Busy Here
+ * 600 : Busy Everywhere
+ */
+ public static final int SIP_BUSY = 1317;
+ /** 487 : Request Terminated */
+ public static final int SIP_REQUEST_CANCELLED = 1318;
+ /** 406 : Not Acceptable
+ * 488 : Not Acceptable Here
+ * 606 : Not Acceptable
+ */
+ public static final int SIP_NOT_ACCEPTABLE = 1319;
+ /** 410 : Gone
+ * 604 : Does Not Exist Anywhere
+ */
+ public static final int SIP_NOT_REACHABLE = 1320;
+ /** Others */
+ public static final int SIP_CLIENT_ERROR = 1321;
+ /** 5xx responses
+ * 501 : Server Internal Error
+ */
+ public static final int SIP_SERVER_INTERNAL_ERROR = 1330;
+ /** 503 : Service Unavailable */
+ public static final int SIP_SERVICE_UNAVAILABLE = 1331;
+ /** 504 : Server Time-out */
+ public static final int SIP_SERVER_TIMEOUT = 1332;
+ /** Others */
+ public static final int SIP_SERVER_ERROR = 1333;
+ /** 6xx responses
+ * 603 : Decline
+ */
+ public static final int SIP_USER_REJECTED = 1340;
+ /** Others */
+ public static final int SIP_GLOBAL_ERROR = 1341;
+ /** Emergency failure */
+ public static final int EMERGENCY_TEMP_FAILURE = 1342;
+ public static final int EMERGENCY_PERM_FAILURE = 1343;
+ /** Media resource initialization failed */
+ public static final int MEDIA_INIT_FAILED = 1400;
+ /** RTP timeout (no audio / video traffic in the session) */
+ public static final int MEDIA_NO_DATA = 1401;
+ /** Media is not supported; so dropped the call */
+ public static final int MEDIA_NOT_ACCEPTABLE = 1402;
+ /** Unknown media related errors */
+ public static final int MEDIA_UNSPECIFIED = 1403;
+ /** User triggers the call end */
+ public static final int USER_TERMINATED = 1500;
+ /** No action while an incoming call is ringing */
+ public static final int USER_NOANSWER = 1501;
+ /** User ignores an incoming call */
+ public static final int USER_IGNORE = 1502;
+ /** User declines an incoming call */
+ public static final int USER_DECLINE = 1503;
+ /** Device declines/ends a call due to low battery */
+ public static final int LOW_BATTERY = 1504;
+ /** Device declines call due to blacklisted call ID */
+ public static final int BLACKLISTED_CALL_ID = 1505;
+ /** The call is terminated by the network or remote user */
+ public static final int USER_TERMINATED_BY_REMOTE = 1510;
+
+ /**
+ * UT
+ */
+ public static final int UT_NOT_SUPPORTED = 1800;
+ public static final int UT_SERVICE_UNAVAILABLE = 1801;
+ public static final int UT_OPERATION_NOT_ALLOWED = 1802;
+ public static final int UT_NETWORK_ERROR = 1803;
+ public static final int UT_CB_PASSWORD_MISMATCH = 1804;
+
+ /**
+ * ECBM
+ */
+ public static final int ECBM_NOT_SUPPORTED = 1900;
+
+ /**
+ * Fail code used to indicate that Multi-endpoint is not supported by the Ims framework.
+ */
+ public static final int MULTIENDPOINT_NOT_SUPPORTED = 1901;
+
+ /**
+ * CALL DROP error codes (Call could drop because of many reasons like Network not available,
+ * handover, failed, etc)
+ */
+
+ /**
+ * CALL DROP error code for the case when a device is ePDG capable and when the user is on an
+ * active wifi call and at the edge of coverage and there is no qualified LTE network available
+ * to handover the call to. We get a handover NOT_TRIGERRED message from the modem. This error
+ * code is received as part of the handover message.
+ */
+ public static final int CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE = 2000;
+
+ /**
+ * MT call has ended due to a release from the network
+ * because the call was answered elsewhere
+ */
+ public static final int ANSWERED_ELSEWHERE = 2100;
+
+ /**
+ * For MultiEndpoint - Call Pull request has failed
+ */
+ public static final int CALL_PULL_OUT_OF_SYNC = 2101;
+
+ /**
+ * For MultiEndpoint - Call has been pulled from primary to secondary
+ */
+ public static final int CALL_PULLED = 2102;
+
+ /**
+ * Supplementary services (HOLD/RESUME) failure error codes.
+ * Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision.
+ */
+ public static final int SUPP_SVC_FAILED = 2300;
+ public static final int SUPP_SVC_CANCELLED = 2301;
+ public static final int SUPP_SVC_REINVITE_COLLISION = 2302;
+
+ /**
+ * DPD Procedure received no response or send failed
+ */
+ public static final int IWLAN_DPD_FAILURE = 2400;
+
+ /**
+ * Establishment of the ePDG Tunnel Failed
+ */
+ public static final int EPDG_TUNNEL_ESTABLISH_FAILURE = 2500;
+
+ /**
+ * Re-keying of the ePDG Tunnel Failed; may not always result in teardown
+ */
+ public static final int EPDG_TUNNEL_REKEY_FAILURE = 2501;
+
+ /**
+ * Connection to the packet gateway is lost
+ */
+ public static final int EPDG_TUNNEL_LOST_CONNECTION = 2502;
+
+ /**
+ * The maximum number of calls allowed has been reached. Used in a multi-endpoint scenario
+ * where the number of calls across all connected devices has reached the maximum.
+ */
+ public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 2503;
+
+ /**
+ * Similar to {@link #CODE_LOCAL_CALL_DECLINE}, except indicates that a remote device has
+ * declined the call. Used in a multi-endpoint scenario where a remote device declined an
+ * incoming call.
+ */
+ public static final int REMOTE_CALL_DECLINE = 2504;
+
+ /**
+ * Indicates the call was disconnected due to the user reaching their data limit.
+ */
+ public static final int DATA_LIMIT_REACHED = 2505;
+
+ /**
+ * Indicates the call was disconnected due to the user disabling cellular data.
+ */
+ public static final int DATA_DISABLED = 2506;
+
+ /**
+ * Indicates a call was disconnected due to loss of wifi signal.
+ */
+ public static final int WIFI_LOST = 2507;
+
+
+ /* OEM specific error codes. To be used by OEMs when they don't want to
+ reveal error code which would be replaced by ERROR_UNSPECIFIED */
+ public static final int OEM_CAUSE_1 = 0xf001;
+ public static final int OEM_CAUSE_2 = 0xf002;
+ public static final int OEM_CAUSE_3 = 0xf003;
+ public static final int OEM_CAUSE_4 = 0xf004;
+ public static final int OEM_CAUSE_5 = 0xf005;
+ public static final int OEM_CAUSE_6 = 0xf006;
+ public static final int OEM_CAUSE_7 = 0xf007;
+ public static final int OEM_CAUSE_8 = 0xf008;
+ public static final int OEM_CAUSE_9 = 0xf009;
+ public static final int OEM_CAUSE_10 = 0xf00a;
+ public static final int OEM_CAUSE_11 = 0xf00b;
+ public static final int OEM_CAUSE_12 = 0xf00c;
+ public static final int OEM_CAUSE_13 = 0xf00d;
+ public static final int OEM_CAUSE_14 = 0xf00e;
+ public static final int OEM_CAUSE_15 = 0xf00f;
+
/** Disconnected due to unspecified reasons */
- public static final int ERROR_UNSPECIFIED = 0xffff;
+ public static final int ERROR_UNSPECIFIED = 0xffff;
/** Private constructor to avoid class instantiation. */
private PreciseDisconnectCause() {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 7a83979..5fb83ab 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -243,6 +243,10 @@
private boolean mIsUsingCarrierAggregation;
+ /* EARFCN stands for E-UTRA Absolute Radio Frequency Channel Number,
+ * Reference: 3GPP TS 36.104 5.4.3 */
+ private int mLteEarfcnRsrpBoost = 0;
+
/**
* get String description of roaming type
* @hide
@@ -322,6 +326,7 @@
mIsEmergencyOnly = s.mIsEmergencyOnly;
mIsDataRoamingFromRegistration = s.mIsDataRoamingFromRegistration;
mIsUsingCarrierAggregation = s.mIsUsingCarrierAggregation;
+ mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost;
}
/**
@@ -351,6 +356,7 @@
mIsEmergencyOnly = in.readInt() != 0;
mIsDataRoamingFromRegistration = in.readInt() != 0;
mIsUsingCarrierAggregation = in.readInt() != 0;
+ mLteEarfcnRsrpBoost = in.readInt();
}
public void writeToParcel(Parcel out, int flags) {
@@ -377,6 +383,7 @@
out.writeInt(mIsEmergencyOnly ? 1 : 0);
out.writeInt(mIsDataRoamingFromRegistration ? 1 : 0);
out.writeInt(mIsUsingCarrierAggregation ? 1 : 0);
+ out.writeInt(mLteEarfcnRsrpBoost);
}
public int describeContents() {
@@ -814,7 +821,8 @@
+ " DefRoamInd=" + mCdmaDefaultRoamingIndicator
+ " EmergOnly=" + mIsEmergencyOnly
+ " IsDataRoamingFromRegistration=" + mIsDataRoamingFromRegistration
- + " IsUsingCarrierAggregation=" + mIsUsingCarrierAggregation);
+ + " IsUsingCarrierAggregation=" + mIsUsingCarrierAggregation
+ + " mLteEarfcnRsrpBoost=" + mLteEarfcnRsrpBoost);
}
private void setNullState(int state) {
@@ -842,6 +850,7 @@
mIsEmergencyOnly = false;
mIsDataRoamingFromRegistration = false;
mIsUsingCarrierAggregation = false;
+ mLteEarfcnRsrpBoost = 0;
}
public void setStateOutOfService() {
@@ -1016,6 +1025,7 @@
mIsEmergencyOnly = m.getBoolean("emergencyOnly");
mIsDataRoamingFromRegistration = m.getBoolean("isDataRoamingFromRegistration");
mIsUsingCarrierAggregation = m.getBoolean("isUsingCarrierAggregation");
+ mLteEarfcnRsrpBoost = m.getInt("LteEarfcnRsrpBoost");
}
/**
@@ -1046,6 +1056,7 @@
m.putBoolean("emergencyOnly", mIsEmergencyOnly);
m.putBoolean("isDataRoamingFromRegistration", mIsDataRoamingFromRegistration);
m.putBoolean("isUsingCarrierAggregation", mIsUsingCarrierAggregation);
+ m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
}
/** @hide */
@@ -1081,6 +1092,16 @@
}
/** @hide */
+ public int getLteEarfcnRsrpBoost() {
+ return mLteEarfcnRsrpBoost;
+ }
+
+ /** @hide */
+ public void setLteEarfcnRsrpBoost(int LteEarfcnRsrpBoost) {
+ mLteEarfcnRsrpBoost = LteEarfcnRsrpBoost;
+ }
+
+ /** @hide */
public void setCssIndicator(int css) {
this.mCssIndicator = (css != 0);
}
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index c484fd3..9e02399 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -64,6 +64,8 @@
private int mLteRsrq;
private int mLteRssnr;
private int mLteCqi;
+ private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
+ // signal strength level
private int mTdScdmaRscp;
private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult
@@ -104,6 +106,7 @@
mLteRsrq = INVALID;
mLteRssnr = INVALID;
mLteCqi = INVALID;
+ mLteRsrpBoost = 0;
mTdScdmaRscp = INVALID;
isGsm = true;
}
@@ -129,6 +132,7 @@
mLteRsrq = INVALID;
mLteRssnr = INVALID;
mLteCqi = INVALID;
+ mLteRsrpBoost = 0;
mTdScdmaRscp = INVALID;
isGsm = gsmFlag;
}
@@ -142,10 +146,26 @@
int cdmaDbm, int cdmaEcio,
int evdoDbm, int evdoEcio, int evdoSnr,
int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
+ int lteRsrpBoost, int tdScdmaRscp, boolean gsmFlag) {
+ initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+ evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
+ lteRsrq, lteRssnr, lteCqi, lteRsrpBoost, gsmFlag);
+ mTdScdmaRscp = tdScdmaRscp;
+ }
+
+ /**
+ * Constructor
+ *
+ * @hide
+ */
+ public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+ int cdmaDbm, int cdmaEcio,
+ int evdoDbm, int evdoEcio, int evdoSnr,
+ int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
int tdScdmaRscp, boolean gsmFlag) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
- lteRsrq, lteRssnr, lteCqi, gsmFlag);
+ lteRsrq, lteRssnr, lteCqi, 0, gsmFlag);
mTdScdmaRscp = tdScdmaRscp;
}
@@ -161,7 +181,7 @@
boolean gsmFlag) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
- lteRsrq, lteRssnr, lteCqi, gsmFlag);
+ lteRsrq, lteRssnr, lteCqi, 0, gsmFlag);
}
/**
@@ -175,7 +195,7 @@
boolean gsmFlag) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
- INVALID, INVALID, INVALID, gsmFlag);
+ INVALID, INVALID, INVALID, 0, gsmFlag);
}
/**
@@ -209,7 +229,7 @@
boolean gsm) {
initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
- INVALID, INVALID, INVALID, gsm);
+ INVALID, INVALID, INVALID, 0, gsm);
}
/**
@@ -227,6 +247,7 @@
* @param lteRsrq
* @param lteRssnr
* @param lteCqi
+ * @param lteRsrpBoost
* @param gsm
*
* @hide
@@ -235,7 +256,7 @@
int cdmaDbm, int cdmaEcio,
int evdoDbm, int evdoEcio, int evdoSnr,
int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
- boolean gsm) {
+ int lteRsrpBoost, boolean gsm) {
mGsmSignalStrength = gsmSignalStrength;
mGsmBitErrorRate = gsmBitErrorRate;
mCdmaDbm = cdmaDbm;
@@ -248,6 +269,7 @@
mLteRsrq = lteRsrq;
mLteRssnr = lteRssnr;
mLteCqi = lteCqi;
+ mLteRsrpBoost = lteRsrpBoost;
mTdScdmaRscp = INVALID;
isGsm = gsm;
if (DBG) log("initialize: " + toString());
@@ -269,6 +291,7 @@
mLteRsrq = s.mLteRsrq;
mLteRssnr = s.mLteRssnr;
mLteCqi = s.mLteCqi;
+ mLteRsrpBoost = s.mLteRsrpBoost;
mTdScdmaRscp = s.mTdScdmaRscp;
isGsm = s.isGsm;
}
@@ -293,6 +316,7 @@
mLteRsrq = in.readInt();
mLteRssnr = in.readInt();
mLteCqi = in.readInt();
+ mLteRsrpBoost = in.readInt();
mTdScdmaRscp = in.readInt();
isGsm = (in.readInt() != 0);
}
@@ -340,6 +364,7 @@
out.writeInt(mLteRsrq);
out.writeInt(mLteRssnr);
out.writeInt(mLteCqi);
+ out.writeInt(mLteRsrpBoost);
out.writeInt(mTdScdmaRscp);
out.writeInt(isGsm ? 1 : 0);
}
@@ -416,6 +441,18 @@
}
/**
+ * @param lteRsrpBoost - signal strength offset
+ *
+ * Used by phone to set the lte signal strength offset which will be
+ * reduced from rsrp threshold while calculating signal strength level
+ *
+ * @hide
+ */
+ public void setLteRsrpBoost(int lteRsrpBoost) {
+ mLteRsrpBoost = lteRsrpBoost;
+ }
+
+ /**
* Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS
* 27.007 8.5
*/
@@ -490,6 +527,11 @@
return mLteCqi;
}
+ /** @hide */
+ public int getLteRsrpBoost() {
+ return mLteRsrpBoost;
+ }
+
/**
* Retrieve an abstract level value for the overall signal strength.
*
@@ -793,12 +835,19 @@
Log.wtf(LOG_TAG, "getLteLevel - config_lteDbmThresholds has invalid num of elements."
+ " Cannot evaluate RSRP signal.");
} else {
- if (mLteRsrp > threshRsrp[5]) rsrpIconLevel = -1;
- else if (mLteRsrp >= threshRsrp[4]) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
- else if (mLteRsrp >= threshRsrp[3]) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
- else if (mLteRsrp >= threshRsrp[2]) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
- else if (mLteRsrp >= threshRsrp[1]) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
- else if (mLteRsrp >= threshRsrp[0]) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ if (mLteRsrp > threshRsrp[5]) {
+ rsrpIconLevel = -1;
+ } else if (mLteRsrp >= (threshRsrp[4] - mLteRsrpBoost)) {
+ rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
+ } else if (mLteRsrp >= (threshRsrp[3] - mLteRsrpBoost)) {
+ rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
+ } else if (mLteRsrp >= (threshRsrp[2] - mLteRsrpBoost)) {
+ rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
+ } else if (mLteRsrp >= (threshRsrp[1] - mLteRsrpBoost)) {
+ rsrpIconLevel = SIGNAL_STRENGTH_POOR;
+ } else if (mLteRsrp >= threshRsrp[0]) {
+ rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ }
}
/*
@@ -816,7 +865,8 @@
snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
if (DBG) log("getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:"
- + rsrpIconLevel + " snrIconLevel:" + snrIconLevel);
+ + rsrpIconLevel + " snrIconLevel:" + snrIconLevel
+ + " lteRsrpBoost:" + mLteRsrpBoost);
/* Choose a measurement type to use for notification */
if (snrIconLevel != -1 && rsrpIconLevel != -1) {
@@ -939,7 +989,7 @@
+ (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
+ (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
+ (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
- + (mTdScdmaRscp * primeNum) + (isGsm ? 1 : 0));
+ + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum) + (isGsm ? 1 : 0));
}
/**
@@ -971,6 +1021,7 @@
&& mLteRsrq == s.mLteRsrq
&& mLteRssnr == s.mLteRssnr
&& mLteCqi == s.mLteCqi
+ && mLteRsrpBoost == s.mLteRsrpBoost
&& mTdScdmaRscp == s.mTdScdmaRscp
&& isGsm == s.isGsm);
}
@@ -993,6 +1044,7 @@
+ " " + mLteRsrq
+ " " + mLteRssnr
+ " " + mLteCqi
+ + " " + mLteRsrpBoost
+ " " + mTdScdmaRscp
+ " " + (isGsm ? "gsm|lte" : "cdma"));
}
@@ -1016,6 +1068,7 @@
mLteRsrq = m.getInt("LteRsrq");
mLteRssnr = m.getInt("LteRssnr");
mLteCqi = m.getInt("LteCqi");
+ mLteRsrpBoost = m.getInt("lteRsrpBoost");
mTdScdmaRscp = m.getInt("TdScdma");
isGsm = m.getBoolean("isGsm");
}
@@ -1039,6 +1092,7 @@
m.putInt("LteRsrq", mLteRsrq);
m.putInt("LteRssnr", mLteRssnr);
m.putInt("LteCqi", mLteCqi);
+ m.putInt("lteRsrpBoost", mLteRsrpBoost);
m.putInt("TdScdma", mTdScdmaRscp);
m.putBoolean("isGsm", isGsm);
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index dd6f9cb..201f3ad 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -521,14 +521,14 @@
}
/**
- * Get the active SubscriptionInfo associated with the slotIdx
- * @param slotIdx the slot which the subscription is inserted
+ * Get the active SubscriptionInfo associated with the slotIndex
+ * @param slotIndex the slot which the subscription is inserted
* @return SubscriptionInfo, maybe null if its not active
*/
- public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIdx) {
- if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIdx=" + slotIdx);
- if (!isValidSlotId(slotIdx)) {
- logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIdx");
+ public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) {
+ if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex);
+ if (!isValidSlotIndex(slotIndex)) {
+ logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIndex");
return null;
}
@@ -537,7 +537,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIdx,
+ result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
mContext.getOpPackageName());
}
} catch (RemoteException ex) {
@@ -671,24 +671,24 @@
/**
* Add a new SubscriptionInfo to SubscriptionInfo database if needed
* @param iccId the IccId of the SIM card
- * @param slotId the slot which the SIM is inserted
+ * @param slotIndex the slot which the SIM is inserted
* @return the URL of the newly created row or the updated row
* @hide
*/
- public Uri addSubscriptionInfoRecord(String iccId, int slotId) {
- if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotId:" + slotId);
+ public Uri addSubscriptionInfoRecord(String iccId, int slotIndex) {
+ if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotIndex:" + slotIndex);
if (iccId == null) {
logd("[addSubscriptionInfoRecord]- null iccId");
}
- if (!isValidSlotId(slotId)) {
- logd("[addSubscriptionInfoRecord]- invalid slotId");
+ if (!isValidSlotIndex(slotIndex)) {
+ logd("[addSubscriptionInfoRecord]- invalid slotIndex");
}
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
// FIXME: This returns 1 on success, 0 on error should should we return it?
- iSub.addSubInfoRecord(iccId, slotId);
+ iSub.addSubInfoRecord(iccId, slotIndex);
}
} catch (RemoteException ex) {
// ignore it
@@ -830,15 +830,15 @@
}
/**
- * Get slotId associated with the subscription.
- * @return slotId as a positive integer or a negative value if an error either
+ * Get slotIndex associated with the subscription.
+ * @return slotIndex as a positive integer or a negative value if an error either
* SIM_NOT_INSERTED or < 0 if an invalid slot index
* @hide
*/
- public static int getSlotId(int subId) {
+ public static int getSlotIndex(int subId) {
if (!isValidSubscriptionId(subId)) {
if (DBG) {
- logd("[getSlotId]- fail");
+ logd("[getSlotIndex]- fail");
}
}
@@ -847,7 +847,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getSlotId(subId);
+ result = iSub.getSlotIndex(subId);
}
} catch (RemoteException ex) {
// ignore it
@@ -858,8 +858,8 @@
}
/** @hide */
- public static int[] getSubId(int slotId) {
- if (!isValidSlotId(slotId)) {
+ public static int[] getSubId(int slotIndex) {
+ if (!isValidSlotIndex(slotIndex)) {
logd("[getSubId]- fail");
return null;
}
@@ -869,7 +869,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subId = iSub.getSubId(slotId);
+ subId = iSub.getSubId(slotIndex);
}
} catch (RemoteException ex) {
// ignore it
@@ -1155,8 +1155,8 @@
}
/** @hide */
- public static boolean isValidSlotId(int slotId) {
- return slotId >= 0 && slotId < TelephonyManager.getDefault().getSimCount();
+ public static boolean isValidSlotIndex(int slotIndex) {
+ return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSimCount();
}
/** @hide */
@@ -1179,7 +1179,7 @@
if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
- //FIXME this is using phoneId and slotId interchangeably
+ //FIXME this is using phoneId and slotIndex interchangeably
//Eventually, this should be removed as it is not the slot id
intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
}
@@ -1228,9 +1228,9 @@
}
/**
- * Returns a constant indicating the state of sim for the slot idx.
+ * Returns a constant indicating the state of sim for the slot index.
*
- * @param slotIdx
+ * @param slotIndex
*
* {@See TelephonyManager#SIM_STATE_UNKNOWN}
* {@See TelephonyManager#SIM_STATE_ABSENT}
@@ -1244,13 +1244,13 @@
*
* {@hide}
*/
- public static int getSimStateForSlotIdx(int slotIdx) {
+ public static int getSimStateForSlotIndex(int slotIndex) {
int simState = TelephonyManager.SIM_STATE_UNKNOWN;
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- simState = iSub.getSimStateForSlotIdx(slotIdx);
+ simState = iSub.getSimStateForSlotIndex(slotIndex);
}
} catch (RemoteException ex) {
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c691879..a61496d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -46,6 +46,7 @@
import com.android.ims.internal.IImsServiceController;
import com.android.ims.internal.IImsServiceFeatureListener;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telecom.ITelecomService;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.IPhoneSubInfo;
@@ -863,15 +864,15 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
- * @param slotId of which deviceID is returned
+ * @param slotIndex of which deviceID is returned
*/
/** {@hide} */
- public String getDeviceSoftwareVersion(int slotId) {
+ public String getDeviceSoftwareVersion(int slotIndex) {
ITelephony telephony = getITelephony();
if (telephony == null) return null;
try {
- return telephony.getDeviceSoftwareVersionForSlot(slotId, getOpPackageName());
+ return telephony.getDeviceSoftwareVersionForSlot(slotIndex, getOpPackageName());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -885,7 +886,11 @@
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ *
+ * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
+ * MEID for CDMA.
*/
+ @Deprecated
public String getDeviceId() {
try {
ITelephony telephony = getITelephony();
@@ -906,15 +911,19 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
- * @param slotId of which deviceID is returned
+ * @param slotIndex of which deviceID is returned
+ *
+ * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
+ * MEID for CDMA.
*/
- public String getDeviceId(int slotId) {
- // FIXME this assumes phoneId == slotId
+ @Deprecated
+ public String getDeviceId(int slotIndex) {
+ // FIXME this assumes phoneId == slotIndex
try {
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getDeviceIdForPhone(slotId, mContext.getOpPackageName());
+ return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -923,35 +932,62 @@
}
/**
- * Returns the IMEI. Return null if IMEI is not available.
+ * 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}
- *
- * @hide
*/
- @SystemApi
public String getImei() {
return getImei(getDefaultSim());
}
/**
- * Returns the IMEI. Return null if IMEI is not available.
+ * 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}
*
- * @param slotId of which deviceID is returned
- *
- * @hide
+ * @param slotIndex of which IMEI is returned
*/
- @SystemApi
- public String getImei(int slotId) {
+ public String getImei(int slotIndex) {
ITelephony telephony = getITelephony();
if (telephony == null) return null;
try {
- return telephony.getImeiForSlot(slotId, getOpPackageName());
+ return telephony.getImeiForSlot(slotIndex, getOpPackageName());
+ } catch (RemoteException ex) {
+ return null;
+ } catch (NullPointerException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * 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}
+ */
+ public String getMeid() {
+ return getMeid(getDefaultSim());
+ }
+
+ /**
+ * 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}
+ *
+ * @param slotIndex of which MEID is returned
+ */
+ public String getMeid(int slotIndex) {
+ ITelephony telephony = getITelephony();
+ if (telephony == null) return null;
+
+ try {
+ return telephony.getMeidForSlot(slotIndex, getOpPackageName());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -971,11 +1007,11 @@
/**
* Returns the NAI. Return null if NAI is not available.
*
- * @param slotId of which Nai is returned
+ * @param slotIndex of which Nai is returned
*/
/** {@hide}*/
- public String getNai(int slotId) {
- int[] subId = SubscriptionManager.getSubId(slotId);
+ public String getNai(int slotIndex) {
+ int[] subId = SubscriptionManager.getSubId(slotIndex);
try {
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
@@ -1171,23 +1207,23 @@
*
* @hide
*/
- public int getCurrentPhoneTypeForSlot(int slotId) {
+ public int getCurrentPhoneTypeForSlot(int slotIndex) {
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getActivePhoneTypeForSlot(slotId);
+ return telephony.getActivePhoneTypeForSlot(slotIndex);
} else {
// This can happen when the ITelephony interface is not up yet.
- return getPhoneTypeFromProperty(slotId);
+ return getPhoneTypeFromProperty(slotIndex);
}
} catch (RemoteException ex) {
// This shouldn't happen in the normal case, as a backup we
// read from the system property.
- return getPhoneTypeFromProperty(slotId);
+ return getPhoneTypeFromProperty(slotIndex);
} catch (NullPointerException ex) {
// This shouldn't happen in the normal case, as a backup we
// read from the system property.
- return getPhoneTypeFromProperty(slotId);
+ return getPhoneTypeFromProperty(slotIndex);
}
}
@@ -1900,17 +1936,17 @@
/**
* @return true if a ICC card is present for a subscription
*
- * @param slotId for which icc card presence is checked
+ * @param slotIndex for which icc card presence is checked
*/
/** {@hide} */
- // FIXME Input argument slotId should be of type int
- public boolean hasIccCard(int slotId) {
+ // FIXME Input argument slotIndex should be of type int
+ public boolean hasIccCard(int slotIndex) {
try {
ITelephony telephony = getITelephony();
if (telephony == null)
return false;
- return telephony.hasIccCardUsingSlotId(slotId);
+ return telephony.hasIccCardUsingSlotIndex(slotIndex);
} catch (RemoteException ex) {
// Assume no ICC card if remote exception which shouldn't happen
return false;
@@ -1935,31 +1971,31 @@
* @see #SIM_STATE_CARD_RESTRICTED
*/
public int getSimState() {
- int slotIdx = getDefaultSim();
- // slotIdx may be invalid due to sim being absent. In that case query all slots to get
+ int slotIndex = getDefaultSim();
+ // slotIndex may be invalid due to sim being absent. In that case query all slots to get
// sim state
- if (slotIdx < 0) {
+ if (slotIndex < 0) {
// query for all slots and return absent if all sim states are absent, otherwise
// return unknown
for (int i = 0; i < getPhoneCount(); i++) {
int simState = getSimState(i);
if (simState != SIM_STATE_ABSENT) {
- Rlog.d(TAG, "getSimState: default sim:" + slotIdx + ", sim state for " +
- "slotIdx=" + i + " is " + simState + ", return state as unknown");
+ Rlog.d(TAG, "getSimState: default sim:" + slotIndex + ", sim state for " +
+ "slotIndex=" + i + " is " + simState + ", return state as unknown");
return SIM_STATE_UNKNOWN;
}
}
- Rlog.d(TAG, "getSimState: default sim:" + slotIdx + ", all SIMs absent, return " +
+ Rlog.d(TAG, "getSimState: default sim:" + slotIndex + ", all SIMs absent, return " +
"state as absent");
return SIM_STATE_ABSENT;
}
- return getSimState(slotIdx);
+ return getSimState(slotIndex);
}
/**
* Returns a constant indicating the state of the device SIM card in a slot.
*
- * @param slotIdx
+ * @param slotIndex
*
* @see #SIM_STATE_UNKNOWN
* @see #SIM_STATE_ABSENT
@@ -1972,8 +2008,8 @@
* @see #SIM_STATE_CARD_IO_ERROR
* @see #SIM_STATE_CARD_RESTRICTED
*/
- public int getSimState(int slotIdx) {
- int simState = SubscriptionManager.getSimStateForSlotIdx(slotIdx);
+ public int getSimState(int slotIndex) {
+ int simState = SubscriptionManager.getSimStateForSlotIndex(slotIndex);
return simState;
}
@@ -3065,12 +3101,12 @@
*
* @hide
*/
- public int getCallStateForSlot(int slotId) {
+ public int getCallStateForSlot(int slotIndex) {
try {
ITelephony telephony = getITelephony();
if (telephony == null)
return CALL_STATE_IDLE;
- return telephony.getCallStateForSlot(slotId);
+ return telephony.getCallStateForSlot(slotIndex);
} catch (RemoteException ex) {
// the phone process is restarting.
return CALL_STATE_IDLE;
@@ -3204,7 +3240,7 @@
public void listen(PhoneStateListener listener, int events) {
if (mContext == null) return;
try {
- Boolean notifyNow = (getITelephony() != null);
+ boolean notifyNow = (getITelephony() != null);
// If the listener has not explicitly set the subId (for example, created with the
// default constructor), replace the subId so it will listen to the account the
// telephony manager is created with.
@@ -3886,9 +3922,19 @@
return SubscriptionManager.getPhoneId(SubscriptionManager.getDefaultSubscriptionId());
}
- /** {@hide} */
+ /**
+ * @return default SIM's slot index. If SIM is not inserted, return default SIM slot index.
+ *
+ * {@hide}
+ */
+ @VisibleForTesting
public int getDefaultSim() {
- return SubscriptionManager.getSlotId(SubscriptionManager.getDefaultSubscriptionId());
+ int slotIndex = SubscriptionManager.getSlotIndex(
+ SubscriptionManager.getDefaultSubscriptionId());
+ if (slotIndex == SubscriptionManager.SIM_NOT_INSERTED) {
+ slotIndex = SubscriptionManager.DEFAULT_SIM_SLOT_INDEX;
+ }
+ return slotIndex;
}
/**
@@ -4253,7 +4299,7 @@
* feature or {@link null} if the service is not available. If an ImsServiceController is
* available, the {@link IImsServiceFeatureListener} callback is registered as a listener for
* feature updates.
- * @param slotId The SIM slot that we are requesting the {@link IImsServiceController} for.
+ * @param slotIndex The SIM slot that we are requesting the {@link IImsServiceController} for.
* @param feature The IMS Feature we are requesting, corresponding to {@link ImsFeature}.
* @param callback Listener that will send updates to ImsManager when there are updates to
* ImsServiceController.
@@ -4261,12 +4307,12 @@
* it is unavailable.
* @hide
*/
- public IImsServiceController getImsServiceControllerAndListen(int slotId, @Feature int feature,
+ public IImsServiceController getImsServiceControllerAndListen(int slotIndex, @Feature int feature,
IImsServiceFeatureListener callback) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getImsServiceControllerAndListen(slotId, feature, callback);
+ return telephony.getImsServiceControllerAndListen(slotIndex, feature, callback);
}
} catch (RemoteException e) {
Rlog.e(TAG, "getImsServiceControllerAndListen, RemoteException: " + e.getMessage());
@@ -5404,7 +5450,7 @@
/**
* Set SIM card power state. Request is equivalent to inserting or removing the card.
*
- * @param slotId SIM slot id
+ * @param slotIndex SIM slot id
* @param powerUp True if powering up the SIM, otherwise powering down
*
* <p>Requires Permission:
@@ -5412,11 +5458,11 @@
*
* @hide
**/
- public void setSimPowerStateForSlot(int slotId, boolean powerUp) {
+ public void setSimPowerStateForSlot(int slotIndex, boolean powerUp) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- telephony.setSimPowerStateForSlot(slotId, powerUp);
+ telephony.setSimPowerStateForSlot(slotIndex, powerUp);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#setSimPowerStateForSlot", e);
@@ -5952,7 +5998,7 @@
}
/**
- * Set the allowed carrier list for slotId
+ * Set the allowed carrier list for slotIndex
* Require system privileges. In the future we may add this to carrier APIs.
*
* <p>Requires Permission:
@@ -5966,11 +6012,11 @@
* @hide
*/
@SystemApi
- public int setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers) {
+ public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.setAllowedCarriers(slotId, carriers);
+ return service.setAllowedCarriers(slotIndex, carriers);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
@@ -5981,7 +6027,7 @@
}
/**
- * Get the allowed carrier list for slotId.
+ * Get the allowed carrier list for slotIndex.
* Require system privileges. In the future we may add this to carrier APIs.
*
* <p>Requires Permission:
@@ -5995,11 +6041,11 @@
* @hide
*/
@SystemApi
- public List<CarrierIdentifier> getAllowedCarriers(int slotId) {
+ public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getAllowedCarriers(slotId);
+ return service.getAllowedCarriers(slotIndex);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
diff --git a/telephony/java/com/android/ims/ImsException.java b/telephony/java/com/android/ims/ImsException.java
index 74b20f4..0e8bad7 100644
--- a/telephony/java/com/android/ims/ImsException.java
+++ b/telephony/java/com/android/ims/ImsException.java
@@ -32,7 +32,7 @@
}
public ImsException(String message, int code) {
- super(message + ", code = " + code);
+ super(message + "(" + code + ")");
mCode = code;
}
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index e4f380f..bd8492b3 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -318,6 +318,66 @@
*/
public static final int CODE_IKEV2_AUTH_FAILURE = 1408;
+ /** The call cannot be established because RADIO is OFF */
+ public static final int CODE_RADIO_OFF = 1500;
+
+ /** The call cannot be established because of no valid SIM */
+ public static final int CODE_NO_VALID_SIM = 1501;
+
+ /** The failure is due internal error at modem */
+ public static final int CODE_RADIO_INTERNAL_ERROR = 1502;
+
+ /** The failure is due to UE timer expired while waiting for a response from network */
+ public static final int CODE_NETWORK_RESP_TIMEOUT = 1503;
+
+ /** The failure is due to explicit reject from network */
+ public static final int CODE_NETWORK_REJECT = 1504;
+
+ /** The failure is due to radio access failure. ex. RACH failure */
+ public static final int CODE_RADIO_ACCESS_FAILURE = 1505;
+
+ /** Call/IMS registration failed/dropped because of a RLF */
+ public static final int CODE_RADIO_LINK_FAILURE = 1506;
+
+ /** Call/IMS registration failed/dropped because of radio link lost */
+ public static final int CODE_RADIO_LINK_LOST = 1507;
+
+ /** The call Call/IMS registration failed because of a radio uplink issue */
+ public static final int CODE_RADIO_UPLINK_FAILURE = 1508;
+
+ /** Call failed because of a RRC connection setup failure */
+ public static final int CODE_RADIO_SETUP_FAILURE = 1509;
+
+ /** Call failed/dropped because of RRC connection release from NW */
+ public static final int CODE_RADIO_RELEASE_NORMAL = 1510;
+
+ /** Call failed/dropped because of RRC abnormally released by modem/network */
+ public static final int CODE_RADIO_RELEASE_ABNORMAL = 1511;
+
+ /** Call failed because of access class barring */
+ public static final int CODE_ACCESS_CLASS_BLOCKED = 1512;
+
+ /** Call/IMS registration is failed/dropped because of a network detach */
+ public static final int CODE_NETWORK_DETACH = 1513;
+
+ /* OEM specific error codes. To be used by OEMs when they don't want to
+ reveal error code which would be replaced by ERROR_UNSPECIFIED */
+ public static final int CODE_OEM_CAUSE_1 = 0xf001;
+ public static final int CODE_OEM_CAUSE_2 = 0xf002;
+ public static final int CODE_OEM_CAUSE_3 = 0xf003;
+ public static final int CODE_OEM_CAUSE_4 = 0xf004;
+ public static final int CODE_OEM_CAUSE_5 = 0xf005;
+ public static final int CODE_OEM_CAUSE_6 = 0xf006;
+ public static final int CODE_OEM_CAUSE_7 = 0xf007;
+ public static final int CODE_OEM_CAUSE_8 = 0xf008;
+ public static final int CODE_OEM_CAUSE_9 = 0xf009;
+ public static final int CODE_OEM_CAUSE_10 = 0xf00a;
+ public static final int CODE_OEM_CAUSE_11 = 0xf00b;
+ public static final int CODE_OEM_CAUSE_12 = 0xf00c;
+ public static final int CODE_OEM_CAUSE_13 = 0xf00d;
+ public static final int CODE_OEM_CAUSE_14 = 0xf00e;
+ public static final int CODE_OEM_CAUSE_15 = 0xf00f;
+
/**
* Network string error messages.
* mExtraMessage may have these values.
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index f6aef08..71f2c6b 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -52,12 +52,12 @@
SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId, String callingPackage);
/**
- * Get the active SubscriptionInfo associated with the slotIdx
- * @param slotIdx the slot which the subscription is inserted
+ * Get the active SubscriptionInfo associated with the slotIndex
+ * @param slotIndex the slot which the subscription is inserted
* @param callingPackage The package maing the call.
* @return SubscriptionInfo, maybe null if its not active
*/
- SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIdx, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, String callingPackage);
/**
* Get the SubscriptionInfo(s) of the active subscriptions. The records will be sorted
@@ -96,10 +96,10 @@
/**
* Add a new SubscriptionInfo to subinfo database if needed
* @param iccId the IccId of the SIM card
- * @param slotId the slot which the SIM is inserted
+ * @param slotIndex the slot which the SIM is inserted
* @return the URL of the newly created row or the updated row
*/
- int addSubInfoRecord(String iccId, int slotId);
+ int addSubInfoRecord(String iccId, int slotIndex);
/**
* Set SIM icon tint color by simInfo index
@@ -142,9 +142,9 @@
*/
int setDataRoaming(int roaming, int subId);
- int getSlotId(int subId);
+ int getSlotIndex(int subId);
- int[] getSubId(int slotId);
+ int[] getSubId(int slotIndex);
int getDefaultSubId();
@@ -177,10 +177,10 @@
String getSubscriptionProperty(int subId, String propKey, String callingPackage);
/**
- * Get the SIM state for the slot idx
+ * Get the SIM state for the slot index
* @return SIM state as the ordinal of IccCardConstants.State
*/
- int getSimStateForSlotIdx(int slotIdx);
+ int getSimStateForSlotIndex(int slotIndex);
boolean isActiveSubId(int subId);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index d21efc6..5c37822 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -370,7 +370,7 @@
/**
* Returns the call state for a slot.
*/
- int getCallStateForSlot(int slotId);
+ int getCallStateForSlot(int slotIndex);
int getDataActivity();
int getDataState();
@@ -386,9 +386,9 @@
* Returns the current active phone type as integer for particular slot.
* Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE
* and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
- * @param slotId - slot to query.
+ * @param slotIndex - slot to query.
*/
- int getActivePhoneTypeForSlot(int slotId);
+ int getActivePhoneTypeForSlot(int slotIndex);
/**
* Returns the CDMA ERI icon index to display
@@ -542,10 +542,10 @@
/**
* Return true if an ICC card is present for a subId.
- * @param slotId user preferred slotId.
+ * @param slotIndex user preferred slotIndex.
* Return true if an ICC card is present
*/
- boolean hasIccCardUsingSlotId(int slotId);
+ boolean hasIccCardUsingSlotIndex(int slotIndex);
/**
* Return if the current radio is LTE on CDMA. This
@@ -746,7 +746,7 @@
* requested as well as registering the ImsServiceController for callbacks using the
* IImsServiceFeatureListener interface.
*/
- IImsServiceController getImsServiceControllerAndListen(int slotId, int feature,
+ IImsServiceController getImsServiceControllerAndListen(int slotIndex, int feature,
IImsServiceFeatureListener callback);
/**
@@ -1054,22 +1054,32 @@
/**
* Returns the IMEI for the given slot.
*
- * @param slotId - device slot.
+ * @param slotIndex - device slot.
* @param callingPackage The package making the call.
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getImeiForSlot(int slotId, String callingPackage);
+ String getImeiForSlot(int slotIndex, String callingPackage);
+
+ /**
+ * Returns the MEID for the given slot.
+ *
+ * @param slotIndex - device slot.
+ * @param callingPackage The package making the call.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ */
+ String getMeidForSlot(int slotIndex, String callingPackage);
/**
* Returns the device software version.
*
- * @param slotId - device slot.
+ * @param slotIndex - device slot.
* @param callingPackage The package making the call.
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getDeviceSoftwareVersionForSlot(int slotId, String callingPackage);
+ String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage);
/**
* Returns the subscription ID associated with the specified PhoneAccount.
@@ -1167,22 +1177,22 @@
List<TelephonyHistogram> getTelephonyHistograms();
/**
- * Set the allowed carrier list for slotId
+ * Set the allowed carrier list for slotIndex
* Require system privileges. In the future we may add this to carrier APIs.
*
* @return The number of carriers set successfully. Should match length of
* carriers on success.
*/
- int setAllowedCarriers(int slotId, in List<CarrierIdentifier> carriers);
+ int setAllowedCarriers(int slotIndex, in List<CarrierIdentifier> carriers);
/**
- * Get the allowed carrier list for slotId.
+ * Get the allowed carrier list for slotIndex.
* Require system privileges. In the future we may add this to carrier APIs.
*
* @return List of {@link android.service.carrier.CarrierIdentifier}; empty list
* means all carriers are allowed.
*/
- List<CarrierIdentifier> getAllowedCarriers(int slotId);
+ List<CarrierIdentifier> getAllowedCarriers(int slotIndex);
/**
* Action set from carrier signalling broadcast receivers to enable/disable metered apns
@@ -1229,11 +1239,11 @@
/**
* Set SIM card power state. Request is equivalent to inserting or removing the card.
- * @param slotId SIM slot id
+ * @param slotIndex SIM slot id
* @param powerUp True if powering up the SIM, otherwise powering down
* @hide
* */
- void setSimPowerStateForSlot(int slotId, boolean powerUp);
+ void setSimPowerStateForSlot(int slotIndex, boolean powerUp);
/**
* Returns a list of Forbidden PLMNs from the specified SIM App
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 682b672..c17c521 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -261,7 +261,7 @@
* by the system.
*/
public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS
- = "android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS";
+ = "com.android.internal.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS";
/**
* <p>Broadcast Action: Indicates that the action is forbidden by network.
diff --git a/tests/net/java/android/net/ip/IpManagerTest.java b/tests/net/java/android/net/ip/IpManagerTest.java
new file mode 100644
index 0000000..025b017
--- /dev/null
+++ b/tests/net/java/android/net/ip/IpManagerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2017 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.net.ip;
+
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.INetworkManagementService;
+import android.provider.Settings;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContentResolver;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.internal.R;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for IpManager.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpManagerTest {
+ private static final int DEFAULT_AVOIDBADWIFI_CONFIG_VALUE = 1;
+
+ @Mock private Context mContext;
+ @Mock private INetworkManagementService mNMService;
+ @Mock private Resources mResources;
+ private MockContentResolver mContentResolver;
+
+ @Before public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
+ .thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
+
+ mContentResolver = new MockContentResolver();
+ mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ }
+
+ @Test
+ public void testNullCallbackDoesNotThrow() throws Exception {
+ final IpManager ipm = new IpManager(mContext, "lo", null, mNMService);
+ }
+
+ @Test
+ public void testInvalidInterfaceDoesNotThrow() throws Exception {
+ final IpManager.Callback cb = new IpManager.Callback();
+ final IpManager ipm = new IpManager(mContext, "test_wlan0", cb, mNMService);
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b033382..519e7ab 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -23,7 +23,12 @@
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.NetworkCapabilities.*;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -33,6 +38,7 @@
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivityManager.PacketKeepalive;
@@ -76,11 +82,16 @@
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
import com.android.server.net.NetworkPinner;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
@@ -133,8 +144,19 @@
private class MockContext extends BroadcastInterceptingContext {
private final MockContentResolver mContentResolver;
+ @Spy private Resources mResources;
+
MockContext(Context base) {
super(base);
+
+ mResources = spy(base.getResources());
+ when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
+ thenReturn(new String[] {
+ "wifi,1,1,1,-1,true",
+ "mobile,0,0,0,-1,true",
+ "mobile_mms,2,0,2,60000,true",
+ });
+
mContentResolver = new MockContentResolver();
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
}
@@ -150,6 +172,11 @@
public ContentResolver getContentResolver() {
return mContentResolver;
}
+
+ @Override
+ public Resources getResources() {
+ return mResources;
+ }
}
/**
@@ -614,6 +641,7 @@
private class WrappedConnectivityService extends ConnectivityService {
public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
+ private MockableSystemProperties mSystemProperties;
public WrappedConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
@@ -623,9 +651,13 @@
}
@Override
- protected int getDefaultTcpRwnd() {
- // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
- return 0;
+ protected MockableSystemProperties getSystemProperties() {
+ // Minimal approach to overriding system properties: let most calls fall through to real
+ // device values, and only override ones values that are important to this test.
+ mSystemProperties = spy(new MockableSystemProperties());
+ when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
+ when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
+ return mSystemProperties;
}
@Override
@@ -795,6 +827,14 @@
return cv;
}
+ public void testNetworkTypes() {
+ // Ensure that our mocks for the networkAttributes config variable work as expected. If they
+ // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
+ // will fail. Failing here is much easier to debug.
+ assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
+ assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
+ }
+
@SmallTest
public void testLingering() throws Exception {
verifyNoNetwork();
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index b51b277..efe6fec 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -27,10 +27,12 @@
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.UidRange;
+import android.os.Build;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.UserHandle;
@@ -45,6 +47,7 @@
import java.util.Map;
import java.util.Set;
+import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
@@ -87,12 +90,13 @@
}
}
- @Mock private Context mContext;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
@Mock private UserManager mUserManager;
@Mock private PackageManager mPackageManager;
@Mock private INetworkManagementService mNetService;
@Mock private AppOpsManager mAppOps;
@Mock private NotificationManager mNotificationManager;
+ @Mock private Vpn.SystemServices mSystemServices;
@Override
public void setUp() throws Exception {
@@ -104,6 +108,12 @@
when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
.thenReturn(mNotificationManager);
+
+ // Used by {@link Notification.Builder}
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+ when(mContext.getApplicationInfo()).thenReturn(applicationInfo);
+
doNothing().when(mNetService).registerObserver(any());
}
@@ -111,7 +121,7 @@
public void testRestrictedProfilesAreAddedToVpn() {
setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB);
- final Vpn vpn = spyVpn(primaryUser.id);
+ final Vpn vpn = createVpn(primaryUser.id);
final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
null, null);
@@ -125,7 +135,7 @@
public void testManagedProfilesAreNotAddedToVpn() {
setMockedUsers(primaryUser, managedProfileA);
- final Vpn vpn = spyVpn(primaryUser.id);
+ final Vpn vpn = createVpn(primaryUser.id);
final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
null, null);
@@ -138,7 +148,7 @@
public void testAddUserToVpnOnlyAddsOneUser() {
setMockedUsers(primaryUser, restrictedProfileA, managedProfileA);
- final Vpn vpn = spyVpn(primaryUser.id);
+ final Vpn vpn = createVpn(primaryUser.id);
final Set<UidRange> ranges = new ArraySet<>();
vpn.addUserToRanges(ranges, primaryUser.id, null, null);
@@ -149,7 +159,7 @@
@SmallTest
public void testUidWhiteAndBlacklist() throws Exception {
- final Vpn vpn = spyVpn(primaryUser.id);
+ final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id);
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
@@ -174,7 +184,7 @@
@SmallTest
public void testLockdownChangingPackage() throws Exception {
- final Vpn vpn = spyVpn(primaryUser.id);
+ final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id);
// Default state.
@@ -209,7 +219,7 @@
@SmallTest
public void testLockdownAddingAProfile() throws Exception {
- final Vpn vpn = spyVpn(primaryUser.id);
+ final Vpn vpn = createVpn(primaryUser.id);
setMockedUsers(primaryUser);
// Make a copy of the restricted profile, as we're going to mark it deleted halfway through.
@@ -249,40 +259,41 @@
@SmallTest
public void testNotificationShownForAlwaysOnApp() {
- final Vpn vpn = spyVpn(primaryUser.id);
- final InOrder order = inOrder(vpn);
+ final UserHandle userHandle = UserHandle.of(primaryUser.id);
+ final Vpn vpn = createVpn(primaryUser.id);
setMockedUsers(primaryUser);
+ final InOrder order = inOrder(mNotificationManager);
+
// Don't show a notification for regular disconnected states.
vpn.updateState(DetailedState.DISCONNECTED, TAG);
- order.verify(vpn).updateAlwaysOnNotificationInternal(false);
+ order.verify(mNotificationManager, atLeastOnce())
+ .cancelAsUser(anyString(), anyInt(), eq(userHandle));
// Start showing a notification for disconnected once always-on.
vpn.setAlwaysOnPackage(PKGS[0], false);
- order.verify(vpn).updateAlwaysOnNotificationInternal(true);
+ order.verify(mNotificationManager)
+ .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
// Stop showing the notification once connected.
vpn.updateState(DetailedState.CONNECTED, TAG);
- order.verify(vpn).updateAlwaysOnNotificationInternal(false);
+ order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
// Show the notification if we disconnect again.
vpn.updateState(DetailedState.DISCONNECTED, TAG);
- order.verify(vpn).updateAlwaysOnNotificationInternal(true);
+ order.verify(mNotificationManager)
+ .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
// Notification should be cleared after unsetting always-on package.
vpn.setAlwaysOnPackage(null, false);
- order.verify(vpn).updateAlwaysOnNotificationInternal(false);
+ order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
}
/**
* Mock some methods of vpn object.
*/
- private Vpn spyVpn(@UserIdInt int userId) {
- final Vpn vpn = spy(new Vpn(Looper.myLooper(), mContext, mNetService, userId));
-
- // Block calls to the NotificationManager or PendingIntent#getActivity.
- doNothing().when(vpn).updateAlwaysOnNotificationInternal(anyBoolean());
- return vpn;
+ private Vpn createVpn(@UserIdInt int userId) {
+ return new Vpn(Looper.myLooper(), mContext, mNetService, userId, mSystemServices);
}
private static void assertBlocked(Vpn vpn, int... uids) {
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 18c1245..65b437d 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -16,7 +16,11 @@
package android.net.wifi;
+
+import android.content.pm.ParceledListSlice;
+
import android.net.wifi.hotspot2.PasspointConfiguration;
+
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.ScanSettings;
@@ -51,9 +55,9 @@
*/
oneway void requestActivityInfo(in ResultReceiver result);
- List<WifiConfiguration> getConfiguredNetworks();
+ ParceledListSlice getConfiguredNetworks();
- List<WifiConfiguration> getPrivilegedConfiguredNetworks();
+ ParceledListSlice getPrivilegedConfiguredNetworks();
WifiConfiguration getMatchingWifiConfig(in ScanResult scanResult);
@@ -77,8 +81,6 @@
boolean disableNetwork(int netId);
- boolean pingSupplicant();
-
void startScan(in ScanSettings requested, in WorkSource ws);
List<ScanResult> getScanResults(String callingPackage);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 6095c86..dac511e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -281,7 +281,9 @@
public int apChannel = 0;
/**
- * Pre-shared key for use with WPA-PSK.
+ * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in
+ * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or
+ * a string of 64 hex digits for raw PSK.
* <p/>
* When the value of this key is read, the actual key is
* not returned, just a "*" if the key has a value, or the null
@@ -305,7 +307,7 @@
/**
* Priority determines the preference given to a network by {@code wpa_supplicant}
* when choosing an access point with which to associate.
- * @deprecated Priority is no longer used.
+ * @deprecated This field does not exist anymore.
*/
@Deprecated
public int priority;
@@ -434,6 +436,13 @@
public int dtimInterval = 0;
/**
+ * Flag indicating if this configuration represents a legacy Passpoint configuration
+ * (Release N or older). This is used for migrating Passpoint configuration from N to O.
+ * This will no longer be needed after O.
+ * @hide
+ */
+ public boolean isLegacyPasspointConfig = false;
+ /**
* @hide
* Uid of app creating the configuration
*/
@@ -1951,6 +1960,7 @@
mCachedConfigKey = null; //force null configKey
selfAdded = source.selfAdded;
validatedInternetAccess = source.validatedInternetAccess;
+ isLegacyPasspointConfig = source.isLegacyPasspointConfig;
ephemeral = source.ephemeral;
meteredHint = source.meteredHint;
meteredOverride = source.meteredOverride;
@@ -2027,6 +2037,7 @@
dest.writeInt(selfAdded ? 1 : 0);
dest.writeInt(didSelfAdd ? 1 : 0);
dest.writeInt(validatedInternetAccess ? 1 : 0);
+ dest.writeInt(isLegacyPasspointConfig ? 1 : 0);
dest.writeInt(ephemeral ? 1 : 0);
dest.writeInt(meteredHint ? 1 : 0);
dest.writeInt(meteredOverride ? 1 : 0);
@@ -2093,6 +2104,7 @@
config.selfAdded = in.readInt() != 0;
config.didSelfAdd = in.readInt() != 0;
config.validatedInternetAccess = in.readInt() != 0;
+ config.isLegacyPasspointConfig = in.readInt() != 0;
config.ephemeral = in.readInt() != 0;
config.meteredHint = in.readInt() != 0;
config.meteredOverride = in.readInt() != 0;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index ed6a166..b79ecdd 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -21,6 +21,7 @@
import android.annotation.SystemApi;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
+import android.content.pm.ParceledListSlice;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.Network;
@@ -46,6 +47,7 @@
import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.CountDownLatch;
+import java.util.Collections;
/**
* This class provides the primary API for managing all aspects of Wi-Fi
@@ -80,6 +82,34 @@
public static final int ERROR_AUTHENTICATING = 1;
/**
+ * The reason code if there is no error during authentication.
+ * It could also imply that there no authentication in progress,
+ * this reason code also serves as a reset value.
+ * @hide
+ */
+ public static final int ERROR_AUTH_FAILURE_NONE = 0;
+
+ /**
+ * The reason code if there was a timeout authenticating.
+ * @hide
+ */
+ public static final int ERROR_AUTH_FAILURE_TIMEOUT = 1;
+
+ /**
+ * The reason code if there was a wrong password while
+ * authenticating.
+ * @hide
+ */
+ public static final int ERROR_AUTH_FAILURE_WRONG_PSWD = 2;
+
+ /**
+ * The reason code if there was EAP failure while
+ * authenticating.
+ * @hide
+ */
+ public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3;
+
+ /**
* Broadcast intent action indicating whether Wi-Fi scanning is allowed currently
* @hide
*/
@@ -114,166 +144,125 @@
public static final int WIFI_CREDENTIAL_FORGOT = 1;
/**
- * Broadcast intent action indicating that the a Passpoint release 2 icon has been received.
- * @hide
- */
- public static final String PASSPOINT_ICON_RECEIVED_ACTION =
- "android.net.wifi.PASSPOINT_ICON_RECEIVED";
- /** @hide */
- public static final String EXTRA_PASSPOINT_ICON_FILE = "file";
-
- /**
- * Broadcast intent action indicating that the a Passpoint release
- * 2 WNM frame has been received.
- * @hide
- */
- public static final String PASSPOINT_WNM_FRAME_RECEIVED_ACTION =
- "android.net.wifi.PASSPOINT_WNM_FRAME_RECEIVED";
- /**
- * Originating BSS
- * @hide */
- public static final String EXTRA_PASSPOINT_WNM_BSSID = "bssid";
- /**
- * SOAP-XML or OMA-DM
- * @hide */
- public static final String EXTRA_PASSPOINT_WNM_METHOD = "method";
- /**
- * Type of Passpoint match
- * @hide */
- public static final String EXTRA_PASSPOINT_WNM_PPOINT_MATCH = "match";
- /**
- * String
- * @hide */
- public static final String EXTRA_PASSPOINT_WNM_URL = "url";
- /**
- * Boolean true=ess, false=bss
- * @hide */
- public static final String EXTRA_PASSPOINT_WNM_ESS = "ess";
- /**
- * Delay in seconds
- * @hide */
- public static final String EXTRA_PASSPOINT_WNM_DELAY = "delay";
-
- /**
* Broadcast intent action indicating that a Passpoint provider icon has been received.
*
+ * Included extras:
+ * {@link #EXTRA_BSSID_LONG}
+ * {@link #EXTRA_FILENAME}
+ * {@link #EXTRA_ICON}
+ *
* Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
- */
- public static final String ACTION_PASSPOINT_ICON =
- "android.net.wifi.action.PASSPOINT_ICON";
- /**
- * BSSID of the sender.
*
- * Type: long
+ * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+ * components will be launched.
*/
- public static final String EXTRA_PASSPOINT_ICON_BSSID =
- "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
+ public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
/**
- * Filename of the icon.
+ * BSSID of an AP in long representation. The {@link #EXTRA_BSSID} contains BSSID in
+ * String representation.
*
- * Type: String
+ * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}.
*/
- public static final String EXTRA_PASSPOINT_ICON_FILENAME =
- "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
+ public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
/**
- * Binary blob of the icon.
+ * Icon data.
*
- * Type: byte[]
+ * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into
+ * {@link android.graphics.drawable.Icon}.
*/
- public static final String EXTRA_PASSPOINT_ICON_DATA =
- "android.net.wifi.extra.PASSPOINT_ICON_DATA";
+ public static final String EXTRA_ICON = "android.net.wifi.extra.ICON";
+ /**
+ * Name of a file.
+ *
+ * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
+ */
+ public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
/**
* Broadcast intent action indicating a Passpoint OSU Providers List element has been received.
*
+ * Included extras:
+ * {@link #EXTRA_BSSID_LONG}
+ * {@link #EXTRA_ANQP_ELEMENT_DATA}
+ *
* Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+ *
+ * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+ * components will be launched.
+ *
*/
public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST =
"android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
/**
- * BSSID of the sender.
+ * Raw binary data of an ANQP (Access Network Query Protocol) element.
*
- * Type: long
+ * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}.
*/
- public static final String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID =
- "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
- /**
- * Raw data of OSU Providers List ANQP element. Refer to Section 4.8 of Hotspot 2.0 Release 2
- * Technical Specification for the exact data format.
- *
- * Type: byte[]
- */
- public static final String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA =
- "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
+ public static final String EXTRA_ANQP_ELEMENT_DATA =
+ "android.net.wifi.extra.ANQP_ELEMENT_DATA";
/**
* Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received.
*
+ * Included extras:
+ * {@link #EXTRA_BSSID_LONG}
+ * {@link #EXTRA_ESS}
+ * {@link #EXTRA_DELAY}
+ * {@link #EXTRA_URL}
+ *
* Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+ *
+ * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+ * components will be launched.
+ *
*/
public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT =
"android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
/**
- * The BSSID of the sender.
+ * Flag indicating BSS (Basic Service Set) or ESS (Extended Service Set). This will be set to
+ * {@code true} for ESS.
*
- * Type: long
+ * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}.
*/
- public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID =
- "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
+ public static final String EXTRA_ESS = "android.net.wifi.extra.ESS";
/**
- * Flag indicating failure at BSS (Basic Service Set) or ESS (Extended Service Set) level.
+ * Delay in seconds.
*
- * Type: boolean
+ * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}.
*/
- public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS =
- "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
+ public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
/**
- * Delay in seconds that a device shall wait before attempting re-association to the same BSS
- * or ESS (as indicated by {@link #EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS}.
+ * String representation of an URL.
*
- * Type: int
+ * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
*/
- public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY =
- "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
- /**
- * URL that provides a webpage explaining the deauth reason.
- *
- * Type: String
- */
- public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL =
- "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
+ public static final String EXTRA_URL = "android.net.wifi.extra.URL";
/**
* Broadcast intent action indicating a Passpoint subscription remediation frame has been
* received.
*
+ * Included extras:
+ * {@link #EXTRA_BSSID_LONG}
+ * {@link #EXTRA_SUBSCRIPTION_REMEDIATION_METHOD}
+ * {@link #EXTRA_URL}
+ *
* Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+ *
+ ** <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+ * components will be launched.
*/
public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION =
"android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
/**
- * The BSSID of the sender.
- *
- * Type: long
- */
- public static final String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID =
- "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
- /**
* The protocol supported by the subscription remediation server. The possible values are:
* 0 - OMA DM
* 1 - SOAP XML SPP
*
- * Type: int
+ * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}.
*/
- public static final String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD =
- "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
- /**
- * URL of the subscription remediation server.
- *
- * Type: String
- */
- public static final String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL =
- "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
+ public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD =
+ "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
/**
* Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
@@ -536,6 +525,16 @@
public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError";
/**
+ * The lookup key for a {@link SupplicantState} describing the supplicant
+ * error reason if any
+ * Retrieve with
+ * {@link android.content.Intent#getIntExtra(String, int)}.
+ * @see #ERROR_AUTH_FAILURE_#REASON_CODE
+ * @hide
+ */
+ public static final String EXTRA_SUPPLICANT_ERROR_REASON = "supplicantErrorReason";
+
+ /**
* Broadcast intent action indicating that the configured networks changed.
* This can be as a result of adding/updating/deleting a network. If
* {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration
@@ -859,7 +858,12 @@
*/
public List<WifiConfiguration> getConfiguredNetworks() {
try {
- return mService.getConfiguredNetworks();
+ ParceledListSlice<WifiConfiguration> parceledList =
+ mService.getConfiguredNetworks();
+ if (parceledList == null) {
+ return Collections.emptyList();
+ }
+ return parceledList.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -869,7 +873,12 @@
@SystemApi
public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
try {
- return mService.getPrivilegedConfiguredNetworks();
+ ParceledListSlice<WifiConfiguration> parceledList =
+ mService.getPrivilegedConfiguredNetworks();
+ if (parceledList == null) {
+ return Collections.emptyList();
+ }
+ return parceledList.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -972,12 +981,15 @@
* Name). In the case when there is an existing configuration with the same
* FQDN, the new configuration will replace the existing configuration.
*
+ * An {@link IllegalArgumentException} will be thrown on failure.
+ *
* @param config The Passpoint configuration to be added
- * @return true on success
*/
- public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
+ public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
try {
- return mService.addOrUpdatePasspointConfiguration(config);
+ if (!mService.addOrUpdatePasspointConfiguration(config)) {
+ throw new IllegalArgumentException();
+ }
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -986,12 +998,15 @@
/**
* Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
*
+ * An {@link IllegalArgumentException} will be thrown on failure.
+ *
* @param fqdn The FQDN of the passpoint configuration to be removed
- * @return true on success
*/
- public boolean removePasspointConfiguration(String fqdn) {
+ public void removePasspointConfiguration(String fqdn) {
try {
- return mService.removePasspointConfiguration(fqdn);
+ if (!mService.removePasspointConfiguration(fqdn)) {
+ throw new IllegalArgumentException();
+ }
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1013,10 +1028,13 @@
}
/**
- * Query for a Hotspot 2.0 release 2 OSU icon file.
+ * Query for a Hotspot 2.0 release 2 OSU icon file. An {@link #ACTION_PASSPOINT_ICON} intent
+ * will be broadcasted once the request is completed. The presence of the intent extra
+ * {@link #EXTRA_ICON} will indicate the result of the request.
+ * A missing intent extra {@link #EXTRA_ICON} will indicate a failure.
*
* @param bssid The BSSID of the AP
- * @param fileName File name of the icon to query
+ * @param fileName Name of the icon file (remote file) to query from the AP
*/
public void queryPasspointIcon(long bssid, String fileName) {
try {
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 5847f79..40e34b1 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -934,46 +934,13 @@
/** Implement the Parcelable interface {@hide} */
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(rssiSampleSize);
- dest.writeInt(lostApSampleSize);
- dest.writeInt(unchangedSampleSize);
- dest.writeInt(minApsBreachingThreshold);
- dest.writeInt(periodInMs);
- if (bssidInfos != null) {
- dest.writeInt(bssidInfos.length);
- for (int i = 0; i < bssidInfos.length; i++) {
- BssidInfo info = bssidInfos[i];
- dest.writeString(info.bssid);
- dest.writeInt(info.low);
- dest.writeInt(info.high);
- dest.writeInt(info.frequencyHint);
- }
- } else {
- dest.writeInt(0);
- }
}
/** Implement the Parcelable interface {@hide} */
public static final Creator<WifiChangeSettings> CREATOR =
new Creator<WifiChangeSettings>() {
public WifiChangeSettings createFromParcel(Parcel in) {
- WifiChangeSettings settings = new WifiChangeSettings();
- settings.rssiSampleSize = in.readInt();
- settings.lostApSampleSize = in.readInt();
- settings.unchangedSampleSize = in.readInt();
- settings.minApsBreachingThreshold = in.readInt();
- settings.periodInMs = in.readInt();
- int len = in.readInt();
- settings.bssidInfos = new BssidInfo[len];
- for (int i = 0; i < len; i++) {
- BssidInfo info = new BssidInfo();
- info.bssid = in.readString();
- info.low = in.readInt();
- info.high = in.readInt();
- info.frequencyHint = in.readInt();
- settings.bssidInfos[i] = info;
- }
- return settings;
+ return new WifiChangeSettings();
}
public WifiChangeSettings[] newArray(int size) {
@@ -998,20 +965,10 @@
int unchangedSampleSize, /* samples to confirm no change */
int minApsBreachingThreshold, /* change threshold to trigger event */
int periodInMs, /* period of scan */
- BssidInfo[] bssidInfos /* signal thresholds to crosss */
+ BssidInfo[] bssidInfos /* signal thresholds to cross */
)
{
- validateChannel();
-
- WifiChangeSettings settings = new WifiChangeSettings();
- settings.rssiSampleSize = rssiSampleSize;
- settings.lostApSampleSize = lostApSampleSize;
- settings.unchangedSampleSize = unchangedSampleSize;
- settings.minApsBreachingThreshold = minApsBreachingThreshold;
- settings.periodInMs = periodInMs;
- settings.bssidInfos = bssidInfos;
-
- configureWifiChange(settings);
+ throw new UnsupportedOperationException();
}
/**
@@ -1034,11 +991,7 @@
* provided on {@link #stopTrackingWifiChange}
*/
public void startTrackingWifiChange(WifiChangeListener listener) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
- int key = addListener(listener);
- if (key == INVALID_KEY) return;
- validateChannel();
- mAsyncChannel.sendMessage(CMD_START_TRACKING_CHANGE, 0, key);
+ throw new UnsupportedOperationException();
}
/**
@@ -1047,17 +1000,13 @@
* #stopTrackingWifiChange}
*/
public void stopTrackingWifiChange(WifiChangeListener listener) {
- int key = removeListener(listener);
- if (key == INVALID_KEY) return;
- validateChannel();
- mAsyncChannel.sendMessage(CMD_STOP_TRACKING_CHANGE, 0, key);
+ throw new UnsupportedOperationException();
}
/** @hide */
@SystemApi
public void configureWifiChange(WifiChangeSettings settings) {
- validateChannel();
- mAsyncChannel.sendMessage(CMD_CONFIGURE_WIFI_CHANGE, 0, 0, settings);
+ throw new UnsupportedOperationException();
}
/** interface to receive hotlist events on; use this on {@link #setHotlist} */
@@ -1085,20 +1034,6 @@
/** Implement the Parcelable interface {@hide} */
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(apLostThreshold);
-
- if (bssidInfos != null) {
- dest.writeInt(bssidInfos.length);
- for (int i = 0; i < bssidInfos.length; i++) {
- BssidInfo info = bssidInfos[i];
- dest.writeString(info.bssid);
- dest.writeInt(info.low);
- dest.writeInt(info.high);
- dest.writeInt(info.frequencyHint);
- }
- } else {
- dest.writeInt(0);
- }
}
/** Implement the Parcelable interface {@hide} */
@@ -1106,17 +1041,6 @@
new Creator<HotlistSettings>() {
public HotlistSettings createFromParcel(Parcel in) {
HotlistSettings settings = new HotlistSettings();
- settings.apLostThreshold = in.readInt();
- int n = in.readInt();
- settings.bssidInfos = new BssidInfo[n];
- for (int i = 0; i < n; i++) {
- BssidInfo info = new BssidInfo();
- info.bssid = in.readString();
- info.low = in.readInt();
- info.high = in.readInt();
- info.frequencyHint = in.readInt();
- settings.bssidInfos[i] = info;
- }
return settings;
}
@@ -1135,14 +1059,7 @@
*/
public void startTrackingBssids(BssidInfo[] bssidInfos,
int apLostThreshold, BssidListener listener) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
- int key = addListener(listener);
- if (key == INVALID_KEY) return;
- validateChannel();
- HotlistSettings settings = new HotlistSettings();
- settings.bssidInfos = bssidInfos;
- settings.apLostThreshold = apLostThreshold;
- mAsyncChannel.sendMessage(CMD_SET_HOTLIST, 0, key, settings);
+ throw new UnsupportedOperationException();
}
/**
@@ -1150,11 +1067,7 @@
* @param listener same object provided in {@link #startTrackingBssids}
*/
public void stopTrackingBssids(BssidListener listener) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
- int key = removeListener(listener);
- if (key == INVALID_KEY) return;
- validateChannel();
- mAsyncChannel.sendMessage(CMD_RESET_HOTLIST, 0, key);
+ throw new UnsupportedOperationException();
}
@@ -1177,20 +1090,10 @@
/** @hide */
public static final int CMD_SCAN_RESULT = BASE + 5;
/** @hide */
- public static final int CMD_SET_HOTLIST = BASE + 6;
- /** @hide */
- public static final int CMD_RESET_HOTLIST = BASE + 7;
- /** @hide */
public static final int CMD_AP_FOUND = BASE + 9;
/** @hide */
public static final int CMD_AP_LOST = BASE + 10;
/** @hide */
- public static final int CMD_START_TRACKING_CHANGE = BASE + 11;
- /** @hide */
- public static final int CMD_STOP_TRACKING_CHANGE = BASE + 12;
- /** @hide */
- public static final int CMD_CONFIGURE_WIFI_CHANGE = BASE + 13;
- /** @hide */
public static final int CMD_WIFI_CHANGE_DETECTED = BASE + 15;
/** @hide */
public static final int CMD_WIFI_CHANGES_STABILIZED = BASE + 16;
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
index 9645b1d..334205b 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -85,7 +85,7 @@
/**
* Called when a discovery session (publish or subscribe) terminates. Termination may be due
* to user-request (either directly through {@link DiscoverySession#destroy()} or
- * application-specified expiration, e.g. {@link PublishConfig.Builder#setPublishCount(int)}
+ * application-specified expiration, e.g. {@link PublishConfig.Builder#setTtlSec(int)}
* or {@link SubscribeConfig.Builder#setTtlSec(int)}).
*/
public void onSessionTerminated() {
diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java
index a996844..1ce12f3 100644
--- a/wifi/java/android/net/wifi/aware/PublishConfig.java
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.java
@@ -75,9 +75,6 @@
public final int mPublishType;
/** @hide */
- public final int mPublishCount;
-
- /** @hide */
public final int mTtlSec;
/** @hide */
@@ -85,12 +82,11 @@
/** @hide */
public PublishConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
- int publishType, int publichCount, int ttlSec, boolean enableTerminateNotification) {
+ int publishType, int ttlSec, boolean enableTerminateNotification) {
mServiceName = serviceName;
mServiceSpecificInfo = serviceSpecificInfo;
mMatchFilter = matchFilter;
mPublishType = publishType;
- mPublishCount = publichCount;
mTtlSec = ttlSec;
mEnableTerminateNotification = enableTerminateNotification;
}
@@ -100,8 +96,8 @@
return "PublishConfig [mServiceName='" + mServiceName + ", mServiceSpecificInfo='" + (
(mServiceSpecificInfo == null) ? "null" : HexEncoding.encode(mServiceSpecificInfo))
+ ", mMatchFilter=" + (new TlvBufferUtils.TlvIterable(0, 1,
- mMatchFilter)).toString() + ", mPublishType=" + mPublishType + ", mPublishCount="
- + mPublishCount + ", mTtlSec=" + mTtlSec + ", mEnableTerminateNotification="
+ mMatchFilter)).toString() + ", mPublishType=" + mPublishType
+ + ", mTtlSec=" + mTtlSec + ", mEnableTerminateNotification="
+ mEnableTerminateNotification + "]";
}
@@ -116,7 +112,6 @@
dest.writeByteArray(mServiceSpecificInfo);
dest.writeByteArray(mMatchFilter);
dest.writeInt(mPublishType);
- dest.writeInt(mPublishCount);
dest.writeInt(mTtlSec);
dest.writeInt(mEnableTerminateNotification ? 1 : 0);
}
@@ -133,11 +128,10 @@
byte[] ssi = in.createByteArray();
byte[] matchFilter = in.createByteArray();
int publishType = in.readInt();
- int publishCount = in.readInt();
int ttlSec = in.readInt();
boolean enableTerminateNotification = in.readInt() != 0;
- return new PublishConfig(serviceName, ssi, matchFilter, publishType, publishCount,
+ return new PublishConfig(serviceName, ssi, matchFilter, publishType,
ttlSec, enableTerminateNotification);
}
};
@@ -156,7 +150,7 @@
return Arrays.equals(mServiceName, lhs.mServiceName) && Arrays.equals(mServiceSpecificInfo,
lhs.mServiceSpecificInfo) && Arrays.equals(mMatchFilter, lhs.mMatchFilter)
- && mPublishType == lhs.mPublishType && mPublishCount == lhs.mPublishCount
+ && mPublishType == lhs.mPublishType
&& mTtlSec == lhs.mTtlSec
&& mEnableTerminateNotification == lhs.mEnableTerminateNotification;
}
@@ -169,7 +163,6 @@
result = 31 * result + Arrays.hashCode(mServiceSpecificInfo);
result = 31 * result + Arrays.hashCode(mMatchFilter);
result = 31 * result + mPublishType;
- result = 31 * result + mPublishCount;
result = 31 * result + mTtlSec;
result = 31 * result + (mEnableTerminateNotification ? 1 : 0);
@@ -193,9 +186,6 @@
if (mPublishType < PUBLISH_TYPE_UNSOLICITED || mPublishType > PUBLISH_TYPE_SOLICITED) {
throw new IllegalArgumentException("Invalid publishType - " + mPublishType);
}
- if (mPublishCount < 0) {
- throw new IllegalArgumentException("Invalid publishCount - must be non-negative");
- }
if (mTtlSec < 0) {
throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
}
@@ -229,7 +219,6 @@
private byte[] mServiceSpecificInfo;
private byte[] mMatchFilter;
private int mPublishType = PUBLISH_TYPE_UNSOLICITED;
- private int mPublishCount = 0;
private int mTtlSec = 0;
private boolean mEnableTerminateNotification = true;
@@ -317,30 +306,6 @@
}
/**
- * Sets the number of times an unsolicited (configured using
- * {@link PublishConfig.Builder#setPublishType(int)}) publish session
- * will be broadcast. When the count is reached an event will be
- * generated for {@link DiscoverySessionCallback#onSessionTerminated()}
- * [unless {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
- * <p>
- * Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link DiscoverySession#destroy()} is
- * called.
- *
- * @param publishCount Number of publish packets to broadcast.
- *
- * @return The builder to facilitate chaining
- * {@code builder.setXXX(..).setXXX(..)}.
- */
- public Builder setPublishCount(int publishCount) {
- if (publishCount < 0) {
- throw new IllegalArgumentException("Invalid publishCount - must be non-negative");
- }
- mPublishCount = publishCount;
- return this;
- }
-
- /**
* Sets the time interval (in seconds) an unsolicited (
* {@link PublishConfig.Builder#setPublishType(int)}) publish session
* will be alive - broadcasting a packet. When the TTL is reached
@@ -387,7 +352,7 @@
*/
public PublishConfig build() {
return new PublishConfig(mServiceName, mServiceSpecificInfo, mMatchFilter, mPublishType,
- mPublishCount, mTtlSec, mEnableTerminateNotification);
+ mTtlSec, mEnableTerminateNotification);
}
}
}
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index 3397c4b..97a6a3f 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -94,9 +94,6 @@
public final int mSubscribeType;
/** @hide */
- public final int mSubscribeCount;
-
- /** @hide */
public final int mTtlSec;
/** @hide */
@@ -107,13 +104,12 @@
/** @hide */
public SubscribeConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
- int subscribeType, int publichCount, int ttlSec, int matchStyle,
+ int subscribeType, int ttlSec, int matchStyle,
boolean enableTerminateNotification) {
mServiceName = serviceName;
mServiceSpecificInfo = serviceSpecificInfo;
mMatchFilter = matchFilter;
mSubscribeType = subscribeType;
- mSubscribeCount = publichCount;
mTtlSec = ttlSec;
mMatchStyle = matchStyle;
mEnableTerminateNotification = enableTerminateNotification;
@@ -125,7 +121,7 @@
(mServiceSpecificInfo == null) ? "null" : HexEncoding.encode(mServiceSpecificInfo))
+ ", mMatchFilter=" + (new TlvBufferUtils.TlvIterable(0, 1,
mMatchFilter)).toString() + ", mSubscribeType=" + mSubscribeType
- + ", mSubscribeCount=" + mSubscribeCount + ", mTtlSec=" + mTtlSec + ", mMatchType="
+ + ", mTtlSec=" + mTtlSec + ", mMatchType="
+ mMatchStyle + ", mEnableTerminateNotification=" + mEnableTerminateNotification
+ "]";
}
@@ -141,7 +137,6 @@
dest.writeByteArray(mServiceSpecificInfo);
dest.writeByteArray(mMatchFilter);
dest.writeInt(mSubscribeType);
- dest.writeInt(mSubscribeCount);
dest.writeInt(mTtlSec);
dest.writeInt(mMatchStyle);
dest.writeInt(mEnableTerminateNotification ? 1 : 0);
@@ -159,12 +154,11 @@
byte[] ssi = in.createByteArray();
byte[] matchFilter = in.createByteArray();
int subscribeType = in.readInt();
- int subscribeCount = in.readInt();
int ttlSec = in.readInt();
int matchStyle = in.readInt();
boolean enableTerminateNotification = in.readInt() != 0;
- return new SubscribeConfig(serviceName, ssi, matchFilter, subscribeType, subscribeCount,
+ return new SubscribeConfig(serviceName, ssi, matchFilter, subscribeType,
ttlSec, matchStyle, enableTerminateNotification);
}
};
@@ -183,7 +177,7 @@
return Arrays.equals(mServiceName, lhs.mServiceName) && Arrays.equals(mServiceSpecificInfo,
lhs.mServiceSpecificInfo) && Arrays.equals(mMatchFilter, lhs.mMatchFilter)
- && mSubscribeType == lhs.mSubscribeType && mSubscribeCount == lhs.mSubscribeCount
+ && mSubscribeType == lhs.mSubscribeType
&& mTtlSec == lhs.mTtlSec && mMatchStyle == lhs.mMatchStyle
&& mEnableTerminateNotification == lhs.mEnableTerminateNotification;
}
@@ -196,7 +190,6 @@
result = 31 * result + Arrays.hashCode(mServiceSpecificInfo);
result = 31 * result + Arrays.hashCode(mMatchFilter);
result = 31 * result + mSubscribeType;
- result = 31 * result + mSubscribeCount;
result = 31 * result + mTtlSec;
result = 31 * result + mMatchStyle;
result = 31 * result + (mEnableTerminateNotification ? 1 : 0);
@@ -221,9 +214,6 @@
if (mSubscribeType < SUBSCRIBE_TYPE_PASSIVE || mSubscribeType > SUBSCRIBE_TYPE_ACTIVE) {
throw new IllegalArgumentException("Invalid subscribeType - " + mSubscribeType);
}
- if (mSubscribeCount < 0) {
- throw new IllegalArgumentException("Invalid subscribeCount - must be non-negative");
- }
if (mTtlSec < 0) {
throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
}
@@ -261,7 +251,6 @@
private byte[] mServiceSpecificInfo;
private byte[] mMatchFilter;
private int mSubscribeType = SUBSCRIBE_TYPE_PASSIVE;
- private int mSubscribeCount = 0;
private int mTtlSec = 0;
private int mMatchStyle = MATCH_STYLE_ALL;
private boolean mEnableTerminateNotification = true;
@@ -350,29 +339,6 @@
}
/**
- * Sets the number of times an active (
- * {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session
- * will broadcast. When the count is reached an event will be
- * generated for {@link DiscoverySessionCallback#onSessionTerminated()}.
- * <p>
- * Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link DiscoverySession#destroy()} is
- * called.
- *
- * @param subscribeCount Number of subscribe packets to broadcast.
- *
- * @return The builder to facilitate chaining
- * {@code builder.setXXX(..).setXXX(..)}.
- */
- public Builder setSubscribeCount(int subscribeCount) {
- if (subscribeCount < 0) {
- throw new IllegalArgumentException("Invalid subscribeCount - must be non-negative");
- }
- mSubscribeCount = subscribeCount;
- return this;
- }
-
- /**
* Sets the time interval (in seconds) an active (
* {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session
* will be alive - i.e. broadcasting a packet. When the TTL is reached
@@ -440,7 +406,7 @@
*/
public SubscribeConfig build() {
return new SubscribeConfig(mServiceName, mServiceSpecificInfo, mMatchFilter,
- mSubscribeType, mSubscribeCount, mTtlSec, mMatchStyle,
+ mSubscribeType, mTtlSec, mMatchStyle,
mEnableTerminateNotification);
}
}
diff --git a/wifi/java/android/net/wifi/hotspot2/ConfigParser.java b/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
index 027b049a..e8e8731 100644
--- a/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
@@ -111,6 +111,7 @@
*
* Content-Type: multipart/mixed; boundary={boundary}
* Content-Transfer-Encoding: base64
+ * [Skip uninterested headers]
*
* --{boundary}
* Content-Type: application/x-passpoint-profile
@@ -326,7 +327,8 @@
header.encodingType = entry.getValue();
break;
default:
- throw new IOException("Unexpected header: " + entry.getKey());
+ Log.d(TAG, "Ignore header: " + entry.getKey());
+ break;
}
}
return header;
@@ -344,21 +346,24 @@
* @throws IOException
*/
private static Pair<String, String> parseContentType(String contentType) throws IOException {
- String[] attributes = contentType.toString().split(";");
+ String[] attributes = contentType.split(";");
String type = null;
String boundary = null;
- if (attributes.length < 1 || attributes.length > 2) {
+ if (attributes.length < 1) {
throw new IOException("Invalid Content-Type: " + contentType);
}
+ // The type is always the first attribute.
type = attributes[0].trim();
- if (attributes.length == 2) {
- boundary = attributes[1].trim();
- if (!boundary.startsWith(BOUNDARY)) {
- throw new IOException("Invalid Content-Type: " + contentType);
+ // Look for boundary string from the rest of the attributes.
+ for (int i = 1; i < attributes.length; i++) {
+ String attribute = attributes[i].trim();
+ if (!attribute.startsWith(BOUNDARY)) {
+ Log.d(TAG, "Ignore Content-Type attribute: " + attributes[i]);
+ continue;
}
- boundary = boundary.substring(BOUNDARY.length());
+ boundary = attribute.substring(BOUNDARY.length());
// Remove the leading and trailing quote if present.
if (boundary.length() > 1 && boundary.startsWith("\"") && boundary.endsWith("\"")) {
boundary = boundary.substring(1, boundary.length()-1);
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 1f661c4..333a4f7d 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -28,6 +28,7 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@@ -329,10 +330,55 @@
mUsageLimitStartTimeInMs, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes);
}
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("UpdateIdentifier: ").append(mUpdateIdentifier).append("\n");
+ builder.append("CredentialPriority: ").append(mCredentialPriority).append("\n");
+ builder.append("SubscriptionCreationTime: ").append(
+ mSubscriptionCreationTimeInMs != Long.MIN_VALUE
+ ? new Date(mSubscriptionCreationTimeInMs) : "Not specified").append("\n");
+ builder.append("SubscriptionExpirationTime: ").append(
+ mSubscriptionExpirationTimeInMs != Long.MIN_VALUE
+ ? new Date(mSubscriptionExpirationTimeInMs) : "Not specified").append("\n");
+ builder.append("UsageLimitStartTime: ").append(mUsageLimitStartTimeInMs != Long.MIN_VALUE
+ ? new Date(mUsageLimitStartTimeInMs) : "Not specified").append("\n");
+ builder.append("UsageTimePeriod: ").append(mUsageLimitUsageTimePeriodInMinutes)
+ .append("\n");
+ builder.append("UsageLimitDataLimit: ").append(mUsageLimitDataLimit).append("\n");
+ builder.append("UsageLimitTimeLimit: ").append(mUsageLimitTimeLimitInMinutes).append("\n");
+ if (mHomeSp != null) {
+ builder.append("HomeSP Begin ---\n");
+ builder.append(mHomeSp);
+ builder.append("HomeSP End ---\n");
+ }
+ if (mCredential != null) {
+ builder.append("Credential Begin ---\n");
+ builder.append(mCredential);
+ builder.append("Credential End ---\n");
+ }
+ if (mPolicy != null) {
+ builder.append("Policy Begin ---\n");
+ builder.append(mPolicy);
+ builder.append("Policy End ---\n");
+ }
+ if (mSubscriptionUpdate != null) {
+ builder.append("SubscriptionUpdate Begin ---\n");
+ builder.append(mSubscriptionUpdate);
+ builder.append("SubscriptionUpdate End ---\n");
+ }
+ if (mTrustRootCertList != null) {
+ builder.append("TrustRootCertServers: ").append(mTrustRootCertList.keySet())
+ .append("\n");
+ }
+ return builder.toString();
+ }
+
/**
* Validate the configuration data.
*
* @return true on success or false on failure
+ * @hide
*/
public boolean validate() {
if (mHomeSp == null || !mHomeSp.validate()) {
diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
index 2ffe428..5dc5d13 100644
--- a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
@@ -144,6 +144,8 @@
private static final String NODE_TIME_LIMIT = "TimeLimit";
private static final String NODE_USAGE_TIME_PERIOD = "UsageTimePeriod";
private static final String NODE_CREDENTIAL_PRIORITY = "CredentialPriority";
+ private static final String NODE_EXTENSION = "Extension";
+
/**
* Fields under HomeSP subtree.
*/
@@ -629,6 +631,10 @@
case NODE_CREDENTIAL_PRIORITY:
config.setCredentialPriority(parseInteger(getPpsNodeValue(child)));
break;
+ case NODE_EXTENSION:
+ // All vendor specific information will be under this node.
+ Log.d(TAG, "Ignore Extension node for vendor specific information");
+ break;
default:
throw new ParsingException("Unknown node: " + child.getName());
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 2388841..67fa1bb 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -30,6 +30,7 @@
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
+import java.util.Date;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@@ -282,10 +283,23 @@
mAbleToShare, mEapType, mNonEapInnerMethod);
}
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Username: ").append(mUsername).append("\n");
+ builder.append("MachineManaged: ").append(mMachineManaged).append("\n");
+ builder.append("SoftTokenApp: ").append(mSoftTokenApp).append("\n");
+ builder.append("AbleToShare: ").append(mAbleToShare).append("\n");
+ builder.append("EAPType: ").append(mEapType).append("\n");
+ builder.append("AuthMethod: ").append(mNonEapInnerMethod).append("\n");
+ return builder.toString();
+ }
+
/**
* Validate the configuration data.
*
* @return true on success or false on failure
+ * @hide
*/
public boolean validate() {
if (TextUtils.isEmpty(mUsername)) {
@@ -439,10 +453,16 @@
return Objects.hash(mCertType, mCertSha256Fingerprint);
}
+ @Override
+ public String toString() {
+ return "CertificateType: " + mCertType + "\n";
+ }
+
/**
* Validate the configuration data.
*
* @return true on success or false on failure
+ * @hide
*/
public boolean validate() {
if (!TextUtils.equals(CERT_TYPE_X509V3, mCertType)) {
@@ -560,6 +580,14 @@
}
@Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("IMSI: ").append(mImsi).append("\n");
+ builder.append("EAPType: ").append(mEapType).append("\n");
+ return builder.toString();
+ }
+
+ @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mImsi);
dest.writeInt(mEapType);
@@ -569,6 +597,7 @@
* Validate the configuration data.
*
* @return true on success or false on failure
+ * @hide
*/
public boolean validate() {
// Note: this only validate the format of IMSI string itself. Additional verification
@@ -764,10 +793,38 @@
mCaCertificate, mClientCertificateChain, mClientPrivateKey);
}
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Realm: ").append(mRealm).append("\n");
+ builder.append("CreationTime: ").append(mCreationTimeInMs != Long.MIN_VALUE
+ ? new Date(mCreationTimeInMs) : "Not specified").append("\n");
+ builder.append("ExpirationTime: ").append(mExpirationTimeInMs != Long.MIN_VALUE
+ ? new Date(mExpirationTimeInMs) : "Not specified").append("\n");
+ builder.append("CheckAAAServerStatus: ").append(mCheckAaaServerCertStatus).append("\n");
+ if (mUserCredential != null) {
+ builder.append("UserCredential Begin ---\n");
+ builder.append(mUserCredential);
+ builder.append("UserCredential End ---\n");
+ }
+ if (mCertCredential != null) {
+ builder.append("CertificateCredential Begin ---\n");
+ builder.append(mCertCredential);
+ builder.append("CertificateCredential End ---\n");
+ }
+ if (mSimCredential != null) {
+ builder.append("SIMCredential Begin ---\n");
+ builder.append(mSimCredential);
+ builder.append("SIMCredential End ---\n");
+ }
+ return builder.toString();
+ }
+
/**
* Validate the configuration data.
*
* @return true on success or false on failure
+ * @hide
*/
public boolean validate() {
if (TextUtils.isEmpty(mRealm)) {
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 8ec40c0..9192ab0 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -241,10 +241,25 @@
mMatchAnyOis, mOtherHomePartners, mRoamingConsortiumOis);
}
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("FQDN: ").append(mFqdn).append("\n");
+ builder.append("FriendlyName: ").append(mFriendlyName).append("\n");
+ builder.append("IconURL: ").append(mIconUrl).append("\n");
+ builder.append("HomeNetworkIDs: ").append(mHomeNetworkIds).append("\n");
+ builder.append("MatchAllOIs: ").append(mMatchAllOis).append("\n");
+ builder.append("MatchAnyOIs: ").append(mMatchAnyOis).append("\n");
+ builder.append("OtherHomePartners: ").append(mOtherHomePartners).append("\n");
+ builder.append("RoamingConsortiumOIs: ").append(mRoamingConsortiumOis).append("\n");
+ return builder.toString();
+ }
+
/**
* Validate HomeSp data.
*
* @return true on success or false on failure
+ * @hide
*/
public boolean validate() {
if (TextUtils.isEmpty(mFqdn)) {
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index 63238e8..1df70f8 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -249,10 +249,21 @@
return Objects.hash(mFqdn, mFqdnExactMatch, mPriority, mCountries);
}
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("FQDN: ").append(mFqdn).append("\n");
+ builder.append("ExactMatch: ").append("mFqdnExactMatch").append("\n");
+ builder.append("Priority: ").append(mPriority).append("\n");
+ builder.append("Countries: ").append(mCountries).append("\n");
+ return builder.toString();
+ }
+
/**
* Validate RoamingParnter data.
*
* @return true on success
+ * @hide
*/
public boolean validate() {
if (TextUtils.isEmpty(mFqdn)) {
@@ -389,10 +400,34 @@
mPolicyUpdate);
}
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("MinHomeDownlinkBandwidth: ").append(mMinHomeDownlinkBandwidth)
+ .append("\n");
+ builder.append("MinHomeUplinkBandwidth: ").append(mMinHomeUplinkBandwidth).append("\n");
+ builder.append("MinRoamingDownlinkBandwidth: ").append(mMinRoamingDownlinkBandwidth)
+ .append("\n");
+ builder.append("MinRoamingUplinkBandwidth: ").append(mMinRoamingUplinkBandwidth)
+ .append("\n");
+ builder.append("ExcludedSSIDList: ").append(mExcludedSsidList).append("\n");
+ builder.append("RequiredProtoPortMap: ").append(mRequiredProtoPortMap).append("\n");
+ builder.append("MaximumBSSLoadValue: ").append(mMaximumBssLoadValue).append("\n");
+ builder.append("PreferredRoamingPartnerList: ").append(mPreferredRoamingPartnerList)
+ .append("\n");
+ if (mPolicyUpdate != null) {
+ builder.append("PolicyUpdate Begin ---\n");
+ builder.append(mPolicyUpdate);
+ builder.append("PolicyUpdate End ---\n");
+ }
+ return builder.toString();
+ }
+
/**
* Validate Policy data.
*
* @return true on success
+ * @hide
*/
public boolean validate() {
if (mPolicyUpdate == null) {
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
index 70264b0e..a7adfeb 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
@@ -247,10 +247,23 @@
mTrustRootCertSha256Fingerprint);
}
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("UpdateInterval: ").append(mUpdateIntervalInMinutes).append("\n");
+ builder.append("UpdateMethod: ").append(mUpdateMethod).append("\n");
+ builder.append("Restriction: ").append(mRestriction).append("\n");
+ builder.append("ServerURI: ").append(mServerUri).append("\n");
+ builder.append("Username: ").append(mUsername).append("\n");
+ builder.append("TrustRootCertURL: ").append(mTrustRootCertUrl).append("\n");
+ return builder.toString();
+ }
+
/**
* Validate UpdateParameter data.
*
* @return true on success
+ * @hide
*/
public boolean validate() {
if (mUpdateIntervalInMinutes == Long.MIN_VALUE) {
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
index 995963d..56919c2 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
@@ -1,85 +1,86 @@
-Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
-dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
-cHBsaWNhdGlvbi94LXBhc3Nwb2ludC1wcm9maWxlCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6
-IGJhc2U2NAoKUEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29n
-SUR4V1pYSkVWRVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVo
-YldVK1VHVnlVSEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0Fn
-UEZKVVVISnZjR1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhi
-V1UrZFhKdU9uZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZ
-M0pwY0hScGIyNDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThM
-MUpVVUhKdmNHVnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSth
-VEF3TVR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRt
-RnRaVDVJYjIxbFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lD
-QWdJQ0FnUEU1dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
-QWdJQ0FnSUNBOFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklD
-QWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcx
-bFBrWlJSRTQ4TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1
-MWF6d3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdv
-Z0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2
-ClpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpo
-YkhWbFBnb2dJQ0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4
-VG05a1pUNEtJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVo
-YldVK0NpQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhi
-RzA4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHlj
-bVZrTG1OdmJUd3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9i
-MlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThM
-MDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2Iy
-UmxUbUZ0ClpUNVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
-eDFaVDVxWVcxbGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lD
-QWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BD
-OU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3
-dlZtRnNkV1UrCkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0
-S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldV
-K0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1G
-dFpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1Ur
-TWpFOEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0Fn
-SUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2
-WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0
-VmpJOEwxWmhiSFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThM
-MDV2WkdVK0NpQWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJ
-Q0FnSUNBZ1BFNXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhi
-V1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQ
-a05sY25ScFptbGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
-eDFaVDU0TlRBNWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lD
-QWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1q
-VTJSbWx1WjJWeWNISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
-KwpNV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpG
-bU1XWXhaakZtTVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNB
-OEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNB
-Z0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4
-VG05awpaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFs
-UGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0Fn
-SUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2
-WkdWT1lXMWxQa1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNk
-V1UrTWpROApMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZU
-bTlrWlQ0S0lDQWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQ
-QzlOWjIxMFZISmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94
-LXg1MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFD
-UlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtR
-VWxNYkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5U
-bFlLUWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpU
-azFxV1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5V
-VEJGZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMw
-TkJVVVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZY
-TldkVzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01T
-dHZSMWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJV
-RkRaV1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJo
-U1FqZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdK
-ck1IVjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtz
-M2FFUTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxh
-CmFYQllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVX
-TTJreGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZH
-U1hkWU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFF
-YlVGR1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJk
-MFJuCldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldV
-akJVUWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZ
-MDVCVVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZD
-amxIUlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNY
-ZEpWV00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1Ew
-OTBhWE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JX
-MVdUQW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVF
-MXVWR3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhw
-aFNFb3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpG
-S1VDdHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNS
-a1RrNTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmts
-RFFWUkZMUzB0TFMwSwotLXtib3VuZGFyeX0tLQo=
+TUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5
+PXtib3VuZGFyeX07IGNoYXJzZXQ9VVRGLTgKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFz
+ZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXBhc3Nwb2ludC1w
+cm9maWxlOyBjaGFyc2V0PVVURi04CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2NAoK
+UEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29nSUR4V1pYSkVW
+RVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVoYldVK1VHVnlV
+SEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0FnUEZKVVVISnZj
+R1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhiV1UrZFhKdU9u
+ZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZM0pwY0hScGIy
+NDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThMMUpVVUhKdmNH
+VnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSthVEF3TVR3dlRt
+OWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRtRnRaVDVJYjIx
+bFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1
+dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNB
+OFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklDQWdQQzlPYjJS
+bFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrWlJSRTQ4
+TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1MWF6d3ZWbUZz
+ZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0Fn
+SUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2ClpHVk9ZVzFs
+UGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpoYkhWbFBnb2dJ
+Q0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4VG05a1pUNEtJ
+Q0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVoYldVK0NpQWdJ
+Q0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhiRzA4CkwwNXZa
+R1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHljbVZrTG1OdmJU
+d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lD
+QWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThMMDV2WkdWT1lX
+MWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0ClpU
+NVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lXeDFaVDVxWVcx
+bGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05
+a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BDOU9iMlJsVG1G
+dFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3dlZtRnNkV1Ur
+CkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0Fn
+SUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0Fn
+SUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1GdFpUNUZRVkJV
+ZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1UrTWpFOEwxWmhi
+SFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxQ
+Z29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2WkR3dlRtOWta
+VTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0VmpJOEwxWmhi
+SFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0Np
+QWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BF
+NXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
+QWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQa05sY25ScFpt
+bGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lXeDFaVDU0TlRB
+NWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1
+dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1qVTJSbWx1WjJW
+eWNISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdVKwpNV1l4WmpG
+bU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZt
+TVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNBOEwwNXZaR1Ur
+Q2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0Fn
+UEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4VG05awpaVDRL
+SUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJ
+Q0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNBOEwwNXZa
+R1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2WkdWT1lXMWxQ
+a1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1UrTWpROApM
+MVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lD
+QWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQQzlOWjIxMFZI
+SmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXg1MDktY2Et
+Y2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFDUlVkSlRpQkRS
+VkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtRVWxNYkVaa2Qz
+cE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5UbFlLUWtGTlZF
+SXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpUazFxV1hkTlZF
+RTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5VVEJGZUUxSlNV
+Skpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMwTkJVVVZCQ25w
+dVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZYTldkVzFFWWxs
+SWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01TdHZSMWhhZGto
+M2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJVRkRaV1pXYW1v
+d2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJoU1FqZzFNVEpR
+UWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdKck1IVjVhM1Jr
+WW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtzM2FFUTRjRkIy
+WmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxhCmFYQllOREY0
+UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVXTTJreGRIRXdO
+R3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZHU1hkWU5IWnpP
+RUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFFYlVGR1NYZFlO
+SFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJkMFJuCldVUldV
+VkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldVakJVUWtGVmQw
+RjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZMDVCVVVWTVFs
+RkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZDamxIUlZBdmRX
+OW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNYZEpWV00zCmQy
+azNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1EwOTBhWE5rUW5F
+eWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JXMVdUQW94Y1VK
+S2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVFMXVWR3c0ZUVW
+WFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhwaFNFb3hkVlk0
+Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpGS1VDdHNlRllL
+YlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNSa1RrNTJRMWw2
+YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmtsRFFWUkZMUzB0
+TFMwSwotLXtib3VuZGFyeX0tLQo=
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
index 3ddd09f..a44b542 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
@@ -1,8 +1,9 @@
-Content-Type: multipart/mixed; boundary={boundary}
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary={boundary}; charset=UTF-8
Content-Transfer-Encoding: base64
--{boundary}
-Content-Type: application/x-passpoint-profile
+Content-Type: application/x-passpoint-profile; charset=UTF-8
Content-Transfer-Encoding: base64
PE1nbXRUcmVlIHhtbG5zPSJzeW5jbWw6ZG1kZGYxLjIiPgogIDxWZXJEVEQ+MS4yPC9WZXJEVEQ+
diff --git a/wifi/tests/assets/pps/PerProviderSubscription.xml b/wifi/tests/assets/pps/PerProviderSubscription.xml
index 7f2d95d..1fb8309 100644
--- a/wifi/tests/assets/pps/PerProviderSubscription.xml
+++ b/wifi/tests/assets/pps/PerProviderSubscription.xml
@@ -14,6 +14,13 @@
<Node>
<NodeName>i001</NodeName>
<Node>
+ <NodeName>Extension</NodeName>
+ <Node>
+ <NodeName>VendorSpecific</NodeName>
+ <Value>Test</Value>
+ </Node>
+ </Node>
+ <Node>
<NodeName>HomeSP</NodeName>
<Node>
<NodeName>FriendlyName</NodeName>
diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
index a829eb9..e542789 100644
--- a/wifi/tests/src/android/net/wifi/WifiScannerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
@@ -16,20 +16,12 @@
package android.net.wifi;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.validateMockitoUsage;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
-import android.net.wifi.WifiScanner.BssidInfo;
-import android.net.wifi.WifiScanner.BssidListener;
import android.os.Handler;
-import android.os.Message;
import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
@@ -37,11 +29,10 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+
/**
* Unit tests for {@link android.net.wifi.WifiScanner}.
*/
@@ -51,8 +42,6 @@
private Context mContext;
@Mock
private IWifiScanner mService;
- @Mock
- private BssidListener mBssidListener;
private WifiScanner mWifiScanner;
private TestLooper mLooper;
@@ -81,31 +70,4 @@
validateMockitoUsage();
}
- private void verifySetHotlistMessage(Handler handler) {
- ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
- verify(handler, atLeastOnce()).handleMessage(messageCaptor.capture());
- assertEquals("message.what is not CMD_SET_HOTLIST",
- WifiScanner.CMD_SET_HOTLIST,
- messageCaptor.getValue().what);
- }
-
- /**
- * Test duplicate listeners for bssid tracking.
- */
- @Test
- public void testStartTrackingBssidsDuplicateListeners() throws Exception {
- BssidInfo[] bssids = new BssidInfo[] {
- new BssidInfo()
- };
-
- // First start tracking succeeds.
- mWifiScanner.startTrackingBssids(bssids, -100, mBssidListener);
- mLooper.dispatchAll();
- verifySetHotlistMessage(mHandler);
-
- // Second start tracking should fail.
- mWifiScanner.startTrackingBssids(bssids, -100, mBssidListener);
- mLooper.dispatchAll();
- verify(mBssidListener).onFailure(eq(WifiScanner.REASON_DUPLICATE_REQEUST), anyString());
- }
}
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index eceb365..830db22 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -18,11 +18,10 @@
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -140,8 +139,8 @@
// (1) connect + success
mDut.attach(mockCallback, mMockLooperHandler);
- inOrder.verify(mockAwareService).connect(binder.capture(), anyString(),
- clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ inOrder.verify(mockAwareService).connect(binder.capture(), any(),
+ clientProxyCallback.capture(), isNull(), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -150,8 +149,7 @@
// (2) publish - should succeed
PublishConfig publishConfig = new PublishConfig.Builder().build();
session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
- inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
- any(IWifiAwareDiscoverySessionCallback.class));
+ inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), any());
// (3) disconnect
session.destroy();
@@ -163,8 +161,8 @@
// (5) connect
mDut.attach(mockCallback, mMockLooperHandler);
- inOrder.verify(mockAwareService).connect(binder.capture(), anyString(),
- any(IWifiAwareEventCallback.class), (ConfigRequest) isNull(), eq(false));
+ inOrder.verify(mockAwareService).connect(binder.capture(), any(), any(), isNull(),
+ eq(false));
verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
}
@@ -185,16 +183,16 @@
// (1) connect + failure
mDut.attach(mockCallback, mMockLooperHandler);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ isNull(), eq(false));
clientProxyCallback.getValue().onConnectFail(reason);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttachFailed();
// (2) connect + success
mDut.attach(mockCallback, mMockLooperHandler);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ isNull(), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -203,8 +201,7 @@
// (4) subscribe: should succeed
SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler);
- inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
- any(IWifiAwareDiscoverySessionCallback.class));
+ inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig), any());
verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
}
@@ -223,19 +220,19 @@
// (1) connect + success
mDut.attach(mockCallback, mMockLooperHandler);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ isNull(), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
- inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class));
+ inOrder.verify(mockCallback).onAttached(any());
// (2) connect + success
mDut.attach(mockCallback, mMockLooperHandler);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ isNull(), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId + 1);
mMockLooper.dispatchAll();
- inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class));
+ inOrder.verify(mockCallback).onAttached(any());
verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
}
@@ -278,8 +275,8 @@
// (0) connect + success
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), eq(configRequest), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ eq(configRequest), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -370,8 +367,8 @@
// (1) connect successfully
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), eq(configRequest), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ eq(configRequest), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -426,8 +423,8 @@
// (0) connect + success
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), eq(configRequest), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ eq(configRequest), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -507,8 +504,8 @@
// (1) connect successfully
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), eq(configRequest), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ eq(configRequest), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -691,7 +688,6 @@
collector.checkThat("mServiceName", subscribeConfig.mServiceName, equalTo(null));
collector.checkThat("mSubscribeType", subscribeConfig.mSubscribeType,
equalTo(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE));
- collector.checkThat("mSubscribeCount", subscribeConfig.mSubscribeCount, equalTo(0));
collector.checkThat("mTtlSec", subscribeConfig.mTtlSec, equalTo(0));
collector.checkThat("mMatchStyle", subscribeConfig.mMatchStyle,
equalTo(SubscribeConfig.MATCH_STYLE_ALL));
@@ -714,7 +710,7 @@
.setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(
new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList())
.setSubscribeType(subscribeType)
- .setSubscribeCount(subscribeCount).setTtlSec(subscribeTtl).setMatchStyle(matchStyle)
+ .setTtlSec(subscribeTtl).setMatchStyle(matchStyle)
.setTerminateNotificationEnabled(enableTerminateNotification).build();
collector.checkThat("mServiceName", serviceName.getBytes(),
@@ -724,8 +720,6 @@
collector.checkThat("mMatchFilter", matchFilter, equalTo(subscribeConfig.mMatchFilter));
collector.checkThat("mSubscribeType", subscribeType,
equalTo(subscribeConfig.mSubscribeType));
- collector.checkThat("mSubscribeCount", subscribeCount,
- equalTo(subscribeConfig.mSubscribeCount));
collector.checkThat("mTtlSec", subscribeTtl, equalTo(subscribeConfig.mTtlSec));
collector.checkThat("mMatchStyle", matchStyle, equalTo(subscribeConfig.mMatchStyle));
collector.checkThat("mEnableTerminateNotification", enableTerminateNotification,
@@ -747,7 +741,7 @@
.setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(
new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList())
.setSubscribeType(subscribeType)
- .setSubscribeCount(subscribeCount).setTtlSec(subscribeTtl).setMatchStyle(matchStyle)
+ .setTtlSec(subscribeTtl).setMatchStyle(matchStyle)
.setTerminateNotificationEnabled(enableTerminateNotification).build();
Parcel parcelW = Parcel.obtain();
@@ -769,11 +763,6 @@
}
@Test(expected = IllegalArgumentException.class)
- public void testSubscribeConfigBuilderNegativeCount() {
- new SubscribeConfig.Builder().setSubscribeCount(-1);
- }
-
- @Test(expected = IllegalArgumentException.class)
public void testSubscribeConfigBuilderNegativeTtl() {
new SubscribeConfig.Builder().setTtlSec(-100);
}
@@ -797,7 +786,6 @@
collector.checkThat("mServiceName", publishConfig.mServiceName, equalTo(null));
collector.checkThat("mPublishType", publishConfig.mPublishType,
equalTo(PublishConfig.PUBLISH_TYPE_UNSOLICITED));
- collector.checkThat("mPublishCount", publishConfig.mPublishCount, equalTo(0));
collector.checkThat("mTtlSec", publishConfig.mTtlSec, equalTo(0));
collector.checkThat("mEnableTerminateNotification",
publishConfig.mEnableTerminateNotification, equalTo(true));
@@ -817,7 +805,7 @@
.setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(
new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList())
.setPublishType(publishType)
- .setPublishCount(publishCount).setTtlSec(publishTtl)
+ .setTtlSec(publishTtl)
.setTerminateNotificationEnabled(enableTerminateNotification).build();
collector.checkThat("mServiceName", serviceName.getBytes(),
@@ -826,7 +814,6 @@
serviceSpecificInfo.getBytes(), equalTo(publishConfig.mServiceSpecificInfo));
collector.checkThat("mMatchFilter", matchFilter, equalTo(publishConfig.mMatchFilter));
collector.checkThat("mPublishType", publishType, equalTo(publishConfig.mPublishType));
- collector.checkThat("mPublishCount", publishCount, equalTo(publishConfig.mPublishCount));
collector.checkThat("mTtlSec", publishTtl, equalTo(publishConfig.mTtlSec));
collector.checkThat("mEnableTerminateNotification", enableTerminateNotification,
equalTo(publishConfig.mEnableTerminateNotification));
@@ -846,7 +833,7 @@
.setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(
new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList())
.setPublishType(publishType)
- .setPublishCount(publishCount).setTtlSec(publishTtl)
+ .setTtlSec(publishTtl)
.setTerminateNotificationEnabled(enableTerminateNotification).build();
Parcel parcelW = Parcel.obtain();
@@ -868,11 +855,6 @@
}
@Test(expected = IllegalArgumentException.class)
- public void testPublishConfigBuilderNegativeCount() {
- new PublishConfig.Builder().setPublishCount(-4);
- }
-
- @Test(expected = IllegalArgumentException.class)
public void testPublishConfigBuilderNegativeTtl() {
new PublishConfig.Builder().setTtlSec(-10);
}
@@ -899,8 +881,7 @@
final RttManager.RttResult rttResults = new RttManager.RttResult();
rttResults.distance = 10;
- when(mockAwareService.startRanging(anyInt(), anyInt(),
- any(RttManager.ParcelableRttParams.class))).thenReturn(rangingId);
+ when(mockAwareService.startRanging(anyInt(), anyInt(), any())).thenReturn(rangingId);
InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession, mockRttListener);
@@ -919,8 +900,8 @@
// (1) connect successfully
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), eq(configRequest), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ eq(configRequest), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -994,8 +975,8 @@
// (1) connect successfully
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), eq(configRequest), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ eq(configRequest), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
@@ -1085,8 +1066,8 @@
// (1) connect successfully
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
- inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
- clientProxyCallback.capture(), eq(configRequest), eq(false));
+ inOrder.verify(mockAwareService).connect(any(), any(), clientProxyCallback.capture(),
+ eq(configRequest), eq(false));
clientProxyCallback.getValue().onConnectSuccess(clientId);
mMockLooper.dispatchAll();
inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());