diff options
45 files changed, 1281 insertions, 301 deletions
diff --git a/api/current.txt b/api/current.txt index 3cc9cc8..616884e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -17836,16 +17836,19 @@ package android.net { public class ConnectivityManager { method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); + method public boolean bindProcessToNetwork(android.net.Network); method public android.net.NetworkInfo getActiveNetworkInfo(); method public android.net.NetworkInfo[] getAllNetworkInfo(); method public android.net.Network[] getAllNetworks(); method public deprecated boolean getBackgroundDataSetting(); + method public android.net.Network getBoundNetworkForProcess(); + method public android.net.ProxyInfo getDefaultProxy(); method public android.net.LinkProperties getLinkProperties(android.net.Network); method public android.net.NetworkCapabilities getNetworkCapabilities(android.net.Network); method public android.net.NetworkInfo getNetworkInfo(int); method public android.net.NetworkInfo getNetworkInfo(android.net.Network); method public deprecated int getNetworkPreference(); - method public static android.net.Network getProcessDefaultNetwork(); + method public static deprecated android.net.Network getProcessDefaultNetwork(); method public boolean isActiveNetworkMetered(); method public boolean isDefaultNetworkActive(); method public static boolean isNetworkTypeValid(int); @@ -17857,7 +17860,7 @@ package android.net { method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent); method public deprecated boolean requestRouteToHost(int, int); method public deprecated void setNetworkPreference(int); - method public static boolean setProcessDefaultNetwork(android.net.Network); + method public static deprecated boolean setProcessDefaultNetwork(android.net.Network); method public deprecated int startUsingNetworkFeature(int, java.lang.String); method public deprecated int stopUsingNetworkFeature(int, java.lang.String); method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback); @@ -18026,6 +18029,7 @@ package android.net { method public java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException; method public javax.net.SocketFactory getSocketFactory(); method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException; + method public java.net.URLConnection openConnection(java.net.URL, java.net.Proxy) throws java.io.IOException; method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.Network> CREATOR; } @@ -18135,7 +18139,7 @@ package android.net { method public static final deprecated int getDefaultPort(); method public static final deprecated java.lang.String getHost(android.content.Context); method public static final deprecated int getPort(android.content.Context); - field public static final java.lang.String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; + field public static final deprecated java.lang.String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; field public static final java.lang.String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; } diff --git a/api/system-current.txt b/api/system-current.txt index e1e0764..550c89b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -19287,16 +19287,19 @@ package android.net { public class ConnectivityManager { method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); + method public boolean bindProcessToNetwork(android.net.Network); method public android.net.NetworkInfo getActiveNetworkInfo(); method public android.net.NetworkInfo[] getAllNetworkInfo(); method public android.net.Network[] getAllNetworks(); method public deprecated boolean getBackgroundDataSetting(); + method public android.net.Network getBoundNetworkForProcess(); + method public android.net.ProxyInfo getDefaultProxy(); method public android.net.LinkProperties getLinkProperties(android.net.Network); method public android.net.NetworkCapabilities getNetworkCapabilities(android.net.Network); method public android.net.NetworkInfo getNetworkInfo(int); method public android.net.NetworkInfo getNetworkInfo(android.net.Network); method public deprecated int getNetworkPreference(); - method public static android.net.Network getProcessDefaultNetwork(); + method public static deprecated android.net.Network getProcessDefaultNetwork(); method public boolean isActiveNetworkMetered(); method public boolean isDefaultNetworkActive(); method public static boolean isNetworkTypeValid(int); @@ -19308,7 +19311,7 @@ package android.net { method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent); method public deprecated boolean requestRouteToHost(int, int); method public deprecated void setNetworkPreference(int); - method public static boolean setProcessDefaultNetwork(android.net.Network); + method public static deprecated boolean setProcessDefaultNetwork(android.net.Network); method public deprecated int startUsingNetworkFeature(int, java.lang.String); method public deprecated int stopUsingNetworkFeature(int, java.lang.String); method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback); @@ -19477,6 +19480,7 @@ package android.net { method public java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException; method public javax.net.SocketFactory getSocketFactory(); method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException; + method public java.net.URLConnection openConnection(java.net.URL, java.net.Proxy) throws java.io.IOException; method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.Network> CREATOR; } @@ -19611,7 +19615,7 @@ package android.net { method public static final deprecated int getDefaultPort(); method public static final deprecated java.lang.String getHost(android.content.Context); method public static final deprecated int getPort(android.content.Context); - field public static final java.lang.String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; + field public static final deprecated java.lang.String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; field public static final java.lang.String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; } @@ -20314,21 +20318,25 @@ package android.net.wifi { field public static final int RTT_BW_40_SUPPORT = 8; // 0x8 field public static final int RTT_BW_5_SUPPORT = 1; // 0x1 field public static final int RTT_BW_80_SUPPORT = 16; // 0x10 - field public static final int RTT_CHANNEL_WIDTH_10 = 6; // 0x6 - field public static final int RTT_CHANNEL_WIDTH_160 = 3; // 0x3 - field public static final int RTT_CHANNEL_WIDTH_20 = 0; // 0x0 - field public static final int RTT_CHANNEL_WIDTH_40 = 1; // 0x1 - field public static final int RTT_CHANNEL_WIDTH_5 = 5; // 0x5 - field public static final int RTT_CHANNEL_WIDTH_80 = 2; // 0x2 - field public static final int RTT_CHANNEL_WIDTH_80P80 = 4; // 0x4 + field public static final deprecated int RTT_CHANNEL_WIDTH_10 = 6; // 0x6 + field public static final deprecated int RTT_CHANNEL_WIDTH_160 = 3; // 0x3 + field public static final deprecated int RTT_CHANNEL_WIDTH_20 = 0; // 0x0 + field public static final deprecated int RTT_CHANNEL_WIDTH_40 = 1; // 0x1 + field public static final deprecated int RTT_CHANNEL_WIDTH_5 = 5; // 0x5 + field public static final deprecated int RTT_CHANNEL_WIDTH_80 = 2; // 0x2 + field public static final deprecated int RTT_CHANNEL_WIDTH_80P80 = 4; // 0x4 field public static final deprecated int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; // 0xffffffff + field public static final int RTT_PEER_NAN = 5; // 0x5 + field public static final int RTT_PEER_P2P_CLIENT = 4; // 0x4 + field public static final int RTT_PEER_P2P_GO = 3; // 0x3 field public static final int RTT_PEER_TYPE_AP = 1; // 0x1 field public static final int RTT_PEER_TYPE_STA = 2; // 0x2 - field public static final int RTT_PEER_TYPE_UNSPECIFIED = 0; // 0x0 + field public static final deprecated int RTT_PEER_TYPE_UNSPECIFIED = 0; // 0x0 field public static final int RTT_STATUS_ABORTED = 8; // 0x8 field public static final int RTT_STATUS_FAILURE = 1; // 0x1 field public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; // 0x6 field public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; // 0xc + field public static final int RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15; // 0xf field public static final int RTT_STATUS_FAIL_INVALID_TS = 9; // 0x9 field public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; // 0x4 field public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7; // 0x7 @@ -20337,11 +20345,13 @@ package android.net.wifi { field public static final int RTT_STATUS_FAIL_REJECTED = 3; // 0x3 field public static final int RTT_STATUS_FAIL_SCHEDULE = 11; // 0xb field public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5; // 0x5 + field public static final int RTT_STATUS_INVALID_REQ = 13; // 0xd + field public static final int RTT_STATUS_NO_WIFI = 14; // 0xe field public static final int RTT_STATUS_SUCCESS = 0; // 0x0 field public static final deprecated int RTT_TYPE_11_MC = 4; // 0x4 field public static final deprecated int RTT_TYPE_11_V = 2; // 0x2 field public static final int RTT_TYPE_ONE_SIDED = 1; // 0x1 - field public static final int RTT_TYPE_TWO_SIDED = 4; // 0x4 + field public static final int RTT_TYPE_TWO_SIDED = 2; // 0x2 field public static final deprecated int RTT_TYPE_UNSPECIFIED = 0; // 0x0 } @@ -20409,6 +20419,8 @@ package android.net.wifi { public static class RttManager.RttResult { ctor public RttManager.RttResult(); + field public android.net.wifi.RttManager.WifiInformationElement LCI; + field public android.net.wifi.RttManager.WifiInformationElement LCR; field public java.lang.String bssid; field public int burstDuration; field public int burstNumber; @@ -20421,6 +20433,7 @@ package android.net.wifi { field public int frameNumberPerBurstPeer; field public int measurementFrameNumber; field public int measurementType; + field public int negotiatedBurstNum; field public deprecated int requestType; field public int retryAfterDuration; field public int rssi; @@ -20440,10 +20453,10 @@ package android.net.wifi { field public deprecated int tx_rate; } - public class RttManager.wifiInformationElement { - ctor public RttManager.wifiInformationElement(); - field public java.lang.String data; - field public int id; + public static class RttManager.WifiInformationElement { + ctor public RttManager.WifiInformationElement(); + field public byte[] data; + field public byte id; } public class ScanResult implements android.os.Parcelable { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index ed05321..9ba3049 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -864,10 +864,10 @@ public final class ActivityThread { } public void setHttpProxy(String host, String port, String exclList, Uri pacFileUrl) { - final Network network = ConnectivityManager.getProcessDefaultNetwork(); + final ConnectivityManager cm = ConnectivityManager.from(getSystemContext()); + final Network network = cm.getBoundNetworkForProcess(); if (network != null) { - Proxy.setHttpProxySystemProperty( - ConnectivityManager.from(getSystemContext()).getDefaultProxy()); + Proxy.setHttpProxySystemProperty(cm.getDefaultProxy()); } else { Proxy.setHttpProxySystemProperty(host, port, exclList, pacFileUrl); } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index edb768d..2b3cf34 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -995,6 +995,24 @@ public final class BluetoothAdapter { } /** + * Return true if hardware has entries available for matching beacons + * + * @return true if there are hw entries available for matching beacons + * @hide + */ + public boolean isHardwareTrackingFiltersAvailable() { + if (getState() != STATE_ON) return false; + try { + synchronized(mManagerCallback) { + if(mService != null) return (mService.numOfHwTrackFiltersAvailable() != 0); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return false; + } + + /** * Return the record of {@link BluetoothActivityEnergyInfo} object that * has the activity and energy info. This can be used to ascertain what * the controller has been up to, since the last sample. diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index dabb1ce..299f4c8 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -98,6 +98,7 @@ interface IBluetooth boolean isActivityAndEnergyReportingSupported(); void getActivityEnergyInfoFromController(); BluetoothActivityEnergyInfo reportActivityInfo(); + int numOfHwTrackFiltersAvailable(); // for dumpsys support String dump(); diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index 93ea299..73a1907 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -128,6 +128,16 @@ public final class BluetoothLeScanner { ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); return; } + if (!isHardwareResourcesAvailableForScan(settings)) { + postCallbackError(callback, + ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES); + return; + } + if (!isSettingsAndFilterComboAllowed(settings, filters)) { + postCallbackError(callback, + ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); + return; + } BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, settings, callback, resultStorages); wrapper.startRegisteration(); @@ -394,4 +404,33 @@ public final class BluetoothLeScanner { } return false; } + + private boolean isSettingsAndFilterComboAllowed(ScanSettings settings, + List <ScanFilter> filterList) { + final int callbackType = settings.getCallbackType(); + // If onlost/onfound is requested, a non-empty filter is expected + if ((callbackType & ScanSettings.CALLBACK_TYPE_FIRST_MATCH + | ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) { + if (filterList == null) { + return false; + } + for (ScanFilter filter : filterList) { + if (filter.isAllFieldsEmpty()) { + return false; + } + } + } + return true; + } + + private boolean isHardwareResourcesAvailableForScan(ScanSettings settings) { + final int callbackType = settings.getCallbackType(); + if ((callbackType & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0 + || (callbackType & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) { + // For onlost/onfound, we required hw support be available + return (mBluetoothAdapter.isOffloadedFilteringSupported() && + mBluetoothAdapter.isHardwareTrackingFiltersAvailable()); + } + return true; + } } diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java index 05782a8..27b96bd 100644 --- a/core/java/android/bluetooth/le/ScanCallback.java +++ b/core/java/android/bluetooth/le/ScanCallback.java @@ -45,10 +45,16 @@ public abstract class ScanCallback { public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4; /** + * Fails to start scan as it is out of hardware resources. + * @hide + */ + public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5; + + /** * Callback when a BLE advertisement has been found. * - * @param callbackType Determines how this callback was triggered. Currently could only be - * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}. + * @param callbackType Determines how this callback was triggered. Could be of + * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES} * @param result A Bluetooth LE scan result. */ public void onScanResult(int callbackType, ScanResult result) { diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index 5025218..92a3817 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -67,6 +67,8 @@ public final class ScanFilter implements Parcelable { private final byte[] mManufacturerData; @Nullable private final byte[] mManufacturerDataMask; + private static final ScanFilter EMPTY = new ScanFilter.Builder().build() ; + private ScanFilter(String name, String deviceAddress, ParcelUuid uuid, ParcelUuid uuidMask, ParcelUuid serviceDataUuid, @@ -410,6 +412,14 @@ public final class ScanFilter implements Parcelable { } /** + * Checks if the scanfilter is empty + * @hide + */ + public boolean isAllFieldsEmpty() { + return EMPTY.equals(this); + } + + /** * Builder class for {@link ScanFilter}. */ public static final class Builder { diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 0106686..f103cae 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -59,7 +59,6 @@ public final class ScanSettings implements Parcelable { /** * A result callback is only triggered for the first advertisement packet received that matches * the filter criteria. - * * @hide */ @SystemApi @@ -68,15 +67,53 @@ public final class ScanSettings implements Parcelable { /** * Receive a callback when advertisements are no longer received from a device that has been * previously reported by a first match callback. - * * @hide */ @SystemApi public static final int CALLBACK_TYPE_MATCH_LOST = 4; + + /** + * Determines how many advertisements to match per filter, as this is scarce hw resource + */ + /** + * Match one advertisement per filter + * @hide + */ + public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; + + /** + * Match few advertisement per filter, depends on current capability and availibility of + * the resources in hw + * @hide + */ + public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; + + /** + * Match as many advertisement per filter as hw could allow, depends on current + * capability and availibility of the resources in hw + * @hide + */ + public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; + + + /** + * In Aggressive mode, hw will determine a match sooner even with feeble signal strength + * and few number of sightings/match in a duration. + * @hide + */ + public static final int MATCH_MODE_AGGRESSIVE = 1; + /** - * Request full scan results which contain the device, rssi, advertising data, scan response as - * well as the scan timestamp. + * For sticky mode, higher threshold of signal strength and sightings is required + * before reporting by hw + * @hide + */ + public static final int MATCH_MODE_STICKY = 2; + + /** + * Request full scan results which contain the device, rssi, advertising data, scan response + * as well as the scan timestamp. * * @hide */ @@ -106,6 +143,10 @@ public final class ScanSettings implements Parcelable { // Time of delay for reporting the scan result private long mReportDelayMillis; + private int mMatchMode; + + private int mNumOfMatchesPerFilter; + public int getScanMode() { return mScanMode; } @@ -119,6 +160,20 @@ public final class ScanSettings implements Parcelable { } /** + * @hide + */ + public int getMatchMode() { + return mMatchMode; + } + + /** + * @hide + */ + public int getNumOfMatches() { + return mNumOfMatchesPerFilter; + } + + /** * Returns report delay timestamp based on the device clock. */ public long getReportDelayMillis() { @@ -126,11 +181,13 @@ public final class ScanSettings implements Parcelable { } private ScanSettings(int scanMode, int callbackType, int scanResultType, - long reportDelayMillis) { + long reportDelayMillis, int matchMode, int numOfMatchesPerFilter) { mScanMode = scanMode; mCallbackType = callbackType; mScanResultType = scanResultType; mReportDelayMillis = reportDelayMillis; + mNumOfMatchesPerFilter = numOfMatchesPerFilter; + mMatchMode = numOfMatchesPerFilter; } private ScanSettings(Parcel in) { @@ -138,6 +195,8 @@ public final class ScanSettings implements Parcelable { mCallbackType = in.readInt(); mScanResultType = in.readInt(); mReportDelayMillis = in.readLong(); + mMatchMode = in.readInt(); + mNumOfMatchesPerFilter = in.readInt(); } @Override @@ -146,6 +205,8 @@ public final class ScanSettings implements Parcelable { dest.writeInt(mCallbackType); dest.writeInt(mScanResultType); dest.writeLong(mReportDelayMillis); + dest.writeInt(mMatchMode); + dest.writeInt(mNumOfMatchesPerFilter); } @Override @@ -174,7 +235,8 @@ public final class ScanSettings implements Parcelable { private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES; private int mScanResultType = SCAN_RESULT_TYPE_FULL; private long mReportDelayMillis = 0; - + private int mMatchMode = MATCH_MODE_AGGRESSIVE; + private int mNumOfMatchesPerFilter = MATCH_NUM_ONE_ADVERTISEMENT; /** * Set scan mode for Bluetooth LE scan. * @@ -255,11 +317,48 @@ public final class ScanSettings implements Parcelable { } /** + * Set the number of matches for Bluetooth LE scan filters hardware match + * + * @param numOfMatches The num of matches can be one of + * {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT} or + * {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or + * {@link ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT} + * @throws IllegalArgumentException If the {@code matchMode} is invalid. + * @hide + */ + public Builder setNumOfMatches(int numOfMatches) { + if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT + || numOfMatches > MATCH_NUM_MAX_ADVERTISEMENT) { + throw new IllegalArgumentException("invalid numOfMatches " + numOfMatches); + } + mNumOfMatchesPerFilter = numOfMatches; + return this; + } + + /** + * Set match mode for Bluetooth LE scan filters hardware match + * + * @param matchMode The match mode can be one of + * {@link ScanSettings#MATCH_MODE_AGGRESSIVE} or + * {@link ScanSettings#MATCH_MODE_STICKY} + * @throws IllegalArgumentException If the {@code matchMode} is invalid. + * @hide + */ + public Builder setMatchMode(int matchMode) { + if (matchMode < MATCH_MODE_AGGRESSIVE + || matchMode > MATCH_MODE_STICKY) { + throw new IllegalArgumentException("invalid matchMode " + matchMode); + } + mMatchMode = matchMode; + return this; + } + + /** * Build {@link ScanSettings}. */ public ScanSettings build() { return new ScanSettings(mScanMode, mCallbackType, mScanResultType, - mReportDelayMillis); + mReportDelayMillis, mMatchMode, mNumOfMatchesPerFilter); } } } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 3abccbc..da2c5e0 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -589,9 +589,9 @@ public class ConnectivityManager { * network. * * @return a {@link NetworkInfo} object for the current default network - * or {@code null} if no network default network is currently active + * or {@code null} if no default network is currently active * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. */ public NetworkInfo getActiveNetworkInfo() { @@ -738,9 +738,9 @@ public class ConnectivityManager { * network. * * @return a {@link NetworkInfo} object for the current default network - * or {@code null} if no network default network is currently active + * or {@code null} if no default network is currently active * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * {@hide} @@ -760,7 +760,7 @@ public class ConnectivityManager { * for the current default network, or {@code null} if there * is no current default network. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -780,7 +780,7 @@ public class ConnectivityManager { * for the given networkType, or {@code null} if there is * no current default network. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -830,7 +830,7 @@ public class ConnectivityManager { * @return a boolean, {@code true} indicating success. All network types * will be tried, even if some fail. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#CHANGE_NETWORK_STATE}. * {@hide} */ @@ -851,7 +851,7 @@ public class ConnectivityManager { * {@code} false to turn it off. * @return a boolean, {@code true} indicating success. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#CHANGE_NETWORK_STATE}. * {@hide} */ @@ -1202,7 +1202,7 @@ public class ConnectivityManager { * @return {@code true} on success, {@code false} on failure * * @deprecated Deprecated in favor of the {@link #requestNetwork}, - * {@link #setProcessDefaultNetwork} and {@link Network#getSocketFactory} api. + * {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} api. */ public boolean requestRouteToHost(int networkType, int hostAddress) { return requestRouteToHostAddress(networkType, NetworkUtils.intToInetAddress(hostAddress)); @@ -1220,7 +1220,7 @@ public class ConnectivityManager { * @return {@code true} on success, {@code false} on failure * @hide * @deprecated Deprecated in favor of the {@link #requestNetwork} and - * {@link #setProcessDefaultNetwork} api. + * {@link #bindProcessToNetwork} api. */ public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) { try { @@ -1273,7 +1273,7 @@ public class ConnectivityManager { * network is active. Quota status can change rapidly, so these values * shouldn't be cached. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @hide @@ -1345,7 +1345,7 @@ public class ConnectivityManager { * listener. * <p> * If the process default network has been set with - * {@link ConnectivityManager#setProcessDefaultNetwork} this function will not + * {@link ConnectivityManager#bindProcessToNetwork} this function will not * reflect the process's default, but the system default. * * @param l The listener to be told when the network is active. @@ -1430,11 +1430,20 @@ public class ConnectivityManager { * situations where a Context pointer is unavailable. * @hide */ - public static ConnectivityManager getInstance() { - if (sInstance == null) { + static ConnectivityManager getInstanceOrNull() { + return sInstance; + } + + /** + * @deprecated - use getSystemService. This is a kludge to support static access in certain + * situations where a Context pointer is unavailable. + * @hide + */ + private static ConnectivityManager getInstance() { + if (getInstanceOrNull() == null) { throw new IllegalStateException("No ConnectivityManager yet constructed"); } - return sInstance; + return getInstanceOrNull(); } /** @@ -1443,7 +1452,7 @@ public class ConnectivityManager { * * @return an array of 0 or more Strings of tetherable interface names. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -1460,7 +1469,7 @@ public class ConnectivityManager { * * @return an array of 0 or more String of currently tethered interface names. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -1483,7 +1492,7 @@ public class ConnectivityManager { * @return an array of 0 or more String indicating the interface names * which failed to tether. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -1521,7 +1530,7 @@ public class ConnectivityManager { * @param iface the interface name to tether. * @return error a {@code TETHER_ERROR} value indicating success or failure type * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#CHANGE_NETWORK_STATE}. * {@hide} */ @@ -1539,7 +1548,7 @@ public class ConnectivityManager { * @param iface the interface name to untether. * @return error a {@code TETHER_ERROR} value indicating success or failure type * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#CHANGE_NETWORK_STATE}. * {@hide} */ @@ -1558,7 +1567,7 @@ public class ConnectivityManager { * * @return a boolean - {@code true} indicating Tethering is supported. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -1578,7 +1587,7 @@ public class ConnectivityManager { * @return an array of 0 or more regular expression Strings defining * what interfaces are considered tetherable usb interfaces. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -1598,7 +1607,7 @@ public class ConnectivityManager { * @return an array of 0 or more regular expression Strings defining * what interfaces are considered tetherable wifi interfaces. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -1618,7 +1627,7 @@ public class ConnectivityManager { * @return an array of 0 or more regular expression Strings defining * what interfaces are considered tetherable bluetooth interfaces. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -1640,7 +1649,7 @@ public class ConnectivityManager { * @param enable a boolean - {@code true} to enable tethering * @return error a {@code TETHER_ERROR} value indicating success or failure type * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#CHANGE_NETWORK_STATE}. * {@hide} */ @@ -1683,7 +1692,7 @@ public class ConnectivityManager { * @return error The error code of the last error tethering or untethering the named * interface * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * {@hide} */ @@ -1702,7 +1711,7 @@ public class ConnectivityManager { * @param networkType The type of network you want to report on * @param percentage The quality of the connection 0 is bad, 100 is good * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#STATUS_BAR}. * {@hide} */ @@ -1738,7 +1747,7 @@ public class ConnectivityManager { * @param p The a {@link ProxyInfo} object defining the new global * HTTP proxy. A {@code null} value will clear the global HTTP proxy. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * android.Manifest.permission#CONNECTIVITY_INTERNAL. * @hide */ @@ -1755,7 +1764,7 @@ public class ConnectivityManager { * @return {@link ProxyInfo} for the current global HTTP proxy or {@code null} * if no global HTTP proxy is set. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * @hide */ @@ -1770,15 +1779,14 @@ public class ConnectivityManager { /** * Get the current default HTTP proxy settings. If a global proxy is set it will be returned, * otherwise if this process is bound to a {@link Network} using - * {@link #setProcessDefaultNetwork} then that {@code Network}'s proxy is returned, otherwise + * {@link #bindProcessToNetwork} then that {@code Network}'s proxy is returned, otherwise * the default network's proxy is returned. * * @return the {@link ProxyInfo} for the current HTTP proxy, or {@code null} if no * HTTP proxy is active. - * @hide */ public ProxyInfo getDefaultProxy() { - final Network network = getProcessDefaultNetwork(); + final Network network = getBoundNetworkForProcess(); if (network != null) { final ProxyInfo globalProxy = getGlobalProxy(); if (globalProxy != null) return globalProxy; @@ -1804,7 +1812,7 @@ public class ConnectivityManager { * @param networkType The network type we'd like to check * @return {@code true} if supported, else {@code false} * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * @hide */ @@ -1826,7 +1834,7 @@ public class ConnectivityManager { * @return {@code true} if large transfers should be avoided, otherwise * {@code false}. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. */ public boolean isActiveNetworkMetered() { @@ -1862,7 +1870,7 @@ public class ConnectivityManager { * in question. * @param isCaptivePortal true/false. * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}. * {@hide} */ @@ -1937,7 +1945,7 @@ public class ConnectivityManager { * * @param enable whether to enable airplane mode or not * - * <p>This method requires the call to hold the permission + * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}. * @hide */ @@ -2338,9 +2346,8 @@ public class ConnectivityManager { * successfully finding a network for the applications request. Retrieve it with * {@link android.content.Intent#getParcelableExtra(String)}. * <p> - * Note that if you intend to invoke {@link #setProcessDefaultNetwork} or - * {@link Network#openConnection(java.net.URL)} then you must get a - * ConnectivityManager instance before doing so. + * Note that if you intend to invoke {@link Network#openConnection(java.net.URL)} + * then you must get a ConnectivityManager instance before doing so. */ public static final String EXTRA_NETWORK = "android.net.extra.NETWORK"; @@ -2491,15 +2498,42 @@ public class ConnectivityManager { * Sockets created by Network.getSocketFactory().createSocket() and * performing network-specific host name resolutions via * {@link Network#getAllByName Network.getAllByName} is preferred to calling + * {@code bindProcessToNetwork}. + * + * @param network The {@link Network} to bind the current process to, or {@code null} to clear + * the current binding. + * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. + */ + public boolean bindProcessToNetwork(Network network) { + // Forcing callers to call thru non-static function ensures ConnectivityManager + // instantiated. + return setProcessDefaultNetwork(network); + } + + /** + * Binds the current process to {@code network}. All Sockets created in the future + * (and not explicitly bound via a bound SocketFactory from + * {@link Network#getSocketFactory() Network.getSocketFactory()}) will be bound to + * {@code network}. All host name resolutions will be limited to {@code network} as well. + * Note that if {@code network} ever disconnects, all Sockets created in this way will cease to + * work and all host name resolutions will fail. This is by design so an application doesn't + * accidentally use Sockets it thinks are still bound to a particular {@link Network}. + * To clear binding pass {@code null} for {@code network}. Using individually bound + * Sockets created by Network.getSocketFactory().createSocket() and + * performing network-specific host name resolutions via + * {@link Network#getAllByName Network.getAllByName} is preferred to calling * {@code setProcessDefaultNetwork}. * * @param network The {@link Network} to bind the current process to, or {@code null} to clear * the current binding. * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. + * @deprecated This function can throw {@link IllegalStateException}. Use + * {@link #bindProcessToNetwork} instead. {@code bindProcessToNetwork} + * is a direct replacement. */ public static boolean setProcessDefaultNetwork(Network network) { int netId = (network == null) ? NETID_UNSET : network.netId; - if (netId == NetworkUtils.getNetworkBoundToProcess()) { + if (netId == NetworkUtils.getBoundNetworkForProcess()) { return true; } if (NetworkUtils.bindProcessToNetwork(netId)) { @@ -2519,19 +2553,34 @@ public class ConnectivityManager { /** * Returns the {@link Network} currently bound to this process via - * {@link #setProcessDefaultNetwork}, or {@code null} if no {@link Network} is explicitly bound. + * {@link #bindProcessToNetwork}, or {@code null} if no {@link Network} is explicitly bound. + * + * @return {@code Network} to which this process is bound, or {@code null}. + */ + public Network getBoundNetworkForProcess() { + // Forcing callers to call thru non-static function ensures ConnectivityManager + // instantiated. + return getProcessDefaultNetwork(); + } + + /** + * Returns the {@link Network} currently bound to this process via + * {@link #bindProcessToNetwork}, or {@code null} if no {@link Network} is explicitly bound. * * @return {@code Network} to which this process is bound, or {@code null}. + * @deprecated Using this function can lead to other functions throwing + * {@link IllegalStateException}. Use {@link #getBoundNetworkForProcess} instead. + * {@code getBoundNetworkForProcess} is a direct replacement. */ public static Network getProcessDefaultNetwork() { - int netId = NetworkUtils.getNetworkBoundToProcess(); + int netId = NetworkUtils.getBoundNetworkForProcess(); if (netId == NETID_UNSET) return null; return new Network(netId); } /** * Binds host resolutions performed by this process to {@code network}. - * {@link #setProcessDefaultNetwork} takes precedence over this setting. + * {@link #bindProcessToNetwork} takes precedence over this setting. * * @param network The {@link Network} to bind host resolutions from the current process to, or * {@code null} to clear the current binding. diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java index 1b8adc8..73ef78e 100644 --- a/core/java/android/net/DhcpStateMachine.java +++ b/core/java/android/net/DhcpStateMachine.java @@ -37,7 +37,7 @@ import android.util.Log; * StateMachine that interacts with the native DHCP client and can talk to * a controller that also needs to be a StateMachine * - * The Dhcp state machine provides the following features: + * The DhcpStateMachine provides the following features: * - Wakeup and renewal using the native DHCP client (which will not renew * on its own when the device is in suspend state and this can lead to device * holding IP address beyond expiry) @@ -72,11 +72,6 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { //Used for sanity check on setting up renewal private static final int MIN_RENEWAL_TIME_SECS = 5 * 60; // 5 minutes - private enum DhcpAction { - START, - RENEW - }; - private final String mInterfaceName; private boolean mRegisteredForPreDhcpNotification = false; @@ -99,6 +94,9 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { * after pre DHCP action is complete */ public static final int CMD_PRE_DHCP_ACTION_COMPLETE = BASE + 7; + /* Command from ourselves to see if DHCP results are available */ + private static final int CMD_GET_DHCP_RESULTS = BASE + 8; + /* Message.arg1 arguments to CMD_POST_DHCP notification */ public static final int DHCP_SUCCESS = 1; public static final int DHCP_FAILURE = 2; @@ -108,6 +106,7 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { private State mWaitBeforeStartState = new WaitBeforeStartState(); private State mRunningState = new RunningState(); private State mWaitBeforeRenewalState = new WaitBeforeRenewalState(); + private State mPollingState = new PollingState(); private DhcpStateMachine(Context context, StateMachine controller, String intf) { super(TAG); @@ -139,6 +138,7 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { addState(mDefaultState); addState(mStoppedState, mDefaultState); addState(mWaitBeforeStartState, mDefaultState); + addState(mPollingState, mDefaultState); addState(mRunningState, mDefaultState); addState(mWaitBeforeRenewalState, mDefaultState); @@ -206,6 +206,10 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { @Override public void enter() { if (DBG) Log.d(TAG, getName() + "\n"); + if (!NetworkUtils.stopDhcp(mInterfaceName)) { + Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName); + } + mDhcpResults = null; } @Override @@ -219,7 +223,7 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { mController.sendMessage(CMD_PRE_DHCP_ACTION); transitionTo(mWaitBeforeStartState); } else { - if (runDhcp(DhcpAction.START)) { + if (runDhcpStart()) { transitionTo(mRunningState); } } @@ -247,10 +251,10 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch (message.what) { case CMD_PRE_DHCP_ACTION_COMPLETE: - if (runDhcp(DhcpAction.START)) { + if (runDhcpStart()) { transitionTo(mRunningState); } else { - transitionTo(mStoppedState); + transitionTo(mPollingState); } break; case CMD_STOP_DHCP: @@ -267,6 +271,55 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { } } + class PollingState extends State { + private static final long MAX_DELAY_SECONDS = 32; + private long delaySeconds; + + private void scheduleNextResultsCheck() { + sendMessageDelayed(obtainMessage(CMD_GET_DHCP_RESULTS), delaySeconds * 1000); + delaySeconds *= 2; + if (delaySeconds > MAX_DELAY_SECONDS) { + delaySeconds = MAX_DELAY_SECONDS; + } + } + + @Override + public void enter() { + if (DBG) Log.d(TAG, "Entering " + getName() + "\n"); + delaySeconds = 1; + scheduleNextResultsCheck(); + } + + @Override + public boolean processMessage(Message message) { + boolean retValue = HANDLED; + if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); + switch (message.what) { + case CMD_GET_DHCP_RESULTS: + if (DBG) Log.d(TAG, "GET_DHCP_RESULTS on " + mInterfaceName); + if (dhcpSucceeded()) { + transitionTo(mRunningState); + } else { + scheduleNextResultsCheck(); + } + break; + case CMD_STOP_DHCP: + transitionTo(mStoppedState); + break; + default: + retValue = NOT_HANDLED; + break; + } + return retValue; + } + + @Override + public void exit() { + if (DBG) Log.d(TAG, "Exiting " + getName() + "\n"); + removeMessages(CMD_GET_DHCP_RESULTS); + } + } + class RunningState extends State { @Override public void enter() { @@ -280,9 +333,6 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { switch (message.what) { case CMD_STOP_DHCP: mAlarmManager.cancel(mDhcpRenewalIntent); - if (!NetworkUtils.stopDhcp(mInterfaceName)) { - Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName); - } transitionTo(mStoppedState); break; case CMD_RENEW_DHCP: @@ -292,7 +342,7 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { transitionTo(mWaitBeforeRenewalState); //mDhcpRenewWakeLock is released in WaitBeforeRenewalState } else { - if (!runDhcp(DhcpAction.RENEW)) { + if (!runDhcpRenew()) { transitionTo(mStoppedState); } mDhcpRenewWakeLock.release(); @@ -321,13 +371,10 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { switch (message.what) { case CMD_STOP_DHCP: mAlarmManager.cancel(mDhcpRenewalIntent); - if (!NetworkUtils.stopDhcp(mInterfaceName)) { - Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName); - } transitionTo(mStoppedState); break; case CMD_PRE_DHCP_ACTION_COMPLETE: - if (runDhcp(DhcpAction.RENEW)) { + if (runDhcpRenew()) { transitionTo(mRunningState); } else { transitionTo(mStoppedState); @@ -348,52 +395,68 @@ public class DhcpStateMachine extends BaseDhcpStateMachine { } } - private boolean runDhcp(DhcpAction dhcpAction) { - boolean success = false; + private boolean dhcpSucceeded() { DhcpResults dhcpResults = new DhcpResults(); - - if (dhcpAction == DhcpAction.START) { - /* Stop any existing DHCP daemon before starting new */ - NetworkUtils.stopDhcp(mInterfaceName); - if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName); - success = NetworkUtils.runDhcp(mInterfaceName, dhcpResults); - } else if (dhcpAction == DhcpAction.RENEW) { - if (DBG) Log.d(TAG, "DHCP renewal on " + mInterfaceName); - success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpResults); - if (success) dhcpResults.updateFromDhcpRequest(mDhcpResults); + if (!NetworkUtils.getDhcpResults(mInterfaceName, dhcpResults)) { + return false; } - if (success) { - if (DBG) Log.d(TAG, "DHCP succeeded on " + mInterfaceName); - long leaseDuration = dhcpResults.leaseDuration; //int to long conversion - - //Sanity check for renewal - if (leaseDuration >= 0) { - //TODO: would be good to notify the user that his network configuration is - //bad and that the device cannot renew below MIN_RENEWAL_TIME_SECS - if (leaseDuration < MIN_RENEWAL_TIME_SECS) { - leaseDuration = MIN_RENEWAL_TIME_SECS; - } - //Do it a bit earlier than half the lease duration time - //to beat the native DHCP client and avoid extra packets - //48% for one hour lease time = 29 minutes - mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + - leaseDuration * 480, //in milliseconds - mDhcpRenewalIntent); - } else { - //infinite lease time, no renewal needed - } - mDhcpResults = dhcpResults; - mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpResults) - .sendToTarget(); + if (DBG) Log.d(TAG, "DHCP results found for " + mInterfaceName); + long leaseDuration = dhcpResults.leaseDuration; //int to long conversion + + //Sanity check for renewal + if (leaseDuration >= 0) { + //TODO: would be good to notify the user that his network configuration is + //bad and that the device cannot renew below MIN_RENEWAL_TIME_SECS + if (leaseDuration < MIN_RENEWAL_TIME_SECS) { + leaseDuration = MIN_RENEWAL_TIME_SECS; + } + //Do it a bit earlier than half the lease duration time + //to beat the native DHCP client and avoid extra packets + //48% for one hour lease time = 29 minutes + mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + + leaseDuration * 480, //in milliseconds + mDhcpRenewalIntent); } else { - Log.e(TAG, "DHCP failed on " + mInterfaceName + ": " + + //infinite lease time, no renewal needed + } + + // Fill in any missing fields in dhcpResults from the previous results. + // If mDhcpResults is null (i.e. this is the first server response), + // this is a noop. + dhcpResults.updateFromDhcpRequest(mDhcpResults); + mDhcpResults = dhcpResults; + mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpResults) + .sendToTarget(); + return true; + } + + private boolean runDhcpStart() { + /* Stop any existing DHCP daemon before starting new */ + NetworkUtils.stopDhcp(mInterfaceName); + mDhcpResults = null; + + if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName); + if (!NetworkUtils.startDhcp(mInterfaceName) || !dhcpSucceeded()) { + Log.e(TAG, "DHCP request failed on " + mInterfaceName + ": " + + NetworkUtils.getDhcpError()); + mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0) + .sendToTarget(); + return false; + } + return true; + } + + private boolean runDhcpRenew() { + if (DBG) Log.d(TAG, "DHCP renewal on " + mInterfaceName); + if (!NetworkUtils.startDhcpRenew(mInterfaceName) || !dhcpSucceeded()) { + Log.e(TAG, "DHCP renew failed on " + mInterfaceName + ": " + NetworkUtils.getDhcpError()); - NetworkUtils.stopDhcp(mInterfaceName); mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0) - .sendToTarget(); + .sendToTarget(); + return false; } - return success; + return true; } } diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index ab57c9b..65d325a1 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -48,7 +48,7 @@ import com.android.okhttp.internal.Internal; * {@link ConnectivityManager#registerNetworkCallback} calls. * It is used to direct traffic to the given {@code Network}, either on a {@link Socket} basis * through a targeted {@link SocketFactory} or process-wide via - * {@link ConnectivityManager#setProcessDefaultNetwork}. + * {@link ConnectivityManager#bindProcessToNetwork}. */ public class Network implements Parcelable { @@ -242,7 +242,10 @@ public class Network implements Parcelable { * @see java.net.URL#openConnection() */ public URLConnection openConnection(URL url) throws IOException { - final ConnectivityManager cm = ConnectivityManager.getInstance(); + final ConnectivityManager cm = ConnectivityManager.getInstanceOrNull(); + if (cm == null) { + throw new IOException("No ConnectivityManager yet constructed, please construct one"); + } // TODO: Should this be optimized to avoid fetching the global proxy for every request? ProxyInfo proxyInfo = cm.getGlobalProxy(); if (proxyInfo == null) { @@ -269,7 +272,6 @@ public class Network implements Parcelable { * @throws IllegalArgumentException if the argument proxy is null. * @throws IOException if an error occurs while opening the connection. * @see java.net.URL#openConnection() - * @hide */ public URLConnection openConnection(URL url, java.net.Proxy proxy) throws IOException { if (proxy == null) throw new IllegalArgumentException("proxy is null"); @@ -299,7 +301,7 @@ public class Network implements Parcelable { /** * Binds the specified {@link DatagramSocket} to this {@code Network}. All data traffic on the * socket will be sent on this {@code Network}, irrespective of any process-wide network binding - * set by {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be + * set by {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be * connected. */ public void bindSocket(DatagramSocket socket) throws IOException { @@ -316,7 +318,7 @@ public class Network implements Parcelable { /** * Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket * will be sent on this {@code Network}, irrespective of any process-wide network binding set by - * {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be connected. + * {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected. */ public void bindSocket(Socket socket) throws IOException { // Apparently, the kernel doesn't update a connected TCP socket's routing upon mark changes. diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 02fbe73..29dd8ad 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -159,7 +159,7 @@ public class NetworkUtils { * Return the netId last passed to {@link #bindProcessToNetwork}, or NETID_UNSET if * {@link #unbindProcessToNetwork} has been called since {@link #bindProcessToNetwork}. */ - public native static int getNetworkBoundToProcess(); + public native static int getBoundNetworkForProcess(); /** * Binds host resolutions performed by this process to the network designated by {@code netId}. diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java index 17a84a7..7172c09 100644 --- a/core/java/android/net/Proxy.java +++ b/core/java/android/net/Proxy.java @@ -40,14 +40,9 @@ public final class Proxy { private static final ProxySelector sDefaultProxySelector; /** - * Used to notify an app that's caching the default connection proxy - * that either the default connection or its proxy has changed. - * The intent will have the following extra value:</p> - * <ul> - * <li><em>EXTRA_PROXY_INFO</em> - The ProxyProperties for the proxy. Non-null, - * though if the proxy is undefined the host string - * will be empty. - * </ul> + * Used to notify an app that's caching the proxy that either the default + * connection has changed or any connection's proxy has changed. The new + * proxy should be queried using {@link ConnectivityManager#getDefaultProxy()}. * * <p class="note">This is a protected intent that can only be sent by the system */ @@ -56,6 +51,11 @@ public final class Proxy { /** * Intent extra included with {@link #PROXY_CHANGE_ACTION} intents. * It describes the new proxy being used (as a {@link ProxyInfo} object). + * @deprecated Because {@code PROXY_CHANGE_ACTION} is sent whenever the proxy + * for any network on the system changes, applications should always use + * {@link ConnectivityManager#getDefaultProxy()} or + * {@link ConnectivityManager#getLinkProperties(Network)}.{@link LinkProperties#getHttpProxy()} + * to get the proxy for the Network(s) they are using. */ public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java index c26af06..a0e65eb 100644 --- a/core/java/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -679,7 +679,7 @@ public class VpnService extends Service { * * By default, all traffic from apps is forwarded through the VPN interface and it is not * possible for apps to side-step the VPN. If this method is called, apps may use methods - * such as {@link ConnectivityManager#setProcessDefaultNetwork} to instead send/receive + * such as {@link ConnectivityManager#bindProcessToNetwork} to instead send/receive * directly over the underlying network or any other network they have permissions for. * * @return this {@link Builder} object to facilitate chaining of method calls. diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index 0174f82..60e8ed0 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -269,7 +269,7 @@ static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz return (jboolean) !setNetworkForProcess(netId); } -static jint android_net_utils_getNetworkBoundToProcess(JNIEnv *env, jobject thiz) +static jint android_net_utils_getBoundNetworkForProcess(JNIEnv *env, jobject thiz) { return getNetworkForProcess(); } @@ -307,7 +307,7 @@ static JNINativeMethod gNetworkUtilMethods[] = { { "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease }, { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError }, { "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork }, - { "getNetworkBoundToProcess", "()I", (void*) android_net_utils_getNetworkBoundToProcess }, + { "getBoundNetworkForProcess", "()I", (void*) android_net_utils_getBoundNetworkForProcess }, { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution }, { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork }, { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn }, diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index 2a9f59f..e4054ac 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -97,7 +97,7 @@ public class CaptivePortalLoginActivity extends Activity { final ConnectivityManager cm = ConnectivityManager.from(this); final Network network = new Network(mNetId); // Also initializes proxy system properties. - cm.setProcessDefaultNetwork(network); + cm.bindProcessToNetwork(network); // Proxy system properties must be initialized before setContentView is called because // setContentView initializes the WebView logic which in turn reads the system properties. diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index 6fa653d..3f0a36f 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -221,8 +221,14 @@ public final class Call { */ public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000; - //********************************************************************************************** - // Next CAPABILITY value: 0x00080000 + /** + * Call type can be modified for IMS call + * @hide + */ + public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000; + + //****************************************************************************************** + // Next CAPABILITY value: 0x00100000 //****************************************************************************************** private final Uri mHandle; @@ -238,6 +244,7 @@ public final class Call { private final int mVideoState; private final StatusHints mStatusHints; private final Bundle mExtras; + private final int mCallSubstate; /** * Whether the supplied capabilities supports the specified capability. @@ -325,6 +332,9 @@ public final class Call { if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) { builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO"); } + if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) { + builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO"); + } builder.append("]"); return builder.toString(); } @@ -430,6 +440,14 @@ public final class Call { return mExtras; } + /** + * @return The substate of the {@code Call}. + * @hide + */ + public int getCallSubstate() { + return mCallSubstate; + } + @Override public boolean equals(Object o) { if (o instanceof Details) { @@ -448,7 +466,8 @@ public final class Call { Objects.equals(mGatewayInfo, d.mGatewayInfo) && Objects.equals(mVideoState, d.mVideoState) && Objects.equals(mStatusHints, d.mStatusHints) && - Objects.equals(mExtras, d.mExtras); + Objects.equals(mExtras, d.mExtras) && + Objects.equals(mCallSubstate, d.mCallSubstate); } return false; } @@ -468,7 +487,8 @@ public final class Call { Objects.hashCode(mGatewayInfo) + Objects.hashCode(mVideoState) + Objects.hashCode(mStatusHints) + - Objects.hashCode(mExtras); + Objects.hashCode(mExtras) + + Objects.hashCode(mCallSubstate); } /** {@hide} */ @@ -485,7 +505,8 @@ public final class Call { GatewayInfo gatewayInfo, int videoState, StatusHints statusHints, - Bundle extras) { + Bundle extras, + int callSubstate) { mHandle = handle; mHandlePresentation = handlePresentation; mCallerDisplayName = callerDisplayName; @@ -499,6 +520,7 @@ public final class Call { mVideoState = videoState; mStatusHints = statusHints; mExtras = extras; + mCallSubstate = callSubstate; } } @@ -879,7 +901,8 @@ public final class Call { parcelableCall.getGatewayInfo(), parcelableCall.getVideoState(), parcelableCall.getStatusHints(), - parcelableCall.getExtras()); + parcelableCall.getExtras(), + parcelableCall.getCallSubstate()); boolean detailsChanged = !Objects.equals(mDetails, details); if (detailsChanged) { mDetails = details; diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index 33bbb29..ddaedcd 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -17,10 +17,12 @@ package android.telecom; import android.annotation.SystemApi; +import android.telecom.Connection.VideoProvider; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; @@ -49,6 +51,8 @@ public abstract class Conference implements IConferenceable { public void onDestroyed(Conference conference) {} public void onConnectionCapabilitiesChanged( Conference conference, int connectionCapabilities) {} + public void onVideoStateChanged(Conference c, int videoState) { } + public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) {} } private final Set<Listener> mListeners = new CopyOnWriteArraySet<>(); @@ -180,6 +184,22 @@ public abstract class Conference implements IConferenceable { } /** + * Returns VideoProvider of the primary call. This can be null. + * @hide + */ + public VideoProvider getVideoProvider() { + return null; + } + + /** + * Returns video state of the primary call. + * @hide + */ + public int getVideoState() { + return VideoProfile.VideoState.AUDIO_ONLY; + } + + /** * Invoked when the Conference and all it's {@link Connection}s should be disconnected. */ public void onDisconnect() {} @@ -309,6 +329,7 @@ public abstract class Conference implements IConferenceable { * @return True if the connection was successfully added. */ public final boolean addConnection(Connection connection) { + Log.d(this, "Connection=%s, connection=", connection); if (connection != null && !mChildConnections.contains(connection)) { if (connection.setConference(this)) { mChildConnections.add(connection); @@ -355,6 +376,38 @@ public abstract class Conference implements IConferenceable { fireOnConferenceableConnectionsChanged(); } + /** + * Set the video state for the conference. + * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY}, + * {@link VideoProfile.VideoState#BIDIRECTIONAL}, + * {@link VideoProfile.VideoState#TX_ENABLED}, + * {@link VideoProfile.VideoState#RX_ENABLED}. + * + * @param videoState The new video state. + * @hide + */ + public final void setVideoState(Connection c, int videoState) { + Log.d(this, "setVideoState Conference: %s Connection: %s VideoState: %s", + this, c, videoState); + for (Listener l : mListeners) { + l.onVideoStateChanged(this, videoState); + } + } + + /** + * Sets the video connection provider. + * + * @param videoProvider The video provider. + * @hide + */ + public final void setVideoProvider(Connection c, Connection.VideoProvider videoProvider) { + Log.d(this, "setVideoProvider Conference: %s Connection: %s VideoState: %s", + this, c, videoProvider); + for (Listener l : mListeners) { + l.onVideoProviderChanged(this, videoProvider); + } + } + private final void fireOnConferenceableConnectionsChanged() { for (Listener l : mListeners) { l.onConferenceableConnectionsChanged(this, getConferenceableConnections()); @@ -484,4 +537,15 @@ public abstract class Conference implements IConferenceable { } mConferenceableConnections.clear(); } + + @Override + public String toString() { + return String.format(Locale.US, + "[State: %s,Capabilites: %s, VideoState: %s, VideoProvider: %s, ThisObject %s]", + Connection.stateToString(mState), + Call.Details.capabilitiesToString(mConnectionCapabilities), + getVideoState(), + getVideoProvider(), + super.toString()); + } } diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 082474b..dc3f963 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -186,10 +186,58 @@ public abstract class Connection implements IConferenceable { */ public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000; + /** + * Call type can be modified for IMS call + * @hide + */ + public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000; + //********************************************************************************************** - // Next CAPABILITY value: 0x00080000 + // Next CAPABILITY value: 0x00100000 //********************************************************************************************** + /** + * Call substate bitmask values + */ + + /* Default case */ + /** + * @hide + */ + public static final int SUBSTATE_NONE = 0; + + /* Indicates that the call is connected but audio attribute is suspended */ + /** + * @hide + */ + public static final int SUBSTATE_AUDIO_CONNECTED_SUSPENDED = 0x1; + + /* Indicates that the call is connected but video attribute is suspended */ + /** + * @hide + */ + public static final int SUBSTATE_VIDEO_CONNECTED_SUSPENDED = 0x2; + + /* Indicates that the call is established but media retry is needed */ + /** + * @hide + */ + public static final int SUBSTATE_AVP_RETRY = 0x4; + + /* Indicates that the call is multitasking */ + /** + * @hide + */ + public static final int SUBSTATE_MEDIA_PAUSED = 0x8; + + /* Mask containing all the call substate bits set */ + /** + * @hide + */ + public static final int SUBSTATE_ALL = SUBSTATE_AUDIO_CONNECTED_SUSPENDED | + SUBSTATE_VIDEO_CONNECTED_SUSPENDED | SUBSTATE_AVP_RETRY | + SUBSTATE_MEDIA_PAUSED; + // Flag controlling whether PII is emitted into the logs private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG); @@ -294,6 +342,9 @@ public abstract class Connection implements IConferenceable { if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) { builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO"); } + if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) { + builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO"); + } builder.append("]"); return builder.toString(); } @@ -322,6 +373,7 @@ public abstract class Connection implements IConferenceable { public void onConferenceParticipantsChanged(Connection c, List<ConferenceParticipant> participants) {} public void onConferenceStarted() {} + public void onCallSubstateChanged(Connection c, int substate) {} } /** @hide */ @@ -377,6 +429,16 @@ public abstract class Connection implements IConferenceable { */ public static final int SESSION_MODIFY_REQUEST_INVALID = 3; + /** + * Session modify request timed out. + */ + public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; + + /** + * Session modify request rejected by remote UE. + */ + public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; + private static final int MSG_SET_VIDEO_CALLBACK = 1; private static final int MSG_SET_CAMERA = 2; private static final int MSG_SET_PREVIEW_SURFACE = 3; @@ -462,7 +524,8 @@ public abstract class Connection implements IConferenceable { } public void setDeviceOrientation(int rotation) { - mMessageHandler.obtainMessage(MSG_SET_DEVICE_ORIENTATION, rotation).sendToTarget(); + mMessageHandler.obtainMessage( + MSG_SET_DEVICE_ORIENTATION, rotation, 0).sendToTarget(); } public void setZoom(float value) { @@ -656,7 +719,7 @@ public abstract class Connection implements IConferenceable { * * @param dataUsage The updated data usage. */ - public void changeCallDataUsage(int dataUsage) { + public void changeCallDataUsage(long dataUsage) { if (mVideoCallback != null) { try { mVideoCallback.changeCallDataUsage(dataUsage); @@ -678,6 +741,20 @@ public abstract class Connection implements IConferenceable { } } } + + /** + * Invokes callback method defined in In-Call UI. + * + * @param videoQuality The updated video quality. + */ + public void changeVideoQuality(int videoQuality) { + if (mVideoCallback != null) { + try { + mVideoCallback.changeVideoQuality(videoQuality); + } catch (RemoteException ignored) { + } + } + } } private final Listener mConnectionDeathListener = new Listener() { @@ -724,6 +801,7 @@ public abstract class Connection implements IConferenceable { private DisconnectCause mDisconnectCause; private Conference mConference; private ConnectionService mConnectionService; + private int mCallSubstate; /** * Create a new Connection. @@ -782,6 +860,21 @@ public abstract class Connection implements IConferenceable { } /** + * Returns the call substate of the call. + * Valid values: {@link Connection#SUBSTATE_NONE}, + * {@link Connection#SUBSTATE_AUDIO_CONNECTED_SUSPENDED}, + * {@link Connection#SUBSTATE_VIDEO_CONNECTED_SUSPENDED}, + * {@link Connection#SUBSTATE_AVP_RETRY}, + * {@link Connection#SUBSTATE_MEDIA_PAUSED}. + * + * @param callSubstate The new call substate. + * @hide + */ + public final int getCallSubstate() { + return mCallSubstate; + } + + /** * @return The audio state of the connection, describing how its audio is currently * being routed by the system. This is {@code null} if this Connection * does not directly know about its audio state. @@ -960,6 +1053,25 @@ public abstract class Connection implements IConferenceable { } /** + * Set the call substate for the connection. + * Valid values: {@link Connection#SUBSTATE_NONE}, + * {@link Connection#SUBSTATE_AUDIO_CONNECTED_SUSPENDED}, + * {@link Connection#SUBSTATE_VIDEO_CONNECTED_SUSPENDED}, + * {@link Connection#SUBSTATE_AVP_RETRY}, + * {@link Connection#SUBSTATE_MEDIA_PAUSED}. + * + * @param callSubstate The new call substate. + * @hide + */ + public final void setCallSubstate(int callSubstate) { + Log.d(this, "setCallSubstate %d", callSubstate); + mCallSubstate = callSubstate; + for (Listener l : mListeners) { + l.onCallSubstateChanged(this, mCallSubstate); + } + } + + /** * Sets state to active (e.g., an ongoing connection where two or more parties can actively * communicate). */ diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index dfdc3e1..0c719cd 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -415,6 +415,21 @@ public abstract class ConnectionService extends Service { Connection.capabilitiesToString(connectionCapabilities)); mAdapter.setConnectionCapabilities(id, connectionCapabilities); } + + @Override + public void onVideoStateChanged(Conference c, int videoState) { + String id = mIdByConference.get(c); + Log.d(this, "onVideoStateChanged set video state %d", videoState); + mAdapter.setVideoState(id, videoState); + } + + @Override + public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) { + String id = mIdByConference.get(c); + Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c, + videoProvider); + mAdapter.setVideoProvider(id, videoProvider); + } }; private final Connection.Listener mConnectionListener = new Connection.Listener() { @@ -508,6 +523,8 @@ public abstract class ConnectionService extends Service { @Override public void onVideoProviderChanged(Connection c, Connection.VideoProvider videoProvider) { String id = mIdByConnection.get(c); + Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c, + videoProvider); mAdapter.setVideoProvider(id, videoProvider); } @@ -542,6 +559,13 @@ public abstract class ConnectionService extends Service { mAdapter.setIsConferenced(id, conferenceId); } } + + @Override + public void onCallSubstateChanged(Connection c, int callSubstate) { + String id = mIdByConnection.get(c); + Log.d(this, "Adapter set call substate %d", callSubstate); + mAdapter.setCallSubstate(id, callSubstate); + } }; /** {@inheritDoc} */ @@ -611,7 +635,8 @@ public abstract class ConnectionService extends Service { connection.getAudioModeIsVoip(), connection.getStatusHints(), connection.getDisconnectCause(), - createIdList(connection.getConferenceables()))); + createIdList(connection.getConferenceables()), + connection.getCallSubstate())); } private void abort(String callId) { @@ -871,6 +896,8 @@ public abstract class ConnectionService extends Service { * @param conference The new conference object. */ public final void addConference(Conference conference) { + Log.d(this, "addConference: conference=%s", conference); + String id = addConferenceInternal(conference); if (id != null) { List<String> connectionIds = new ArrayList<>(2); @@ -884,8 +911,14 @@ public abstract class ConnectionService extends Service { conference.getState(), conference.getConnectionCapabilities(), connectionIds, - conference.getConnectTimeMillis()); + conference.getVideoProvider() == null ? + null : conference.getVideoProvider().getInterface(), + conference.getVideoState(), + conference.getConnectTimeMillis() + ); mAdapter.addConferenceCall(id, parcelableConference); + mAdapter.setVideoProvider(id, conference.getVideoProvider()); + mAdapter.setVideoState(id, conference.getVideoState()); // Go through any child calls and set the parent. for (Connection connection : conference.getConnections()) { @@ -926,7 +959,7 @@ public abstract class ConnectionService extends Service { connection.getAudioModeIsVoip(), connection.getStatusHints(), connection.getDisconnectCause(), - emptyList); + emptyList, connection.getCallSubstate()); mAdapter.addExistingConnection(id, parcelableConnection); } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java index d026a28..a410976 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java @@ -369,4 +369,26 @@ final class ConnectionServiceAdapter implements DeathRecipient { } } } + + /** + * Set the call substate for the connection. + * Valid values: {@link Connection#CALL_SUBSTATE_NONE}, + * {@link Connection#CALL_SUBSTATE_AUDIO_CONNECTED_SUSPENDED}, + * {@link Connection#CALL_SUBSTATE_VIDEO_CONNECTED_SUSPENDED}, + * {@link Connection#CALL_SUBSTATE_AVP_RETRY}, + * {@link Connection#CALL_SUBSTATE_MEDIA_PAUSED}. + * + * @param callId The unique ID of the call to set the substate for. + * @param callSubstate The new call substate. + * @hide + */ + public final void setCallSubstate(String callId, int callSubstate) { + Log.v(this, "setCallSubstate: %d", callSubstate); + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + adapter.setCallSubstate(callId, callSubstate); + } catch (RemoteException ignored) { + } + } + } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java index 429f296..5f93789 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java @@ -59,6 +59,7 @@ final class ConnectionServiceAdapterServant { private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20; private static final int MSG_ADD_EXISTING_CONNECTION = 21; private static final int MSG_ON_POST_DIAL_CHAR = 22; + private static final int MSG_SET_CALL_SUBSTATE = 23; private final IConnectionServiceAdapter mDelegate; @@ -220,6 +221,10 @@ final class ConnectionServiceAdapterServant { } break; } + case MSG_SET_CALL_SUBSTATE: { + mDelegate.setCallSubstate((String) msg.obj, msg.arg1); + break; + } } } }; @@ -384,6 +389,12 @@ final class ConnectionServiceAdapterServant { args.arg2 = connection; mHandler.obtainMessage(MSG_ADD_EXISTING_CONNECTION, args).sendToTarget(); } + + @Override + public void setCallSubstate(String connectionId, int callSubstate) { + mHandler.obtainMessage(MSG_SET_CALL_SUBSTATE, callSubstate, 0, + connectionId).sendToTarget(); + } }; public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) { diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java index a85e84d..c0c59fa 100644 --- a/telecomm/java/android/telecom/InCallService.java +++ b/telecomm/java/android/telecom/InCallService.java @@ -361,11 +361,18 @@ public abstract class InCallService extends Service { public abstract void onPeerDimensionsChanged(int width, int height); /** + * Handles a change to the video quality. + * + * @param videoQuality The updated peer video quality. + */ + public abstract void onVideoQualityChanged(int videoQuality); + + /** * Handles an update to the total data used for the current session. * * @param dataUsage The updated data usage. */ - public abstract void onCallDataUsageChanged(int dataUsage); + public abstract void onCallDataUsageChanged(long dataUsage); /** * Handles a change in camera capabilities. diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java index c5c3d11..adc648f 100644 --- a/telecomm/java/android/telecom/ParcelableCall.java +++ b/telecomm/java/android/telecom/ParcelableCall.java @@ -54,6 +54,7 @@ public final class ParcelableCall implements Parcelable { private final int mVideoState; private final List<String> mConferenceableCallIds; private final Bundle mExtras; + private int mCallSubstate; public ParcelableCall( String id, @@ -75,7 +76,8 @@ public final class ParcelableCall implements Parcelable { StatusHints statusHints, int videoState, List<String> conferenceableCallIds, - Bundle extras) { + Bundle extras, + int callSubstate) { mId = id; mState = state; mDisconnectCause = disconnectCause; @@ -96,6 +98,7 @@ public final class ParcelableCall implements Parcelable { mVideoState = videoState; mConferenceableCallIds = Collections.unmodifiableList(conferenceableCallIds); mExtras = extras; + mCallSubstate = callSubstate; } /** The unique ID of the call. */ @@ -232,6 +235,14 @@ public final class ParcelableCall implements Parcelable { return mExtras; } + /** + * The call substate. + * @return The substate of the call. + */ + public int getCallSubstate() { + return mCallSubstate; + } + /** Responsible for creating ParcelableCall objects for deserialized Parcels. */ public static final Parcelable.Creator<ParcelableCall> CREATOR = new Parcelable.Creator<ParcelableCall> () { @@ -262,6 +273,7 @@ public final class ParcelableCall implements Parcelable { List<String> conferenceableCallIds = new ArrayList<>(); source.readList(conferenceableCallIds, classLoader); Bundle extras = source.readParcelable(classLoader); + int callSubstate = source.readInt(); return new ParcelableCall( id, state, @@ -282,7 +294,8 @@ public final class ParcelableCall implements Parcelable { statusHints, videoState, conferenceableCallIds, - extras); + extras, + callSubstate); } @Override @@ -321,6 +334,7 @@ public final class ParcelableCall implements Parcelable { destination.writeInt(mVideoState); destination.writeList(mConferenceableCallIds); destination.writeParcelable(mExtras, 0); + destination.writeInt(mCallSubstate); } @Override diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java index dcc2713..ab82549 100644 --- a/telecomm/java/android/telecom/ParcelableConference.java +++ b/telecomm/java/android/telecom/ParcelableConference.java @@ -22,6 +22,8 @@ import android.os.Parcelable; import java.util.ArrayList; import java.util.List; +import com.android.internal.telecom.IVideoProvider; + /** * A parcelable representation of a conference connection. * @hide @@ -33,17 +35,23 @@ public final class ParcelableConference implements Parcelable { private int mConnectionCapabilities; private List<String> mConnectionIds; private long mConnectTimeMillis; + private final IVideoProvider mVideoProvider; + private final int mVideoState; public ParcelableConference( PhoneAccountHandle phoneAccount, int state, int connectionCapabilities, - List<String> connectionIds) { + List<String> connectionIds, + IVideoProvider videoProvider, + int videoState) { mPhoneAccount = phoneAccount; mState = state; mConnectionCapabilities = connectionCapabilities; mConnectionIds = connectionIds; mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; + mVideoProvider = videoProvider; + mVideoState = videoState; } public ParcelableConference( @@ -51,8 +59,10 @@ public final class ParcelableConference implements Parcelable { int state, int connectionCapabilities, List<String> connectionIds, + IVideoProvider videoProvider, + int videoState, long connectTimeMillis) { - this(phoneAccount, state, connectionCapabilities, connectionIds); + this(phoneAccount, state, connectionCapabilities, connectionIds, videoProvider, videoState); mConnectTimeMillis = connectTimeMillis; } @@ -69,6 +79,10 @@ public final class ParcelableConference implements Parcelable { .append(mConnectTimeMillis) .append(", children: ") .append(mConnectionIds) + .append(", VideoState: ") + .append(mVideoState) + .append(", VideoProvider: ") + .append(mVideoProvider) .toString(); } @@ -91,6 +105,13 @@ public final class ParcelableConference implements Parcelable { public long getConnectTimeMillis() { return mConnectTimeMillis; } + public IVideoProvider getVideoProvider() { + return mVideoProvider; + } + + public int getVideoState() { + return mVideoState; + } public static final Parcelable.Creator<ParcelableConference> CREATOR = new Parcelable.Creator<ParcelableConference> () { @@ -104,8 +125,12 @@ public final class ParcelableConference implements Parcelable { source.readList(connectionIds, classLoader); long connectTimeMillis = source.readLong(); + IVideoProvider videoCallProvider = + IVideoProvider.Stub.asInterface(source.readStrongBinder()); + int videoState = source.readInt(); + return new ParcelableConference(phoneAccount, state, capabilities, connectionIds, - connectTimeMillis); + videoCallProvider, videoState); } @Override @@ -128,5 +153,8 @@ public final class ParcelableConference implements Parcelable { destination.writeInt(mConnectionCapabilities); destination.writeList(mConnectionIds); destination.writeLong(mConnectTimeMillis); + destination.writeStrongBinder( + mVideoProvider != null ? mVideoProvider.asBinder() : null); + destination.writeInt(mVideoState); } } diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java index 552e250..b60b99d 100644 --- a/telecomm/java/android/telecom/ParcelableConnection.java +++ b/telecomm/java/android/telecom/ParcelableConnection.java @@ -46,6 +46,7 @@ public final class ParcelableConnection implements Parcelable { private final StatusHints mStatusHints; private final DisconnectCause mDisconnectCause; private final List<String> mConferenceableConnectionIds; + private final int mCallSubstate; /** @hide */ public ParcelableConnection( @@ -62,7 +63,8 @@ public final class ParcelableConnection implements Parcelable { boolean isVoipAudioMode, StatusHints statusHints, DisconnectCause disconnectCause, - List<String> conferenceableConnectionIds) { + List<String> conferenceableConnectionIds, + int callSubstate) { mPhoneAccount = phoneAccount; mState = state; mConnectionCapabilities = capabilities; @@ -77,6 +79,7 @@ public final class ParcelableConnection implements Parcelable { mStatusHints = statusHints; mDisconnectCause = disconnectCause; this.mConferenceableConnectionIds = conferenceableConnectionIds; + mCallSubstate = callSubstate; } public PhoneAccountHandle getPhoneAccount() { @@ -136,6 +139,10 @@ public final class ParcelableConnection implements Parcelable { return mConferenceableConnectionIds; } + public int getCallSubstate() { + return mCallSubstate; + } + @Override public String toString() { return new StringBuilder() @@ -170,6 +177,7 @@ public final class ParcelableConnection implements Parcelable { DisconnectCause disconnectCause = source.readParcelable(classLoader); List<String> conferenceableConnectionIds = new ArrayList<>(); source.readStringList(conferenceableConnectionIds); + int callSubstate = source.readInt(); return new ParcelableConnection( phoneAccount, @@ -185,7 +193,8 @@ public final class ParcelableConnection implements Parcelable { audioModeIsVoip, statusHints, disconnectCause, - conferenceableConnectionIds); + conferenceableConnectionIds, + callSubstate); } @Override @@ -218,5 +227,6 @@ public final class ParcelableConnection implements Parcelable { destination.writeParcelable(mStatusHints, 0); destination.writeParcelable(mDisconnectCause, 0); destination.writeStringList(mConferenceableConnectionIds); + destination.writeInt(mCallSubstate); } } diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java index 486691f..be7a0a0 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -161,6 +161,16 @@ public final class RemoteConnection { public void onVideoStateChanged(RemoteConnection connection, int videoState) {} /** + * Indicates that the call substate of this {@code RemoteConnection} has changed. + * See {@link #getCallSubstate()}. + * + * @param connection The {@code RemoteConnection} invoking this method. + * @param callSubstate The new call substate of the {@code RemoteConnection}. + * @hide + */ + public void onCallSubstateChanged(RemoteConnection connection, int callSubstate) {} + + /** * Indicates that this {@code RemoteConnection} has been destroyed. No further requests * should be made to the {@code RemoteConnection}, and references to it should be cleared. * @@ -223,11 +233,13 @@ public final class RemoteConnection { public void onPeerDimensionsChanged(VideoProvider videoProvider, int width, int height) {} - public void onCallDataUsageChanged(VideoProvider videoProvider, int dataUsage) {} + public void onCallDataUsageChanged(VideoProvider videoProvider, long dataUsage) {} public void onCameraCapabilitiesChanged( VideoProvider videoProvider, CameraCapabilities cameraCapabilities) {} + + public void onVideoQualityChanged(VideoProvider videoProvider, int videoQuality) {} } private final IVideoCallback mVideoCallbackDelegate = new IVideoCallback() { @@ -265,7 +277,7 @@ public final class RemoteConnection { } @Override - public void changeCallDataUsage(int dataUsage) { + public void changeCallDataUsage(long dataUsage) { for (Listener l : mListeners) { l.onCallDataUsageChanged(VideoProvider.this, dataUsage); } @@ -279,6 +291,13 @@ public final class RemoteConnection { } @Override + public void changeVideoQuality(int videoQuality) { + for (Listener l : mListeners) { + l.onVideoQualityChanged(VideoProvider.this, videoQuality); + } + } + + @Override public IBinder asBinder() { return null; } @@ -403,6 +422,7 @@ public final class RemoteConnection { private boolean mConnected; private int mConnectionCapabilities; private int mVideoState; + private int mCallSubstate; private VideoProvider mVideoProvider; private boolean mIsVoipAudioMode; private StatusHints mStatusHints; @@ -583,8 +603,16 @@ public final class RemoteConnection { } /** - * Obtains the video provider of this {@code RemoteConnection}. * + * @return The call substate of the {@code RemoteConnection}. See + * @hide + */ + public int getCallSubstate() { + return mCallSubstate; + } + + /** + * Obtains the video provider of this {@code RemoteConnection}. * @return The video provider associated with this {@code RemoteConnection}. * @hide */ @@ -897,6 +925,16 @@ public final class RemoteConnection { /** * @hide */ + void setCallSubstate(int callSubstate) { + mCallSubstate = callSubstate; + for (Callback c : mCallbacks) { + c.onCallSubstateChanged(this, callSubstate); + } + } + + /** + * @hide + */ void setVideoProvider(VideoProvider videoProvider) { mVideoProvider = videoProvider; for (Callback c : mCallbacks) { diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index a9b725b..7374a3b 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -84,6 +84,7 @@ final class RemoteConnectionService { } connection.setConferenceableConnections(conferenceable); connection.setVideoState(parcel.getVideoState()); + connection.setCallSubstate(parcel.getCallSubstate()); if (connection.getState() == Connection.STATE_DISCONNECTED) { // ... then, if it was created in a disconnected state, that indicates // failure on the providing end, so immediately mark it destroyed @@ -311,6 +312,12 @@ final class RemoteConnectionService { mOurConnectionServiceImpl.addRemoteExistingConnection(remoteConnction); } + + @Override + public void setCallSubstate(String callId, int callSubstate) { + findConnectionForAction(callId, "callSubstate") + .setCallSubstate(callSubstate); + } }; private final ConnectionServiceAdapterServant mServant = diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java index 925058e..0445448 100644 --- a/telecomm/java/android/telecom/VideoCallImpl.java +++ b/telecomm/java/android/telecom/VideoCallImpl.java @@ -42,6 +42,7 @@ public class VideoCallImpl extends VideoCall { private static final int MSG_CHANGE_PEER_DIMENSIONS = 4; private static final int MSG_CHANGE_CALL_DATA_USAGE = 5; private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6; + private static final int MSG_CHANGE_VIDEO_QUALITY = 7; private final IVideoProvider mVideoProvider; private final VideoCallListenerBinder mBinder; @@ -88,7 +89,12 @@ public class VideoCallImpl extends VideoCall { } @Override - public void changeCallDataUsage(int dataUsage) { + public void changeVideoQuality(int videoQuality) { + mHandler.obtainMessage(MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0).sendToTarget(); + } + + @Override + public void changeCallDataUsage(long dataUsage) { mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, dataUsage).sendToTarget(); } @@ -139,12 +145,15 @@ public class VideoCallImpl extends VideoCall { } break; case MSG_CHANGE_CALL_DATA_USAGE: - mVideoCallListener.onCallDataUsageChanged(msg.arg1); + mVideoCallListener.onCallDataUsageChanged((long) msg.obj); break; case MSG_CHANGE_CAMERA_CAPABILITIES: mVideoCallListener.onCameraCapabilitiesChanged( (CameraCapabilities) msg.obj); break; + case MSG_CHANGE_VIDEO_QUALITY: + mVideoCallListener.onVideoQualityChanged(msg.arg1); + break; default: break; } @@ -244,4 +253,4 @@ public class VideoCallImpl extends VideoCall { } catch (RemoteException e) { } } -}
\ No newline at end of file +} diff --git a/telecomm/java/android/telecom/VideoCallbackServant.java b/telecomm/java/android/telecom/VideoCallbackServant.java index d0e3f22..1123621 100644 --- a/telecomm/java/android/telecom/VideoCallbackServant.java +++ b/telecomm/java/android/telecom/VideoCallbackServant.java @@ -38,6 +38,7 @@ final class VideoCallbackServant { private static final int MSG_CHANGE_PEER_DIMENSIONS = 3; private static final int MSG_CHANGE_CALL_DATA_USAGE = 4; private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 5; + private static final int MSG_CHANGE_VIDEO_QUALITY = 6; private final IVideoCallback mDelegate; @@ -90,7 +91,7 @@ final class VideoCallbackServant { case MSG_CHANGE_CALL_DATA_USAGE: { SomeArgs args = (SomeArgs) msg.obj; try { - mDelegate.changeCallDataUsage(args.argi1); + mDelegate.changeCallDataUsage((long) args.arg1); } finally { args.recycle(); } @@ -100,6 +101,10 @@ final class VideoCallbackServant { mDelegate.changeCameraCapabilities((CameraCapabilities) msg.obj); break; } + case MSG_CHANGE_VIDEO_QUALITY: { + mDelegate.changeVideoQuality(msg.arg1); + break; + } } } }; @@ -136,9 +141,9 @@ final class VideoCallbackServant { } @Override - public void changeCallDataUsage(int dataUsage) throws RemoteException { + public void changeCallDataUsage(long dataUsage) throws RemoteException { SomeArgs args = SomeArgs.obtain(); - args.argi1 = dataUsage; + args.arg1 = dataUsage; mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, args).sendToTarget(); } @@ -148,6 +153,11 @@ final class VideoCallbackServant { mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES, cameraCapabilities) .sendToTarget(); } + + @Override + public void changeVideoQuality(int videoQuality) throws RemoteException { + mHandler.obtainMessage(MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0).sendToTarget(); + } }; public VideoCallbackServant(IVideoCallback delegate) { diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java index e62e994..2fd438a 100644 --- a/telecomm/java/android/telecom/VideoProfile.java +++ b/telecomm/java/android/telecom/VideoProfile.java @@ -24,6 +24,11 @@ import android.os.Parcelable; */ public class VideoProfile implements Parcelable { /** + * "Unknown" video quality. + * @hide + */ + public static final int QUALITY_UNKNOWN = 0; + /** * "High" video quality. */ public static final int QUALITY_HIGH = 1; @@ -179,6 +184,17 @@ public class VideoProfile implements Parcelable { } /** + * Whether the video state is any of the video type + * @param videoState The video state. + * @hide + * @return Returns true if the video state TX or RX or Bidirectional + */ + public static boolean isVideo(int videoState) { + return hasState(videoState, TX_ENABLED) || hasState(videoState, RX_ENABLED) + || hasState(videoState, BIDIRECTIONAL); + } + + /** * Whether the video transmission is enabled. * @param videoState The video state. * @return Returns true if the video transmission is enabled. diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl index 7e7e9cc..e6c28f3 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl @@ -81,4 +81,6 @@ oneway interface IConnectionServiceAdapter { void setConferenceableConnections(String callId, in List<String> conferenceableCallIds); void addExistingConnection(String callId, in ParcelableConnection connection); + + void setCallSubstate(String callId, int callSubstate); } diff --git a/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl b/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl index f758b60..59f8f0c 100644 --- a/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl +++ b/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl @@ -39,7 +39,9 @@ oneway interface IVideoCallback { void changePeerDimensions(int width, int height); - void changeCallDataUsage(int dataUsage); + void changeCallDataUsage(long dataUsage); void changeCameraCapabilities(in CameraCapabilities cameraCapabilities); + + void changeVideoQuality(int videoQuality); } diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java index 239c16a..604d32d 100644 --- a/telephony/java/com/android/ims/ImsCallProfile.java +++ b/telephony/java/com/android/ims/ImsCallProfile.java @@ -270,7 +270,6 @@ public class ImsCallProfile implements Parcelable { return "{ serviceType=" + mServiceType + ", callType=" + mCallType + ", restrictCause=" + mRestrictCause + - //", callExtras=" + mCallExtras.toString() + ", mediaProfile=" + mMediaProfile.toString() + " }"; } @@ -313,22 +312,31 @@ public class ImsCallProfile implements Parcelable { * @param callType The call type. * @return The video state. */ - public static int getVideoStateFromCallType(int callType) { - switch (callType) { - case CALL_TYPE_VT_NODIR: - return VideoProfile.VideoState.PAUSED | - VideoProfile.VideoState.BIDIRECTIONAL; + public static int getVideoStateFromImsCallProfile(ImsCallProfile callProfile) { + int videostate = VideoProfile.VideoState.AUDIO_ONLY; + switch (callProfile.mCallType) { case CALL_TYPE_VT_TX: - return VideoProfile.VideoState.TX_ENABLED; + videostate = VideoProfile.VideoState.TX_ENABLED; + break; case CALL_TYPE_VT_RX: - return VideoProfile.VideoState.RX_ENABLED; + videostate = VideoProfile.VideoState.RX_ENABLED; + break; case CALL_TYPE_VT: - return VideoProfile.VideoState.BIDIRECTIONAL; + videostate = VideoProfile.VideoState.BIDIRECTIONAL; + break; case CALL_TYPE_VOICE: - return VideoProfile.VideoState.AUDIO_ONLY; + videostate = VideoProfile.VideoState.AUDIO_ONLY; + break; default: - return VideoProfile.VideoState.AUDIO_ONLY; + videostate = VideoProfile.VideoState.AUDIO_ONLY; + break; } + if (callProfile.isVideoPaused() && videostate != VideoProfile.VideoState.AUDIO_ONLY) { + videostate |= VideoProfile.VideoState.PAUSED; + } else { + videostate &= ~VideoProfile.VideoState.PAUSED; + } + return videostate; } /** @@ -387,6 +395,14 @@ public class ImsCallProfile implements Parcelable { } /** + * Checks if video call is paused + * @return true if call is video paused + */ + public boolean isVideoPaused() { + return mMediaProfile.mVideoDirection == ImsStreamMediaProfile.DIRECTION_INACTIVE; + } + + /** * Determines if a video state is set in a video state bit-mask. * * @param videoState The video state bit mask. diff --git a/telephony/java/com/android/ims/ImsConfigListener.aidl b/telephony/java/com/android/ims/ImsConfigListener.aidl index e827774..64a5015 100644 --- a/telephony/java/com/android/ims/ImsConfigListener.aidl +++ b/telephony/java/com/android/ims/ImsConfigListener.aidl @@ -48,4 +48,26 @@ oneway interface ImsConfigListener { * @return void. */ void onSetFeatureResponse(int feature, int network, int value, int status); -}
\ No newline at end of file + + /** + * Notifies client the value of the get operation result on the video quality item. + * + * @param status. as defined in com.android.ims.ImsConfig#OperationStatusConstants. + * @param quality. as defined in com.android.ims.ImsConfig#OperationValuesConstants. + * @return void + * + * @throws ImsException if calling the IMS service results in an error. + */ + void onGetVideoQuality(int status, int quality); + + /** + * Notifies client the set value operation result for video quality item. + * Used by clients that need to be notified the set operation result. + * + * @param status. as defined in com.android.ims.ImsConfig#OperationStatusConstants. + * @return void + * + * @throws ImsException if calling the IMS service results in an error. + */ + void onSetVideoQuality(int status); +} diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl index b1f2d32..9b435dc 100644 --- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl +++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl @@ -255,4 +255,11 @@ interface IImsCallSession { * @return {@code True} if the session is multiparty. */ boolean isMultiparty(); + + /** + * Gets the call substate for this session. + * + * @return the call substate for this session. + */ + int getCallSubstate(); } diff --git a/telephony/java/com/android/ims/internal/IImsConfig.aidl b/telephony/java/com/android/ims/internal/IImsConfig.aidl index 441e03e..7324814 100644 --- a/telephony/java/com/android/ims/internal/IImsConfig.aidl +++ b/telephony/java/com/android/ims/internal/IImsConfig.aidl @@ -100,4 +100,24 @@ interface IImsConfig { * @return void */ boolean getVolteProvisioned(); + + /** + * + * Gets the value for ims fature item video quality. + * + * @param listener. Video quality value returned asynchronously through listener. + * @return void + */ + oneway void getVideoQuality(ImsConfigListener listener); + + /** + * Sets the value for IMS feature item video quality. + * + * @param quality, defines the value of video quality. + * @param listener, provided if caller needs to be notified for set result. + * @return void + * + * @throws ImsException if calling the IMS service results in an error. + */ + oneway void setVideoQuality(int quality, ImsConfigListener listener); } diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl index f867fcb..be8751b 100644 --- a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl +++ b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl @@ -41,7 +41,9 @@ oneway interface IImsVideoCallCallback { void changePeerDimensions(int width, int height); - void changeCallDataUsage(int dataUsage); + void changeCallDataUsage(long dataUsage); void changeCameraCapabilities(in CameraCapabilities cameraCapabilities); + + void changeVideoQuality(int videoQuality); } diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java index b8e8064..0ebd719 100644 --- a/telephony/java/com/android/internal/telephony/PhoneConstants.java +++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java @@ -186,4 +186,11 @@ public class PhoneConstants { //FIXME maybe this shouldn't be here - sprout only public static final int CAPABILITY_3G = 1; + + /** + * Values for the adb property "persist.radio.videocall.audio.output" + */ + public static final int AUDIO_OUTPUT_ENABLE_SPEAKER = 0; + public static final int AUDIO_OUTPUT_DISABLE_SPEAKER = 1; + public static final int AUDIO_OUTPUT_DEFAULT = AUDIO_OUTPUT_ENABLE_SPEAKER; } diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 0fccfa5..645c3a1 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -204,4 +204,17 @@ public interface TelephonyProperties * Type: string ( default = silent, enable to = prompt ) */ static final String PROPERTY_MMS_TRANSACTION = "mms.transaction"; + + /** + * Set to the sim count. + */ + static final String PROPERTY_SIM_COUNT = "ro.telephony.sim.count"; + + /** + * Controls audio route for video calls. + * 0 - Use the default audio routing strategy. + * 1 - Disable the speaker. Route the audio to Headset or Bluetooth + * or Earpiece, based on the default audio routing strategy. + */ + static final String PROPERTY_VIDEOCALL_AUDIO_OUTPUT = "persist.radio.call.audio.output"; } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 5342494..6e6d6f6 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -47,6 +47,8 @@ interface IWifiManager List<WifiConfiguration> getPrivilegedConfiguredNetworks(); + WifiConfiguration getMatchingWifiConfig(in ScanResult scanResult); + int addOrUpdateNetwork(in WifiConfiguration config); boolean removeNetwork(int netId); @@ -113,6 +115,8 @@ interface IWifiManager WifiConfiguration getWifiApConfiguration(); + WifiConfiguration buildWifiConfig(String uriString, String mimeType, in byte[] data); + void setWifiApConfiguration(in WifiConfiguration wifiConfig); void startWifi(); diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index 65ecf5d..b156d0c 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -26,51 +26,109 @@ public class RttManager { private static final boolean DBG = true; private static final String TAG = "RttManager"; - /** @deprecated Type must be specified*/ + /** @deprecated It is Not supported anymore. */ @Deprecated public static final int RTT_TYPE_UNSPECIFIED = 0; + public static final int RTT_TYPE_ONE_SIDED = 1; + public static final int RTT_TYPE_TWO_SIDED = 2; - /** @deprecated It is not supported*/ + /** @deprecated It is not supported anymore. */ @Deprecated public static final int RTT_TYPE_11_V = 2; - public static final int RTT_TYPE_TWO_SIDED = 4; - /** @deprecated It is not supported*/ + /** @deprecated It is not supported anymore. */ @Deprecated public static final int RTT_TYPE_11_MC = 4; + /** @deprecated It is not supported anymore. */ + @Deprecated public static final int RTT_PEER_TYPE_UNSPECIFIED = 0; + public static final int RTT_PEER_TYPE_AP = 1; public static final int RTT_PEER_TYPE_STA = 2; /* requires NAN */ + public static final int RTT_PEER_P2P_GO = 3; + public static final int RTT_PEER_P2P_CLIENT = 4; + public static final int RTT_PEER_NAN = 5; + /** + * @deprecated It is not supported anymore. + * Use {@link android.net.wifi.RttManager#RTT_BW_20_SUPPORT} API. + */ + @Deprecated public static final int RTT_CHANNEL_WIDTH_20 = 0; + + /** + * @deprecated It is not supported anymore. + * Use {@link android.net.wifi.RttManager#RTT_BW_40_SUPPORT} API. + */ + @Deprecated public static final int RTT_CHANNEL_WIDTH_40 = 1; + + /** + * @deprecated It is not supported anymore. + * Use {@link android.net.wifi.RttManager#RTT_BW_80_SUPPORT} API. + */ + @Deprecated public static final int RTT_CHANNEL_WIDTH_80 = 2; + + /**@deprecated It is not supported anymore. + * Use {@link android.net.wifi.RttManager#RTT_BW_160_SUPPORT} API. + */ + @Deprecated public static final int RTT_CHANNEL_WIDTH_160 = 3; + + /**@deprecated not supported anymore*/ + @Deprecated public static final int RTT_CHANNEL_WIDTH_80P80 = 4; + + /**@deprecated It is not supported anymore. + * Use {@link android.net.wifi.RttManager#RTT_BW_5_SUPPORT} API. + */ + @Deprecated public static final int RTT_CHANNEL_WIDTH_5 = 5; + + /**@deprecated It is not supported anymore. + * Use {@link android.net.wifi.RttManager#RTT_BW_10_SUPPORT} API. + */ + @Deprecated public static final int RTT_CHANNEL_WIDTH_10 = 6; - /** @deprecated channel info must be specified*/ + /** @deprecated channel info must be specified. */ @Deprecated public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; public static final int RTT_STATUS_SUCCESS = 0; + /** General failure*/ public static final int RTT_STATUS_FAILURE = 1; + /** Destination does not respond to RTT request*/ public static final int RTT_STATUS_FAIL_NO_RSP = 2; + /** RTT request is rejected by the destination. Double side RTT only*/ public static final int RTT_STATUS_FAIL_REJECTED = 3; + /** */ public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; + /** Timing measurement timeout*/ public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5; + /** Destination is on a different channel from the RTT Request*/ public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; + /** This type of Ranging is not support by Hardware*/ public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7; + /** Request abort fro uncertain reason*/ public static final int RTT_STATUS_ABORTED = 8; - //if the T1-T4 or TOD/TOA Timestamp is illegal + /** The T1-T4 or TOD/TOA Timestamp is illegal*/ public static final int RTT_STATUS_FAIL_INVALID_TS = 9; - //11mc protocol failed, eg, unrecognized FTMR/FTM + /** 11mc protocol level failed, eg, unrecognized FTMR/FTM frame*/ public static final int RTT_STATUS_FAIL_PROTOCOL = 10; + /** Request can not be scheduled by hardware*/ public static final int RTT_STATUS_FAIL_SCHEDULE = 11; + /** destination is busy now, you can try after a specified time from destination*/ public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; + /** Bad Request argument*/ + public static final int RTT_STATUS_INVALID_REQ = 13; + /** Wifi is not enabled*/ + public static final int RTT_STATUS_NO_WIFI = 14; + /** Responder overrides param info, cannot range with new params 2-side RTT only*/ + public static final int RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15; public static final int REASON_UNSPECIFIED = -1; public static final int REASON_NOT_AVAILABLE = -2; @@ -80,30 +138,30 @@ public class RttManager { public static final String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description"; /** - * RTT BW supported bit mask + * RTT BW supported bit mask, used as RTT param bandWidth too */ - public static final int RTT_BW_5_SUPPORT = 0x1; - public static final int RTT_BW_10_SUPPORT = 0x2; - public static final int RTT_BW_20_SUPPORT = 0x4; - public static final int RTT_BW_40_SUPPORT = 0x8; + public static final int RTT_BW_5_SUPPORT = 0x01; + public static final int RTT_BW_10_SUPPORT = 0x02; + public static final int RTT_BW_20_SUPPORT = 0x04; + public static final int RTT_BW_40_SUPPORT = 0x08; public static final int RTT_BW_80_SUPPORT = 0x10; public static final int RTT_BW_160_SUPPORT = 0x20; /** * RTT Preamble Support bit mask */ - public static final int PREAMBLE_LEGACY = 0x1; - public static final int PREAMBLE_HT = 0x2; - public static final int PREAMBLE_VHT = 0x4; + public static final int PREAMBLE_LEGACY = 0x01; + public static final int PREAMBLE_HT = 0x02; + public static final int PREAMBLE_VHT = 0x04; - /** @deprecated It has been replaced by RttCapabilities*/ + /** @deprecated Use the new {@link android.net.wifi.RttManager.RttCapabilities} API */ @Deprecated public class Capabilities { public int supportedType; public int supportedPeerType; } - /** @deprecated It has been replaced by getRttCapabilities*/ + /** @deprecated Use the new {@link android.net.wifi.RttManager#getRttCapabilities()} API.*/ @Deprecated public Capabilities getCapabilities() { return new Capabilities(); @@ -241,28 +299,35 @@ public class RttManager { /** specifies parameters for RTT request */ public static class RttParams { /** - * type of destination device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA + * type of destination device being ranged + * currently only support RTT_PEER_TYPE_AP + * Range:RTT_PEER_TYPE_xxxx Default value:RTT_PEER_TYPE_AP */ public int deviceType; /** - * type of RTT measurement method; one of RTT_TYPE_ONE_SIDED or RTT_TYPE_TWO_SIDED. + * type of RTT measurement method. Need check scan result and RttCapabilities first + * Range: RTT_TYPE_ONE_SIDED or RTT_TYPE_TWO_SIDED + * Default value: RTT_TYPE_ONE_SIDED */ public int requestType; - /** mac address of the device being ranged */ + /** + * mac address of the device being ranged + * Default value: null + */ public String bssid; /** - * The primary 20 MHz frequency (in MHz) of the channel over which the client is - * communicating with the access point.Similar as ScanResult.frequency + * The primary control channel over which the client is + * communicating with the AP.Same as ScanResult.frequency + * Default value: 0 */ public int frequency; /** - * channel width used for RTT measurement. User need verify the highest BW the destination - * support (from scan result etc) before set this value. Wider channels result usually give - * better accuracy. However, the frame loss can increase. Similar as ScanResult.channelWidth + * channel width of the destination AP. Same as ScanResult.channelWidth + * Default value: 0 */ public int channelWidth; @@ -270,77 +335,113 @@ public class RttManager { * Not used if the AP bandwidth is 20 MHz * If the AP use 40, 80 or 160 MHz, this is the center frequency * if the AP use 80 + 80 MHz, this is the center frequency of the first segment - * similar as ScanResult.centerFreq0 + * same as ScanResult.centerFreq0 + * Default value: 0 */ public int centerFreq0; /** * Only used if the AP bandwidth is 80 + 80 MHz * if the AP use 80 + 80 MHz, this is the center frequency of the second segment - * similar as ScanResult.centerFreq1 + * same as ScanResult.centerFreq1 + * Default value: 0 */ public int centerFreq1; + /** * number of samples to be taken - * @deprecated It has been replaced by numSamplesPerBurst + * @deprecated Use the new {@link android.net.wifi.RttManager.RttParams#numSamplesPerBurst} */ @Deprecated public int num_samples; /** * number of retries if a sample fails - * @deprecated It has been replaced by numRetriesPerMeasurementFrame + * @deprecated + * Use {@link android.net.wifi.RttManager.RttParams#numRetriesPerMeasurementFrame} API. */ @Deprecated public int num_retries; - /** Number of burst. fixed to 1 for single side RTT*/ + /** Number of burst in exp , 2^x. 0 means single shot measurement, range 0-15 + * Currently only single shot is supported + * Default value: 0 + */ public int numberBurst; - /** valid only if numberBurst > 1, interval between burst(ms). Not used by singe side RTT */ + /** + * valid only if numberBurst > 1, interval between burst(100ms). + * Range : 0-31, 0--means no specific + * Default value: 0 + */ public int interval; - /** number of samples to be taken in one burst*/ + /** + * number of samples to be taken in one burst + * Range: 1-31 + * Default value: 8 + */ public int numSamplesPerBurst; /** number of retries for each measurement frame if a sample fails - * Only used by single side RTT + * Only used by single side RTT, + * Range 0 - 3 Default value: 0 */ public int numRetriesPerMeasurementFrame; - /** number of retries for FTMR frame if fails Only used by 80211MC double side RTT */ + /** + * number of retries for FTMR frame (control frame) if it fails. + * Only used by 80211MC double side RTT + * Range: 0-3 Default Value : 0 + */ public int numRetriesPerFTMR; - /** Request LCI information */ + /** + * Request LCI information, only available when choose double side RTT measurement + * need check RttCapabilties first. + * Default value: false + * */ public boolean LCIRequest; - /** Request LCR information */ + /** + * Request LCR information, only available when choose double side RTT measurement + * need check RttCapabilties first. + * Default value: false + * */ public boolean LCRRequest; - /** Timeout for each burst, unit of 250 us*/ + /** + * Timeout for each burst, (250 * 2^x) us, + * Range 1-11 and 15. 15 means no control Default value: 15 + * */ public int burstTimeout; /** preamble used for RTT measurement - * should be one of PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT + * Range: PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT + * Default value: PREAMBLE_HT */ public int preamble; /** bandWidth used for RTT measurement.User need verify the highest BW the destination * support (from scan result etc) before set this value. Wider channels result usually give * better accuracy. However, the frame loss can increase too. - * should be one of RTT_CHANNEL_WIDTH_20 to RTT_CHANNEL_WIDTH_80 + * should be one of RTT_BW_5_SUPPORT to RTT_BW_160_SUPPORT. However, need check + * RttCapabilities firstto verify HW support this bandwidth. + * Default value:RTT_BW_20_SUPPORT */ public int bandwidth; public RttParams() { //provide initial value for RttParams deviceType = RTT_PEER_TYPE_AP; - numberBurst = 1; + requestType = RTT_TYPE_ONE_SIDED; + numberBurst = 0; numSamplesPerBurst = 8; numRetriesPerMeasurementFrame = 0; - burstTimeout = 40 + numSamplesPerBurst *4; - preamble = PREAMBLE_LEGACY; - bandwidth = RTT_CHANNEL_WIDTH_20; + numRetriesPerFTMR = 0; + burstTimeout = 15; + preamble = PREAMBLE_HT; + bandwidth = RTT_BW_20_SUPPORT; } } @@ -430,26 +531,29 @@ public class RttManager { }; } - public class wifiInformationElement { - /** Information Element ID*/ - public int id; - public String data; + public static class WifiInformationElement { + /** Information Element ID 0xFF means element is invalid. */ + public byte id; + public byte[] data; } /** specifies RTT results */ public static class RttResult { - /** mac address of the device being ranged */ + /** mac address of the device being ranged. */ public String bssid; - /** # of burst for this measurement*/ + /** # of burst for this measurement. */ public int burstNumber; - /** total number of measurement frames in this measurement*/ + /** total number of measurement frames attempted in this measurement. */ public int measurementFrameNumber; - /** total successful number of measurement frames in this measurement*/ + /** total successful number of measurement frames in this measurement. */ public int successMeasurementFrameNumber; - /** Maximum number of frames per burst supported by peer */ + /** + * Maximum number of frames per burst supported by peer. Two side RTT only + * Valid only if less than request + */ public int frameNumberPerBurstPeer; /** status of the request */ @@ -457,120 +561,128 @@ public class RttManager { /** * type of the request used - * @deprecated It has been replaced by measurementType + * @deprecated Use {@link android.net.wifi.RttManager.RttResult#measurementType} */ @Deprecated public int requestType; - /** RTT measurement method type used, shoudl be one of RTT_TYPE_ONE_SIDED or + /** RTT measurement method type used, should be one of RTT_TYPE_ONE_SIDED or * RTT_TYPE_TWO_SIDED. */ public int measurementType; - /** please retry RTT measurement after this S since peer indicate busy at ths moment*/ + /** + * only valid when status == RTT_STATUS_FAIL_BUSY_TRY_LATER + * please retry RTT measurement after this duration since peer indicate busy at ths moment + * Unit S Range:1-31 + */ public int retryAfterDuration; - /** timestamp of completion, in microsecond since boot */ + /** timestamp of completion, in microsecond since boot. */ public long ts; - /** average RSSI observed, unit of 0.5 dB */ + /** average RSSI observed, unit of 0.5 dB. */ public int rssi; /** * RSSI spread (i.e. max - min) - * @deprecated It has been replaced by rssi_spread + * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rssiSpread} API. */ @Deprecated public int rssi_spread; - /**RSSI spread (i.e. max - min), unit of 0.5 dB */ + /**RSSI spread (i.e. max - min), unit of 0.5 dB. */ public int rssiSpread; /** * average transmit rate - * @deprecated It has been replaced by txRate + * @deprecated Use {@link android.net.wifi.RttManager.RttResult#txRate} API. */ @Deprecated public int tx_rate; - /** average transmit rate */ + /** average transmit rate. Unit (100kbps). */ public int txRate; - /** average receiving rate */ + /** average receiving rate Unit (100kbps). */ public int rxRate; /** * average round trip time in nano second - * @deprecated It has been replaced by rtt + * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rtt} API. */ @Deprecated public long rtt_ns; - /** average round trip time in 0.1 nano second */ + /** average round trip time in 0.1 nano second. */ public long rtt; /** * standard deviation observed in round trip time - * @deprecated It has been replaced by rttStandardDeviation + * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rttStandardDeviation} API. */ @Deprecated public long rtt_sd_ns; - /** standard deviation of RTT in 0.1 ns */ + /** standard deviation of RTT in 0.1 ns. */ public long rttStandardDeviation; /** * spread (i.e. max - min) round trip time - * @deprecated It has been replaced by rttSpread + * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rttSpread} API. */ @Deprecated public long rtt_spread_ns; - /** spread (i.e. max - min) RTT in 0.1 ns */ + /** spread (i.e. max - min) RTT in 0.1 ns. */ public long rttSpread; /** * average distance in centimeter, computed based on rtt_ns - * @deprecated It has been replaced by distance + * @deprecated use {@link android.net.wifi.RttManager.RttResult#distance} API. */ @Deprecated public int distance_cm; - /** average distance in cm, computed based on rtt */ + /** average distance in cm, computed based on rtt. */ public int distance; /** * standard deviation observed in distance - * @deprecated It has been replaced with distanceStandardDeviation + * @deprecated + * Use {@link .android.net.wifi.RttManager.RttResult#distanceStandardDeviation} API. */ @Deprecated public int distance_sd_cm; - /** standard deviation observed in distance in cm*/ + /** standard deviation observed in distance in cm. */ public int distanceStandardDeviation; /** * spread (i.e. max - min) distance - * @deprecated It has been replaced by distanceSpread + * @deprecate Use {@link android.net.wifi.RttManager.RttResult#distanceSpread} API. */ @Deprecated public int distance_spread_cm; - /** spread (i.e. max - min) distance in cm */ + /** spread (i.e. max - min) distance in cm. */ public int distanceSpread; - /** the duration of this measurement burst*/ + /** the duration of this measurement burst, unit ms. */ public int burstDuration; - /** LCI information Element*/ - wifiInformationElement LCI; + /** Burst number supported by peer after negotiation, 2side RTT only*/ + public int negotiatedBurstNum; + + /** LCI information Element, only available for double side RTT. */ + public WifiInformationElement LCI; - /** LCR information Element*/ - wifiInformationElement LCR; + /** LCR information Element, only available to double side RTT. */ + public WifiInformationElement LCR; } - /** pseudo-private class used to parcel results */ + /** pseudo-private class used to parcel results. */ public static class ParcelableRttResults implements Parcelable { public RttResult mResults[]; @@ -608,10 +720,17 @@ public class RttManager { dest.writeInt(result.distanceStandardDeviation); dest.writeInt(result.distanceSpread); dest.writeInt(result.burstDuration); - //dest.writeInt(result.LCI.id); - //dest.writeString(result.LCI.data); - //dest.writeInt(result.LCR.id); - //dest.writeString(result.LCR.data); + dest.writeInt(result.negotiatedBurstNum); + dest.writeByte(result.LCI.id); + if (result.LCI.id != (byte) 0xFF) { + dest.writeByte((byte)result.LCI.data.length); + dest.writeByteArray(result.LCI.data); + } + dest.writeByte(result.LCR.id); + if (result.LCR.id != (byte) 0xFF) { + dest.writeInt((byte) result.LCR.data.length); + dest.writeByte(result.LCR.id); + } } } else { dest.writeInt(0); @@ -651,10 +770,21 @@ public class RttManager { results[i].distanceStandardDeviation = in.readInt(); results[i].distanceSpread = in.readInt(); results[i].burstDuration = in.readInt(); - //results[i].LCI.id = in.readInt(); - //results[i].LCI.data = in.readString(); - //results[i].LCR.id = in.readInt(); - //results[i].LCR.data = in.readString(); + results[i].negotiatedBurstNum = in.readInt(); + results[i].LCI = new WifiInformationElement(); + results[i].LCI.id = in.readByte(); + if (results[i].LCI.id != (byte) 0xFF) { + byte length = in.readByte(); + results[i].LCI.data = new byte[length]; + in.readByteArray(results[i].LCI.data); + } + results[i].LCR = new WifiInformationElement(); + results[i].LCR.id = in.readByte(); + if (results[i].LCR.id != (byte) 0xFF) { + byte length = in.readByte(); + results[i].LCR.data = new byte[length]; + in.readByteArray(results[i].LCR.data); + } } ParcelableRttResults parcelableResults = new ParcelableRttResults(results); @@ -696,18 +826,24 @@ public class RttManager { !mRttCapabilities.twoSided11McRttSupported) { Log.e(TAG, "Request " + index + ": two side RTT is not supported"); return false; - } else if ( params.numberBurst <= 0 ) { + } else if(params.bssid == null || params.bssid.isEmpty()) { + Log.e(TAG,"No BSSID is input"); + } else if ( params.numberBurst != 0 ) { Log.e(TAG, "Request " + index + ": Illegal number of burst: " + params.numberBurst); return false; - } else if (params.numberBurst > 1 && params.interval <= 0) { - Log.e(TAG, "Request " + index + ": Illegal interval value: " + params.interval); - return false; - } else if (params.numSamplesPerBurst <= 0) { + } else if (params.numSamplesPerBurst <= 0 || params.numSamplesPerBurst > 31) { Log.e(TAG, "Request " + index + ": Illegal sample number per burst: " + params.numSamplesPerBurst); return false; - } else if (params.numRetriesPerMeasurementFrame < 0 || params.numRetriesPerFTMR < 0) { - Log.e(TAG, "Request " + index + ": Illegal retry number"); + } else if (params.numRetriesPerMeasurementFrame < 0 || + params.numRetriesPerMeasurementFrame > 3) { + Log.e(TAG, "Request " + index + ": Illegal measurement frame retry number:" + + params.numRetriesPerMeasurementFrame); + return false; + } else if(params.numRetriesPerFTMR < 0 || + params.numRetriesPerFTMR > 3) { + Log.e(TAG, "Request " + index + ": Illegal FTMR frame retry number:" + + params.numRetriesPerFTMR); return false; } else if (params.LCIRequest && !mRttCapabilities.lciSupported) { Log.e(TAG, "Request " + index + ": LCI is not supported"); @@ -715,7 +851,8 @@ public class RttManager { } else if (params.LCRRequest && !mRttCapabilities.lcrSupported) { Log.e(TAG, "Request " + index + ": LCR is not supported"); return false; - } else if (params.burstTimeout <= 0){ + } else if (params.burstTimeout < 1 || + (params.burstTimeout > 11 && params.burstTimeout != 15)){ Log.e(TAG, "Request " + index + ": Illegal burst timeout: " + params.burstTimeout); return false; } else if ((params.preamble & mRttCapabilities.preambleSupported) == 0) { diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 9cb6f2e..6ea0db2 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -25,6 +25,7 @@ import android.net.StaticIpConfiguration; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.util.Log; import java.util.HashMap; import java.util.BitSet; @@ -910,41 +911,52 @@ public class WifiConfiguration implements Parcelable { * @hide */ public boolean isValid() { + String reason = strIsValid(); + if (reason != null) { + Log.e("WFII", "WiFi Config not valid: " + reason); + return false; + } + else { + return true; + } + } + + private String strIsValid() { if (allowedKeyManagement == null) - return false; + return "allowed kmgmt"; if (allowedKeyManagement.cardinality() > 1) { if (allowedKeyManagement.cardinality() != 2) { - return false; + return "cardinality != 2"; } - if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) == false) { - return false; + if (!allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { + return "not WPA_EAP"; } - if ((allowedKeyManagement.get(KeyMgmt.IEEE8021X) == false) - && (allowedKeyManagement.get(KeyMgmt.WPA_PSK) == false)) { - return false; + if ((!allowedKeyManagement.get(KeyMgmt.IEEE8021X)) + && (!allowedKeyManagement.get(KeyMgmt.WPA_PSK))) { + return "not PSK or 8021X"; } } - if (TextUtils.isEmpty(FQDN) == false) { + if (!TextUtils.isEmpty(FQDN)) { /* this is passpoint configuration; it must not have an SSID */ - if (TextUtils.isEmpty(SSID) == false) { - return false; + if (!TextUtils.isEmpty(SSID)) { + return "no SSID"; } /* this is passpoint configuration; it must have a providerFriendlyName */ if (TextUtils.isEmpty(providerFriendlyName)) { - return false; + return "no provider friendly name"; } /* this is passpoint configuration; it must have enterprise config */ if (enterpriseConfig == null || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE ) { - return false; + return "no enterprise config"; } } // TODO: Add more checks - return true; + return null; } /** diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 275c7d1..4e4f9b2 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -645,6 +645,20 @@ public class WifiManager { } /** + * Returns a WifiConfiguration matching this ScanResult + * @param scanResult scanResult that represents the BSSID + * @return {@link WifiConfiguration} that matches this BSSID or null + * @hide + */ + public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) { + try { + return mService.getMatchingWifiConfig(scanResult); + } catch (RemoteException e) { + return null; + } + } + + /** * Add a new network description to the set of configured networks. * The {@code networkId} field of the supplied configuration object * is ignored. @@ -1488,6 +1502,20 @@ public class WifiManager { } /** + * Builds a WifiConfiguration from Hotspot 2.0 MIME file. + * @return AP details in WifiConfiguration + * + * @hide Dont open yet + */ + public WifiConfiguration buildWifiConfig(String uriString, String mimeType, byte[] data) { + try { + return mService.buildWifiConfig(uriString, mimeType, data); + } catch (RemoteException e) { + return null; + } + } + + /** * Sets the Wi-Fi AP Configuration. * @return {@code true} if the operation succeeded, {@code false} otherwise * |