Merge "Migrate primary external storage."
diff --git a/api/current.txt b/api/current.txt
index 8216304..578f808 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18299,17 +18299,18 @@
method public boolean bindProcessToNetwork(android.net.Network);
method public android.net.Network getActiveNetwork();
method public android.net.NetworkInfo getActiveNetworkInfo();
- method public android.net.NetworkInfo[] getAllNetworkInfo();
+ method public deprecated 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 deprecated android.net.NetworkInfo getNetworkInfo(int);
method public android.net.NetworkInfo getNetworkInfo(android.net.Network);
method public deprecated int getNetworkPreference();
method public static deprecated android.net.Network getProcessDefaultNetwork();
+ method public void ignoreNetworkWithCaptivePortal(android.net.Network, java.lang.String);
method public boolean isActiveNetworkMetered();
method public boolean isDefaultNetworkActive();
method public static boolean isNetworkTypeValid(int);
@@ -18317,6 +18318,7 @@
method public void releaseNetworkRequest(android.app.PendingIntent);
method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public deprecated void reportBadNetwork(android.net.Network);
+ method public void reportCaptivePortalDismissed(android.net.Network, java.lang.String);
method public void reportNetworkConnectivity(android.net.Network, boolean);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
@@ -18324,8 +18326,10 @@
method public static deprecated boolean setProcessDefaultNetwork(android.net.Network);
method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
+ field public static final java.lang.String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
+ field public static final java.lang.String EXTRA_CAPTIVE_PORTAL_TOKEN = "captivePortalToken";
field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
@@ -19286,8 +19290,6 @@
field public java.util.BitSet allowedKeyManagement;
field public java.util.BitSet allowedPairwiseCiphers;
field public java.util.BitSet allowedProtocols;
- field public int apBand;
- field public int apChannel;
field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
field public boolean hiddenSSID;
field public int networkId;
@@ -19356,6 +19358,7 @@
method public java.lang.String getAnonymousIdentity();
method public java.security.cert.X509Certificate getCaCertificate();
method public java.security.cert.X509Certificate getClientCertificate();
+ method public java.lang.String getDomainSubjectMatch();
method public int getEapMethod();
method public java.lang.String getIdentity();
method public java.lang.String getPassword();
@@ -19367,6 +19370,7 @@
method public void setAnonymousIdentity(java.lang.String);
method public void setCaCertificate(java.security.cert.X509Certificate);
method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
+ method public void setDomainSuffixMatch(java.lang.String);
method public void setEapMethod(int);
method public void setIdentity(java.lang.String);
method public void setPassword(java.lang.String);
@@ -30218,6 +30222,7 @@
method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle();
method public android.telecom.Connection getPrimaryConnection();
method public final int getState();
+ method public final android.telecom.StatusHints getStatusHints();
method public void onAudioStateChanged(android.telecom.AudioState);
method public void onConnectionAdded(android.telecom.Connection);
method public void onDisconnect();
@@ -30236,6 +30241,7 @@
method public final void setConnectionCapabilities(int);
method public final void setDisconnected(android.telecom.DisconnectCause);
method public final void setOnHold();
+ method public final void setStatusHints(android.telecom.StatusHints);
field public static final long CONNECT_TIME_NOT_SPECIFIED = 0L; // 0x0L
}
@@ -30426,6 +30432,7 @@
public static abstract class InCallService.VideoCall {
ctor public InCallService.VideoCall();
method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback);
+ method public abstract void unregisterCallback();
method public abstract void requestCallDataUsage();
method public abstract void requestCameraCapabilities();
method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile);
diff --git a/api/system-current.txt b/api/system-current.txt
index 09d32da..2ea68c6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -19758,17 +19758,18 @@
method public boolean bindProcessToNetwork(android.net.Network);
method public android.net.Network getActiveNetwork();
method public android.net.NetworkInfo getActiveNetworkInfo();
- method public android.net.NetworkInfo[] getAllNetworkInfo();
+ method public deprecated 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 deprecated android.net.NetworkInfo getNetworkInfo(int);
method public android.net.NetworkInfo getNetworkInfo(android.net.Network);
method public deprecated int getNetworkPreference();
method public static deprecated android.net.Network getProcessDefaultNetwork();
+ method public void ignoreNetworkWithCaptivePortal(android.net.Network, java.lang.String);
method public boolean isActiveNetworkMetered();
method public boolean isDefaultNetworkActive();
method public static boolean isNetworkTypeValid(int);
@@ -19776,6 +19777,7 @@
method public void releaseNetworkRequest(android.app.PendingIntent);
method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public deprecated void reportBadNetwork(android.net.Network);
+ method public void reportCaptivePortalDismissed(android.net.Network, java.lang.String);
method public void reportNetworkConnectivity(android.net.Network, boolean);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
@@ -19783,8 +19785,10 @@
method public static deprecated boolean setProcessDefaultNetwork(android.net.Network);
method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
+ field public static final java.lang.String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
+ field public static final java.lang.String EXTRA_CAPTIVE_PORTAL_TOKEN = "captivePortalToken";
field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
@@ -20985,8 +20989,6 @@
field public java.util.BitSet allowedKeyManagement;
field public java.util.BitSet allowedPairwiseCiphers;
field public java.util.BitSet allowedProtocols;
- field public int apBand;
- field public int apChannel;
field public java.lang.String creatorName;
field public int creatorUid;
field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
@@ -21077,6 +21079,7 @@
method public java.lang.String getAnonymousIdentity();
method public java.security.cert.X509Certificate getCaCertificate();
method public java.security.cert.X509Certificate getClientCertificate();
+ method public java.lang.String getDomainSubjectMatch();
method public int getEapMethod();
method public java.lang.String getIdentity();
method public java.lang.String getPassword();
@@ -21088,6 +21091,7 @@
method public void setAnonymousIdentity(java.lang.String);
method public void setCaCertificate(java.security.cert.X509Certificate);
method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
+ method public void setDomainSuffixMatch(java.lang.String);
method public void setEapMethod(int);
method public void setIdentity(java.lang.String);
method public void setPassword(java.lang.String);
@@ -32329,6 +32333,7 @@
method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle();
method public android.telecom.Connection getPrimaryConnection();
method public final int getState();
+ method public final android.telecom.StatusHints getStatusHints();
method public void onAudioStateChanged(android.telecom.AudioState);
method public void onConnectionAdded(android.telecom.Connection);
method public void onDisconnect();
@@ -32347,6 +32352,7 @@
method public final void setConnectionCapabilities(int);
method public final void setDisconnected(android.telecom.DisconnectCause);
method public final void setOnHold();
+ method public final void setStatusHints(android.telecom.StatusHints);
field public static final long CONNECT_TIME_NOT_SPECIFIED = 0L; // 0x0L
}
@@ -32540,6 +32546,7 @@
public static abstract class InCallService.VideoCall {
ctor public InCallService.VideoCall();
method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback);
+ method public abstract void unregisterCallback();
method public abstract void requestCallDataUsage();
method public abstract void requestCameraCapabilities();
method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 79e560f..d4e79be 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -121,6 +121,9 @@
* {@link #STATE_TURNING_ON},
* {@link #STATE_ON},
* {@link #STATE_TURNING_OFF},
+ * {@link #STATE_BLE_TURNING_ON},
+ * {@link #STATE_BLE_ON},
+ * {@link #STATE_BLE_TURNING_OFF},
*/
public static final String EXTRA_STATE =
"android.bluetooth.adapter.extra.STATE";
@@ -130,7 +133,7 @@
* {@link #STATE_OFF},
* {@link #STATE_TURNING_ON},
* {@link #STATE_ON},
- * {@link #STATE_TURNING_OFF},
+ * {@link #STATE_TURNING_OFF}
*/
public static final String EXTRA_PREVIOUS_STATE =
"android.bluetooth.adapter.extra.PREVIOUS_STATE";
@@ -1301,9 +1304,12 @@
public boolean isHardwareTrackingFiltersAvailable() {
if (getState() != STATE_ON) return false;
try {
- synchronized(mManagerCallback) {
- if(mService != null) return (mService.numOfHwTrackFiltersAvailable() != 0);
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported
+ return false;
}
+ return (iGatt.numHwTrackFiltersAvailable() != 0);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
diff --git a/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
index cdb24f4..01778b3 100644
--- a/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
+++ b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
@@ -123,4 +123,7 @@
public void onFoundOrLost(boolean onFound, ScanResult scanResult) throws RemoteException {
}
+ @Override
+ public void onScanManagerErrorCallback(int errorCode) throws RemoteException {
+ }
}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index f6001bf..a3eceb5 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -100,7 +100,6 @@
boolean isActivityAndEnergyReportingSupported();
void getActivityEnergyInfoFromController();
BluetoothActivityEnergyInfo reportActivityInfo();
- int numOfHwTrackFiltersAvailable();
// for dumpsys support
String dump();
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 4ca57f8..72abeaf 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -103,4 +103,5 @@
in boolean confirm, in byte[] value);
void disconnectAll();
void unregAll();
+ int numHwTrackFiltersAvailable();
}
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index 91e62ea..cbba9f0 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -67,6 +67,7 @@
void onReadRemoteRssi(in String address, in int rssi, in int status);
void onMultiAdvertiseCallback(in int status, boolean isStart,
in AdvertiseSettings advertiseSettings);
+ void onScanManagerErrorCallback(in int errorCode);
void onConfigureMTU(in String address, in int mtu, in int status);
void onFoundOrLost(in boolean onFound, in ScanResult scanResult);
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 3078951..687bd5d 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -381,6 +381,18 @@
}
});
}
+
+ @Override
+ public void onScanManagerErrorCallback(final int errorCode) {
+ if (VDBG) {
+ Log.d(TAG, "onScanManagerErrorCallback() - errorCode = " + errorCode);
+ }
+ synchronized (this) {
+ if (mClientIf <= 0)
+ return;
+ }
+ postCallbackError(mScanCallback, errorCode);
+ }
}
private void postCallbackError(final ScanCallback callback, final int errorCode) {
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 691798f..a4d6be09 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -326,6 +326,9 @@
}
try {
+ startPreview(); // If preview is not running (i.e. after a JPEG capture), we need to
+ // explicitely start and stop preview before setting preview surface.
+ // null.
stopPreview();
} catch (RuntimeException e) {
Log.e(TAG, "Received device exception in configure call: ", e);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 63f48cf..c531e7e 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -98,13 +98,41 @@
public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
/**
+ * The device has connected to a network that has presented a captive
+ * portal, which is blocking Internet connectivity. The user was presented
+ * with a notification that network sign in is required,
+ * and the user invoked the notification's action indicating they
+ * desire to sign in to the network. Apps handling this action should
+ * facilitate signing in to the network. This action includes a
+ * {@link Network} typed extra called {@link #EXTRA_NETWORK} that represents
+ * the network presenting the captive portal; all communication with the
+ * captive portal must be done using this {@code Network} object.
+ * <p/>
+ * When the app handling this action believes the user has signed in to
+ * the network and the captive portal has been dismissed, the app should call
+ * {@link #reportCaptivePortalDismissed} so the system can reevaluate the network.
+ * If reevaluation finds the network no longer subject to a captive portal,
+ * the network may become the default active data network.
+ * <p/>
+ * When the app handling this action believes the user explicitly wants
+ * to ignore the captive portal and the network, the app should call
+ * {@link #ignoreNetworkWithCaptivePortal}.
+ * <p/>
+ * Note that this action includes a {@code String} extra named
+ * {@link #EXTRA_CAPTIVE_PORTAL_TOKEN} that must
+ * be passed in to {@link #reportCaptivePortalDismissed} and
+ * {@link #ignoreNetworkWithCaptivePortal}.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
+
+ /**
* The lookup key for a {@link NetworkInfo} object. Retrieve with
* {@link android.content.Intent#getParcelableExtra(String)}.
*
* @deprecated Since {@link NetworkInfo} can vary based on UID, applications
* should always obtain network information through
- * {@link #getActiveNetworkInfo()} or
- * {@link #getAllNetworkInfo()}.
+ * {@link #getActiveNetworkInfo()}.
* @see #EXTRA_NETWORK_TYPE
*/
@Deprecated
@@ -112,8 +140,6 @@
/**
* Network type which triggered a {@link #CONNECTIVITY_ACTION} broadcast.
- * Can be used with {@link #getNetworkInfo(int)} to get {@link NetworkInfo}
- * state based on the calling application.
*
* @see android.content.Intent#getIntExtra(String, int)
*/
@@ -163,6 +189,15 @@
public static final String EXTRA_INET_CONDITION = "inetCondition";
/**
+ * The lookup key for a string that is sent out with
+ * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN}. This string must be
+ * passed in to {@link #reportCaptivePortalDismissed} and
+ * {@link #ignoreNetworkWithCaptivePortal}. Retrieve it with
+ * {@link android.content.Intent#getStringExtra(String)}.
+ */
+ public static final String EXTRA_CAPTIVE_PORTAL_TOKEN = "captivePortalToken";
+
+ /**
* Broadcast action to indicate the change of data activity status
* (idle or active) on a network in a recent period.
* The network becomes active when data transmission is started, or
@@ -660,6 +695,10 @@
*
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ *
+ * @deprecated This method does not support multiple connected networks
+ * of the same type. Use {@link #getAllNetworks} and
+ * {@link #getNetworkInfo(android.net.Network)} instead.
*/
public NetworkInfo getNetworkInfo(int networkType) {
try {
@@ -699,6 +738,10 @@
*
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ *
+ * @deprecated This method does not support multiple connected networks
+ * of the same type. Use {@link #getAllNetworks} and
+ * {@link #getNetworkInfo(android.net.Network)} instead.
*/
public NetworkInfo[] getAllNetworkInfo() {
try {
@@ -716,6 +759,9 @@
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
*
* @hide
+ * @deprecated This method does not support multiple connected networks
+ * of the same type. Use {@link #getAllNetworks} and
+ * {@link #getNetworkInfo(android.net.Network)} instead.
*/
public Network getNetworkForType(int networkType) {
try {
@@ -808,6 +854,10 @@
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
* {@hide}
+ * @deprecated This method does not support multiple connected networks
+ * of the same type. Use {@link #getAllNetworks},
+ * {@link #getNetworkInfo(android.net.Network)}, and
+ * {@link #getLinkProperties(android.net.Network)} instead.
*/
public LinkProperties getLinkProperties(int networkType) {
try {
@@ -1748,6 +1798,82 @@
}
}
+ /** {@hide} */
+ public static final int CAPTIVE_PORTAL_APP_RETURN_DISMISSED = 0;
+ /** {@hide} */
+ public static final int CAPTIVE_PORTAL_APP_RETURN_UNWANTED = 1;
+ /** {@hide} */
+ public static final int CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS = 2;
+
+ /**
+ * Called by an app handling the {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN}
+ * action to indicate to the system that the captive portal has been
+ * dismissed. In response the framework will re-evaluate the network's
+ * connectivity and might take further action thereafter.
+ *
+ * @param network The {@link Network} object passed via
+ * {@link #EXTRA_NETWORK} with the
+ * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN} action.
+ * @param actionToken The {@code String} passed via
+ * {@link #EXTRA_CAPTIVE_PORTAL_TOKEN} with the
+ * {@code ACTION_CAPTIVE_PORTAL_SIGN_IN} action.
+ */
+ public void reportCaptivePortalDismissed(Network network, String actionToken) {
+ try {
+ mService.captivePortalAppResponse(network, CAPTIVE_PORTAL_APP_RETURN_DISMISSED,
+ actionToken);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Called by an app handling the {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN}
+ * action to indicate that the user does not want to pursue signing in to
+ * captive portal and the system should continue to prefer other networks
+ * without captive portals for use as the default active data network. The
+ * system will not retest the network for a captive portal so as to avoid
+ * disturbing the user with further sign in to network notifications.
+ *
+ * @param network The {@link Network} object passed via
+ * {@link #EXTRA_NETWORK} with the
+ * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN} action.
+ * @param actionToken The {@code String} passed via
+ * {@link #EXTRA_CAPTIVE_PORTAL_TOKEN} with the
+ * {@code ACTION_CAPTIVE_PORTAL_SIGN_IN} action.
+ */
+ public void ignoreNetworkWithCaptivePortal(Network network, String actionToken) {
+ try {
+ mService.captivePortalAppResponse(network, CAPTIVE_PORTAL_APP_RETURN_UNWANTED,
+ actionToken);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Called by an app handling the {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN}
+ * action to indicate the user wants to use this network as is, even though
+ * the captive portal is still in place. The system will treat the network
+ * as if it did not have a captive portal when selecting the network to use
+ * as the default active data network. This may result in this network
+ * becoming the default active data network, which could disrupt network
+ * connectivity for apps because the captive portal is still in place.
+ *
+ * @param network The {@link Network} object passed via
+ * {@link #EXTRA_NETWORK} with the
+ * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN} action.
+ * @param actionToken The {@code String} passed via
+ * {@link #EXTRA_CAPTIVE_PORTAL_TOKEN} with the
+ * {@code ACTION_CAPTIVE_PORTAL_SIGN_IN} action.
+ * @hide
+ */
+ public void useNetworkWithCaptivePortal(Network network, String actionToken) {
+ try {
+ mService.captivePortalAppResponse(network, CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS,
+ actionToken);
+ } catch (RemoteException e) {
+ }
+ }
+
/**
* Set a network-independent global http proxy. This is not normally what you want
* for typical HTTP proxies - they are general network dependent. However if you're
@@ -1941,6 +2067,7 @@
* @param networkType
*
* {@hide}
+ * @deprecated Doesn't properly deal with multiple connected networks of the same type.
*/
public void setProvisioningNotificationVisible(boolean visible, int networkType,
String action) {
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index efc76b3..77200a5 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -98,6 +98,8 @@
void reportNetworkConnectivity(in Network network, boolean hasConnectivity);
+ void captivePortalAppResponse(in Network network, int response, String actionToken);
+
ProxyInfo getGlobalProxy();
void setGlobalProxy(in ProxyInfo p);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f430eb5..018c1a1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -212,6 +212,7 @@
<protected-broadcast android:name="android.intent.action.MEDIA_UNMOUNTABLE" />
<protected-broadcast android:name="android.intent.action.MEDIA_EJECT" />
+ <protected-broadcast android:name="android.net.conn.CAPTIVE_PORTAL" />
<protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<!-- @deprecated. Only {@link android.net.ConnectivityManager.CONNECTIVITY_ACTION} is sent. -->
<protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" />
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 2ec15be..aea8585 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -21,6 +21,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<application android:label="@string/app_name" >
<activity
@@ -28,9 +29,8 @@
android:label="@string/action_bar_label"
android:theme="@style/AppTheme" >
<intent-filter>
- <action android:name="android.intent.action.ACTION_SEND"/>
+ <action android:name="android.net.conn.CAPTIVE_PORTAL"/>
<category android:name="android.intent.category.DEFAULT"/>
- <data android:mimeType="text/plain"/>
</intent-filter>
</activity>
</application>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index e4054ac..b86fc4b 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -56,24 +56,13 @@
private static final String DEFAULT_SERVER = "connectivitycheck.android.com";
private static final int SOCKET_TIMEOUT_MS = 10000;
- // Keep this in sync with NetworkMonitor.
- // Intent broadcast to ConnectivityService indicating sign-in is complete.
- // Extras:
- // EXTRA_TEXT = netId
- // LOGGED_IN_RESULT = one of the CAPTIVE_PORTAL_APP_RETURN_* values below.
- // RESPONSE_TOKEN = data fragment from launching Intent
- private static final String ACTION_CAPTIVE_PORTAL_LOGGED_IN =
- "android.net.netmon.captive_portal_logged_in";
- private static final String LOGGED_IN_RESULT = "result";
- private static final int CAPTIVE_PORTAL_APP_RETURN_APPEASED = 0;
- private static final int CAPTIVE_PORTAL_APP_RETURN_UNWANTED = 1;
- private static final int CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS = 2;
- private static final String RESPONSE_TOKEN = "response_token";
+ private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS };
private URL mURL;
- private int mNetId;
+ private Network mNetwork;
private String mResponseToken;
private NetworkCallback mNetworkCallback;
+ private ConnectivityManager mCm;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -81,23 +70,19 @@
String server = Settings.Global.getString(getContentResolver(), "captive_portal_server");
if (server == null) server = DEFAULT_SERVER;
+ mCm = ConnectivityManager.from(this);
try {
mURL = new URL("http", server, "/generate_204");
- final Uri dataUri = getIntent().getData();
- if (!dataUri.getScheme().equals("netid")) {
- throw new MalformedURLException();
- }
- mNetId = Integer.parseInt(dataUri.getSchemeSpecificPart());
- mResponseToken = dataUri.getFragment();
- } catch (MalformedURLException|NumberFormatException e) {
+ } catch (MalformedURLException e) {
// System misconfigured, bail out in a way that at least provides network access.
- done(CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS);
+ Log.e(TAG, "Invalid captive portal URL, server=" + server);
+ done(Result.WANTED_AS_IS);
}
+ mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
+ mResponseToken = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_TOKEN);
- final ConnectivityManager cm = ConnectivityManager.from(this);
- final Network network = new Network(mNetId);
// Also initializes proxy system properties.
- cm.bindProcessToNetwork(network);
+ mCm.bindProcessToNetwork(mNetwork);
// Proxy system properties must be initialized before setContentView is called because
// setContentView initializes the WebView logic which in turn reads the system properties.
@@ -106,7 +91,7 @@
getActionBar().setDisplayShowHomeEnabled(false);
// Exit app if Network disappears.
- final NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(network);
+ final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork);
if (networkCapabilities == null) {
finish();
return;
@@ -114,14 +99,14 @@
mNetworkCallback = new NetworkCallback() {
@Override
public void onLost(Network lostNetwork) {
- if (network.equals(lostNetwork)) done(CAPTIVE_PORTAL_APP_RETURN_UNWANTED);
+ if (mNetwork.equals(lostNetwork)) done(Result.UNWANTED);
}
};
final NetworkRequest.Builder builder = new NetworkRequest.Builder();
for (int transportType : networkCapabilities.getTransportTypes()) {
builder.addTransportType(transportType);
}
- cm.registerNetworkCallback(builder.build(), mNetworkCallback);
+ mCm.registerNetworkCallback(builder.build(), mNetworkCallback);
final WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.clearCache(true);
@@ -158,15 +143,21 @@
}
}
- private void done(int result) {
+ private void done(Result result) {
if (mNetworkCallback != null) {
- ConnectivityManager.from(this).unregisterNetworkCallback(mNetworkCallback);
+ mCm.unregisterNetworkCallback(mNetworkCallback);
}
- Intent intent = new Intent(ACTION_CAPTIVE_PORTAL_LOGGED_IN);
- intent.putExtra(Intent.EXTRA_TEXT, String.valueOf(mNetId));
- intent.putExtra(LOGGED_IN_RESULT, String.valueOf(result));
- intent.putExtra(RESPONSE_TOKEN, mResponseToken);
- sendBroadcast(intent);
+ switch (result) {
+ case DISMISSED:
+ mCm.reportCaptivePortalDismissed(mNetwork, mResponseToken);
+ break;
+ case UNWANTED:
+ mCm.ignoreNetworkWithCaptivePortal(mNetwork, mResponseToken);
+ break;
+ case WANTED_AS_IS:
+ mCm.useNetworkWithCaptivePortal(mNetwork, mResponseToken);
+ break;
+ }
finish();
}
@@ -190,11 +181,11 @@
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_use_network) {
- done(CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS);
+ done(Result.WANTED_AS_IS);
return true;
}
if (id == R.id.action_do_not_use_network) {
- done(CAPTIVE_PORTAL_APP_RETURN_UNWANTED);
+ done(Result.UNWANTED);
return true;
}
return super.onOptionsItemSelected(item);
@@ -223,7 +214,7 @@
if (urlConnection != null) urlConnection.disconnect();
}
if (httpResponseCode == 204) {
- done(CAPTIVE_PORTAL_APP_RETURN_APPEASED);
+ done(Result.DISMISSED);
}
}
}).start();
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 3e5eee8..ef82bb7 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -56,6 +56,7 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.*;
class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String TAG = "BluetoothManagerService";
private static final boolean DBG = true;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 7d8e9de..12a99b0 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2608,6 +2608,16 @@
}
}
+ public void captivePortalAppResponse(Network network, int response, String actionToken) {
+ if (response == ConnectivityManager.CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS) {
+ enforceConnectivityInternalPermission();
+ }
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+ if (nai == null) return;
+ nai.networkMonitor.sendMessage(NetworkMonitor.CMD_CAPTIVE_PORTAL_APP_FINISHED, response, 0,
+ actionToken);
+ }
+
public ProxyInfo getDefaultProxy() {
// this information is already available as a world read/writable jvm property
// so this API change wouldn't have a benifit. It also breaks the passing
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 7e20276..4e83992 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -83,17 +83,6 @@
private static final String PERMISSION_ACCESS_NETWORK_CONDITIONS =
"android.permission.ACCESS_NETWORK_CONDITIONS";
- // Keep these in sync with CaptivePortalLoginActivity.java.
- // Intent broadcast from CaptivePortalLogin indicating sign-in is complete.
- // Extras:
- // EXTRA_TEXT = netId
- // LOGGED_IN_RESULT = one of the CAPTIVE_PORTAL_APP_RETURN_* values below.
- // RESPONSE_TOKEN = data fragment from launching Intent
- private static final String ACTION_CAPTIVE_PORTAL_LOGGED_IN =
- "android.net.netmon.captive_portal_logged_in";
- private static final String LOGGED_IN_RESULT = "result";
- private static final String RESPONSE_TOKEN = "response_token";
-
// After a network has been tested this result can be sent with EVENT_NETWORK_TESTED.
// The network should be used as a default internet connection. It was found to be:
// 1. a functioning network providing internet access, or
@@ -166,11 +155,12 @@
/**
* Message to self indicating captive portal app finished.
- * arg1 = one of: CAPTIVE_PORTAL_APP_RETURN_APPEASED,
+ * arg1 = one of: CAPTIVE_PORTAL_APP_RETURN_DISMISSED,
* CAPTIVE_PORTAL_APP_RETURN_UNWANTED,
* CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS
+ * obj = mCaptivePortalLoggedInResponseToken as String
*/
- private static final int CMD_CAPTIVE_PORTAL_APP_FINISHED = BASE + 9;
+ public static final int CMD_CAPTIVE_PORTAL_APP_FINISHED = BASE + 9;
/**
* Request ConnectivityService display provisioning notification.
@@ -181,26 +171,11 @@
public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 10;
/**
- * Message to self indicating sign-in app bypassed captive portal.
+ * Message to self indicating sign-in app should be launched.
+ * Sent by mLaunchCaptivePortalAppBroadcastReceiver when the
+ * user touches the sign in notification.
*/
- private static final int EVENT_APP_BYPASSED_CAPTIVE_PORTAL = BASE + 11;
-
- /**
- * Message to self indicating no sign-in app responded.
- */
- private static final int EVENT_NO_APP_RESPONSE = BASE + 12;
-
- /**
- * Message to self indicating sign-in app indicates sign-in is not possible.
- */
- private static final int EVENT_APP_INDICATES_SIGN_IN_IMPOSSIBLE = BASE + 13;
-
- /**
- * Return codes from captive portal sign-in app.
- */
- public static final int CAPTIVE_PORTAL_APP_RETURN_APPEASED = 0;
- public static final int CAPTIVE_PORTAL_APP_RETURN_UNWANTED = 1;
- public static final int CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS = 2;
+ private static final int CMD_LAUNCH_CAPTIVE_PORTAL_APP = BASE + 11;
private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
// Default to 30s linger time-out.
@@ -255,7 +230,7 @@
private final State mCaptivePortalState = new CaptivePortalState();
private final State mLingeringState = new LingeringState();
- private CaptivePortalLoggedInBroadcastReceiver mCaptivePortalLoggedInBroadcastReceiver = null;
+ private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null;
private String mCaptivePortalLoggedInResponseToken = null;
public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
@@ -319,9 +294,9 @@
return HANDLED;
case CMD_NETWORK_DISCONNECTED:
if (DBG) log("Disconnected - quitting");
- if (mCaptivePortalLoggedInBroadcastReceiver != null) {
- mContext.unregisterReceiver(mCaptivePortalLoggedInBroadcastReceiver);
- mCaptivePortalLoggedInBroadcastReceiver = null;
+ if (mLaunchCaptivePortalAppBroadcastReceiver != null) {
+ mContext.unregisterReceiver(mLaunchCaptivePortalAppBroadcastReceiver);
+ mLaunchCaptivePortalAppBroadcastReceiver = null;
}
quit();
return HANDLED;
@@ -332,14 +307,21 @@
transitionTo(mEvaluatingState);
return HANDLED;
case CMD_CAPTIVE_PORTAL_APP_FINISHED:
- // Previous token was broadcast, come up with a new one.
+ if (!mCaptivePortalLoggedInResponseToken.equals((String)message.obj))
+ return HANDLED;
+ // Previous token was sent out, come up with a new one.
mCaptivePortalLoggedInResponseToken = String.valueOf(new Random().nextLong());
switch (message.arg1) {
- case CAPTIVE_PORTAL_APP_RETURN_APPEASED:
- case CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS:
+ case ConnectivityManager.CAPTIVE_PORTAL_APP_RETURN_DISMISSED:
+ sendMessage(CMD_FORCE_REEVALUATION, 0 /* no UID */,
+ 0 /* INITIAL_ATTEMPTS */);
+ break;
+ case ConnectivityManager.CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS:
+ // TODO: Distinguish this from a network that actually validates.
+ // Displaying the "!" on the system UI icon may still be a good idea.
transitionTo(mValidatedState);
break;
- case CAPTIVE_PORTAL_APP_RETURN_UNWANTED:
+ case ConnectivityManager.CAPTIVE_PORTAL_APP_RETURN_UNWANTED:
mUserDoesNotWant = true;
// TODO: Should teardown network.
transitionTo(mOfflineState);
@@ -417,6 +399,25 @@
// is required. This State takes care to clear the notification upon exit from the State.
private class MaybeNotifyState extends State {
@Override
+ public boolean processMessage(Message message) {
+ if (DBG) log(getName() + message.toString());
+ switch (message.what) {
+ case CMD_LAUNCH_CAPTIVE_PORTAL_APP:
+ final Intent intent = new Intent(
+ ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK, mNetworkAgentInfo.network);
+ intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_TOKEN,
+ mCaptivePortalLoggedInResponseToken);
+ intent.setFlags(
+ Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+
+ @Override
public void exit() {
Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 0,
mNetworkAgentInfo.network.netId, null);
@@ -512,7 +513,9 @@
mContext.registerReceiver(this, new IntentFilter(mAction));
}
public PendingIntent getPendingIntent() {
- return PendingIntent.getBroadcast(mContext, 0, new Intent(mAction), 0);
+ final Intent intent = new Intent(mAction);
+ intent.setPackage(mContext.getPackageName());
+ return PendingIntent.getBroadcast(mContext, 0, intent, 0);
}
@Override
public void onReceive(Context context, Intent intent) {
@@ -520,48 +523,29 @@
}
}
- private class CaptivePortalLoggedInBroadcastReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Integer.parseInt(intent.getStringExtra(Intent.EXTRA_TEXT)) ==
- mNetworkAgentInfo.network.netId &&
- mCaptivePortalLoggedInResponseToken.equals(
- intent.getStringExtra(RESPONSE_TOKEN))) {
- sendMessage(obtainMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED,
- Integer.parseInt(intent.getStringExtra(LOGGED_IN_RESULT)), 0));
- }
- }
- }
-
// Being in the CaptivePortalState State indicates a captive portal was detected and the user
// has been shown a notification to sign-in.
private class CaptivePortalState extends State {
+ private static final String ACTION_LAUNCH_CAPTIVE_PORTAL_APP =
+ "android.net.netmon.launchCaptivePortalApp";
+
@Override
public void enter() {
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
NETWORK_TEST_RESULT_INVALID, 0, mNetworkAgentInfo));
-
- // Assemble Intent to launch captive portal sign-in app.
- final Intent intent = new Intent(Intent.ACTION_SEND);
- // Intent cannot use extras because PendingIntent.getActivity will merge matching
- // Intents erasing extras. Use data instead of extras to encode NetID.
- intent.setData(Uri.fromParts("netid", Integer.toString(mNetworkAgentInfo.network.netId),
- mCaptivePortalLoggedInResponseToken));
- intent.setComponent(new ComponentName("com.android.captiveportallogin",
- "com.android.captiveportallogin.CaptivePortalLoginActivity"));
- intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
-
- if (mCaptivePortalLoggedInBroadcastReceiver == null) {
+ // Create a CustomIntentReceiver that sends us a
+ // CMD_LAUNCH_CAPTIVE_PORTAL_APP message when the user
+ // touches the notification.
+ if (mLaunchCaptivePortalAppBroadcastReceiver == null) {
// Wait for result.
- mCaptivePortalLoggedInBroadcastReceiver =
- new CaptivePortalLoggedInBroadcastReceiver();
- final IntentFilter filter = new IntentFilter(ACTION_CAPTIVE_PORTAL_LOGGED_IN);
- mContext.registerReceiver(mCaptivePortalLoggedInBroadcastReceiver, filter);
+ mLaunchCaptivePortalAppBroadcastReceiver = new CustomIntentReceiver(
+ ACTION_LAUNCH_CAPTIVE_PORTAL_APP, new Random().nextInt(),
+ CMD_LAUNCH_CAPTIVE_PORTAL_APP);
}
- // Initiate notification to sign-in.
+ // Display the sign in notification.
Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 1,
mNetworkAgentInfo.network.netId,
- PendingIntent.getActivity(mContext, 0, intent, 0));
+ mLaunchCaptivePortalAppBroadcastReceiver.getPendingIntent());
mConnectivityServiceHandler.sendMessage(message);
}
diff --git a/services/net/java/android/net/dhcp/DhcpAckPacket.java b/services/net/java/android/net/dhcp/DhcpAckPacket.java
index 25b8093..c0e1d19 100644
--- a/services/net/java/android/net/dhcp/DhcpAckPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpAckPacket.java
@@ -29,9 +29,9 @@
*/
private final Inet4Address mSrcIp;
- DhcpAckPacket(int transId, boolean broadcast, Inet4Address serverAddress,
+ DhcpAckPacket(int transId, short secs, boolean broadcast, Inet4Address serverAddress,
Inet4Address clientIp, byte[] clientMac) {
- super(transId, INADDR_ANY, clientIp, serverAddress, INADDR_ANY, clientMac, broadcast);
+ super(transId, secs, INADDR_ANY, clientIp, serverAddress, INADDR_ANY, clientMac, broadcast);
mBroadcast = broadcast;
mSrcIp = serverAddress;
}
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index ab56493..e1d1787 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -154,6 +154,7 @@
private byte[] mHwAddr;
private PacketSocketAddress mInterfaceBroadcastAddr;
private int mTransactionId;
+ private long mTransactionStartMillis;
private DhcpResults mDhcpLease;
private long mDhcpLeaseExpiry;
private DhcpResults mOffer;
@@ -264,8 +265,9 @@
}
}
- private void initTransactionId() {
+ private void startNewTransaction() {
mTransactionId = mRandom.nextInt();
+ mTransactionStartMillis = SystemClock.elapsedRealtime();
}
private boolean initSockets() {
@@ -344,6 +346,10 @@
}
}
+ private short getSecs() {
+ return (short) ((SystemClock.elapsedRealtime() - mTransactionStartMillis) / 1000);
+ }
+
private boolean transmitPacket(ByteBuffer buf, String description, Inet4Address to) {
try {
if (to.equals(INADDR_BROADCAST)) {
@@ -362,7 +368,8 @@
private boolean sendDiscoverPacket() {
ByteBuffer packet = DhcpPacket.buildDiscoverPacket(
- DhcpPacket.ENCAP_L2, mTransactionId, mHwAddr, DO_UNICAST, REQUESTED_PARAMS);
+ DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr,
+ DO_UNICAST, REQUESTED_PARAMS);
return transmitPacket(packet, "DHCPDISCOVER", INADDR_BROADCAST);
}
@@ -373,7 +380,7 @@
int encap = to.equals(INADDR_BROADCAST) ? DhcpPacket.ENCAP_L2 : DhcpPacket.ENCAP_BOOTP;
ByteBuffer packet = DhcpPacket.buildRequestPacket(
- encap, mTransactionId, clientAddress,
+ encap, mTransactionId, getSecs(), clientAddress,
DO_UNICAST, mHwAddr, requestedAddress,
serverAddress, REQUESTED_PARAMS, null);
String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() +
@@ -669,7 +676,7 @@
@Override
public void enter() {
super.enter();
- initTransactionId();
+ startNewTransaction();
}
protected boolean sendPacket() {
@@ -776,7 +783,7 @@
@Override
public void enter() {
super.enter();
- initTransactionId();
+ startNewTransaction();
}
protected boolean sendPacket() {
diff --git a/services/net/java/android/net/dhcp/DhcpDeclinePacket.java b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java
index 4a22b65..7ecdea7 100644
--- a/services/net/java/android/net/dhcp/DhcpDeclinePacket.java
+++ b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java
@@ -26,10 +26,10 @@
/**
* Generates a DECLINE packet with the specified parameters.
*/
- DhcpDeclinePacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+ DhcpDeclinePacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp,
Inet4Address nextIp, Inet4Address relayIp,
byte[] clientMac) {
- super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false);
+ super(transId, secs, clientIp, yourIp, nextIp, relayIp, clientMac, false);
}
public String toString() {
diff --git a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
index ed0fdc6..91e6bd6 100644
--- a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
@@ -26,8 +26,8 @@
/**
* Generates a DISCOVER packet with the specified parameters.
*/
- DhcpDiscoverPacket(int transId, byte[] clientMac, boolean broadcast) {
- super(transId, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
+ DhcpDiscoverPacket(int transId, short secs, byte[] clientMac, boolean broadcast) {
+ super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
}
public String toString() {
diff --git a/services/net/java/android/net/dhcp/DhcpInformPacket.java b/services/net/java/android/net/dhcp/DhcpInformPacket.java
index 2434fc9..7a83466 100644
--- a/services/net/java/android/net/dhcp/DhcpInformPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpInformPacket.java
@@ -26,10 +26,10 @@
/**
* Generates an INFORM packet with the specified parameters.
*/
- DhcpInformPacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+ DhcpInformPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp,
Inet4Address nextIp, Inet4Address relayIp,
byte[] clientMac) {
- super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false);
+ super(transId, secs, clientIp, yourIp, nextIp, relayIp, clientMac, false);
}
public String toString() {
diff --git a/services/net/java/android/net/dhcp/DhcpNakPacket.java b/services/net/java/android/net/dhcp/DhcpNakPacket.java
index 1390ea7..6458232 100644
--- a/services/net/java/android/net/dhcp/DhcpNakPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpNakPacket.java
@@ -26,10 +26,10 @@
/**
* Generates a NAK packet with the specified parameters.
*/
- DhcpNakPacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+ DhcpNakPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp,
Inet4Address nextIp, Inet4Address relayIp,
byte[] clientMac) {
- super(transId, INADDR_ANY, INADDR_ANY, nextIp, relayIp,
+ super(transId, secs, INADDR_ANY, INADDR_ANY, nextIp, relayIp,
clientMac, false);
}
diff --git a/services/net/java/android/net/dhcp/DhcpOfferPacket.java b/services/net/java/android/net/dhcp/DhcpOfferPacket.java
index b1f3bbd..af41708 100644
--- a/services/net/java/android/net/dhcp/DhcpOfferPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpOfferPacket.java
@@ -31,9 +31,9 @@
/**
* Generates a OFFER packet with the specified parameters.
*/
- DhcpOfferPacket(int transId, boolean broadcast, Inet4Address serverAddress,
+ DhcpOfferPacket(int transId, short secs, boolean broadcast, Inet4Address serverAddress,
Inet4Address clientIp, byte[] clientMac) {
- super(transId, INADDR_ANY, clientIp, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
+ super(transId, secs, INADDR_ANY, clientIp, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
mSrcIp = serverAddress;
}
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index a64ee6f..b923b1b 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -226,6 +226,11 @@
protected final int mTransId;
/**
+ * The seconds field in the BOOTP header. Per RFC, should be nonzero in client requests only.
+ */
+ protected final short mSecs;
+
+ /**
* The IP address of the client host. This address is typically
* proposed by the client (from an earlier DHCP negotiation) or
* supplied by the server.
@@ -258,10 +263,11 @@
*/
abstract void finishPacket(ByteBuffer buffer);
- protected DhcpPacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+ protected DhcpPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp,
Inet4Address nextIp, Inet4Address relayIp,
byte[] clientMac, boolean broadcast) {
mTransId = transId;
+ mSecs = secs;
mClientIp = clientIp;
mYourIp = yourIp;
mNextIp = nextIp;
@@ -357,7 +363,7 @@
buf.put((byte) mClientMac.length); // Hardware Address Length
buf.put((byte) 0); // Hop Count
buf.putInt(mTransId); // Transaction ID
- buf.putShort((short) 0); // Elapsed Seconds
+ buf.putShort(mSecs); // Elapsed Seconds
if (broadcast) {
buf.putShort((short) 0x8000); // Flags
@@ -652,6 +658,7 @@
{
// bootp parameters
int transactionId;
+ short secs;
Inet4Address clientIp;
Inet4Address yourIp;
Inet4Address nextIp;
@@ -759,7 +766,7 @@
byte addrLen = packet.get();
byte hops = packet.get();
transactionId = packet.getInt();
- short elapsed = packet.getShort();
+ secs = packet.getShort();
short bootpFlags = packet.getShort();
boolean broadcast = (bootpFlags & 0x8000) != 0;
byte[] ipv4addr = new byte[4];
@@ -902,33 +909,33 @@
case -1: return null;
case DHCP_MESSAGE_TYPE_DISCOVER:
newPacket = new DhcpDiscoverPacket(
- transactionId, clientMac, broadcast);
+ transactionId, secs, clientMac, broadcast);
break;
case DHCP_MESSAGE_TYPE_OFFER:
newPacket = new DhcpOfferPacket(
- transactionId, broadcast, ipSrc, yourIp, clientMac);
+ transactionId, secs, broadcast, ipSrc, yourIp, clientMac);
break;
case DHCP_MESSAGE_TYPE_REQUEST:
newPacket = new DhcpRequestPacket(
- transactionId, clientIp, clientMac, broadcast);
+ transactionId, secs, clientIp, clientMac, broadcast);
break;
case DHCP_MESSAGE_TYPE_DECLINE:
newPacket = new DhcpDeclinePacket(
- transactionId, clientIp, yourIp, nextIp, relayIp,
+ transactionId, secs, clientIp, yourIp, nextIp, relayIp,
clientMac);
break;
case DHCP_MESSAGE_TYPE_ACK:
newPacket = new DhcpAckPacket(
- transactionId, broadcast, ipSrc, yourIp, clientMac);
+ transactionId, secs, broadcast, ipSrc, yourIp, clientMac);
break;
case DHCP_MESSAGE_TYPE_NAK:
newPacket = new DhcpNakPacket(
- transactionId, clientIp, yourIp, nextIp, relayIp,
+ transactionId, secs, clientIp, yourIp, nextIp, relayIp,
clientMac);
break;
case DHCP_MESSAGE_TYPE_INFORM:
newPacket = new DhcpInformPacket(
- transactionId, clientIp, yourIp, nextIp, relayIp,
+ transactionId, secs, clientIp, yourIp, nextIp, relayIp,
clientMac);
break;
default:
@@ -1008,9 +1015,9 @@
* parameters.
*/
public static ByteBuffer buildDiscoverPacket(int encap, int transactionId,
- byte[] clientMac, boolean broadcast, byte[] expectedParams) {
+ short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams) {
DhcpPacket pkt = new DhcpDiscoverPacket(
- transactionId, clientMac, broadcast);
+ transactionId, secs, clientMac, broadcast);
pkt.mRequestedParams = expectedParams;
return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT);
}
@@ -1025,7 +1032,7 @@
Inet4Address gateway, List<Inet4Address> dnsServers,
Inet4Address dhcpServerIdentifier, String domainName) {
DhcpPacket pkt = new DhcpOfferPacket(
- transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
+ transactionId, (short) 0, broadcast, serverIpAddr, clientIpAddr, mac);
pkt.mGateway = gateway;
pkt.mDnsServers = dnsServers;
pkt.mLeaseTime = timeout;
@@ -1045,7 +1052,7 @@
Inet4Address gateway, List<Inet4Address> dnsServers,
Inet4Address dhcpServerIdentifier, String domainName) {
DhcpPacket pkt = new DhcpAckPacket(
- transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
+ transactionId, (short) 0, broadcast, serverIpAddr, clientIpAddr, mac);
pkt.mGateway = gateway;
pkt.mDnsServers = dnsServers;
pkt.mLeaseTime = timeout;
@@ -1061,7 +1068,7 @@
*/
public static ByteBuffer buildNakPacket(int encap, int transactionId,
Inet4Address serverIpAddr, Inet4Address clientIpAddr, byte[] mac) {
- DhcpPacket pkt = new DhcpNakPacket(transactionId, clientIpAddr,
+ DhcpPacket pkt = new DhcpNakPacket(transactionId, (short) 0, clientIpAddr,
serverIpAddr, serverIpAddr, serverIpAddr, mac);
pkt.mMessage = "requested address not available";
pkt.mRequestedIp = clientIpAddr;
@@ -1072,10 +1079,10 @@
* Builds a DHCP-REQUEST packet from the required specified parameters.
*/
public static ByteBuffer buildRequestPacket(int encap,
- int transactionId, Inet4Address clientIp, boolean broadcast,
+ int transactionId, short secs, Inet4Address clientIp, boolean broadcast,
byte[] clientMac, Inet4Address requestedIpAddress,
Inet4Address serverIdentifier, byte[] requestedParams, String hostName) {
- DhcpPacket pkt = new DhcpRequestPacket(transactionId, clientIp,
+ DhcpPacket pkt = new DhcpRequestPacket(transactionId, secs, clientIp,
clientMac, broadcast);
pkt.mRequestedIp = requestedIpAddress;
pkt.mServerIdentifier = serverIdentifier;
diff --git a/services/net/java/android/net/dhcp/DhcpRequestPacket.java b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
index 5d378b8..4f9aa01 100644
--- a/services/net/java/android/net/dhcp/DhcpRequestPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
@@ -28,9 +28,9 @@
/**
* Generates a REQUEST packet with the specified parameters.
*/
- DhcpRequestPacket(int transId, Inet4Address clientIp, byte[] clientMac,
+ DhcpRequestPacket(int transId, short secs, Inet4Address clientIp, byte[] clientMac,
boolean broadcast) {
- super(transId, clientIp, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
+ super(transId, secs, clientIp, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
}
public String toString() {
diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
index 2658937..4f7c7ec 100644
--- a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
@@ -41,7 +41,8 @@
private byte[] mDomainBytes, mVendorInfoBytes;
public TestDhcpPacket(byte type, byte[] domainBytes, byte[] vendorInfoBytes) {
- super(0xdeadbeef, INADDR_ANY, CLIENT_ADDR, INADDR_ANY, INADDR_ANY, CLIENT_MAC, true);
+ super(0xdeadbeef, (short) 0, INADDR_ANY, CLIENT_ADDR, INADDR_ANY, INADDR_ANY,
+ CLIENT_MAC, true);
mType = type;
mDomainBytes = domainBytes;
mVendorInfoBytes = vendorInfoBytes;
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 2a30384..d92c0c7 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -933,7 +933,8 @@
Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
}
- boolean videoCallChanged = !Objects.equals(mVideoCall, parcelableCall.getVideoCall());
+ boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
+ !Objects.equals(mVideoCall, parcelableCall.getVideoCall());
if (videoCallChanged) {
mVideoCall = parcelableCall.getVideoCall();
}
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index bab60fe..0424548 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -50,6 +50,7 @@
Conference conference, int connectionCapabilities) {}
public void onVideoStateChanged(Conference c, int videoState) { }
public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) {}
+ public void onStatusHintsChanged(Conference conference, StatusHints statusHints) {}
}
private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
@@ -67,6 +68,7 @@
private int mConnectionCapabilities;
private String mDisconnectMessage;
private long mConnectTimeMillis = CONNECT_TIME_NOT_SPECIFIED;
+ private StatusHints mStatusHints;
private final Connection.Listener mConnectionDeathListener = new Connection.Listener() {
@Override
@@ -535,4 +537,23 @@
getVideoProvider(),
super.toString());
}
+
+ /**
+ * Sets the label and icon status to display in the InCall UI.
+ *
+ * @param statusHints The status label and icon to set.
+ */
+ public final void setStatusHints(StatusHints statusHints) {
+ mStatusHints = statusHints;
+ for (Listener l : mListeners) {
+ l.onStatusHintsChanged(this, statusHints);
+ }
+ }
+
+ /**
+ * @return The status hints for this conference.
+ */
+ public final StatusHints getStatusHints() {
+ return mStatusHints;
+ }
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index e79584f..cd10050 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -402,7 +403,7 @@
*/
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_ADD_VIDEO_CALLBACK = 1;
private static final int MSG_SET_CAMERA = 2;
private static final int MSG_SET_PREVIEW_SURFACE = 3;
private static final int MSG_SET_DISPLAY_SURFACE = 4;
@@ -413,11 +414,16 @@
private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9;
private static final int MSG_REQUEST_CONNECTION_DATA_USAGE = 10;
private static final int MSG_SET_PAUSE_IMAGE = 11;
+ private static final int MSG_REMOVE_VIDEO_CALLBACK = 12;
private final VideoProvider.VideoProviderHandler
mMessageHandler = new VideoProvider.VideoProviderHandler();
private final VideoProvider.VideoProviderBinder mBinder;
- private IVideoCallback mVideoCallback;
+
+ /**
+ * Stores a list of the video callbacks, keyed by IBinder.
+ */
+ private HashMap<IBinder, IVideoCallback> mVideoCallbacks = new HashMap<>();
/**
* Default handler used to consolidate binder method calls onto a single thread.
@@ -426,9 +432,29 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_SET_VIDEO_CALLBACK:
- mVideoCallback = IVideoCallback.Stub.asInterface((IBinder) msg.obj);
+ case MSG_ADD_VIDEO_CALLBACK: {
+ IBinder binder = (IBinder) msg.obj;
+ IVideoCallback callback = IVideoCallback.Stub
+ .asInterface((IBinder) msg.obj);
+ if (mVideoCallbacks.containsKey(binder)) {
+ Log.i(this, "addVideoProvider - skipped; already present.");
+ break;
+ }
+ mVideoCallbacks.put(binder, callback);
+ Log.i(this, "addVideoProvider "+ mVideoCallbacks.size());
break;
+ }
+ case MSG_REMOVE_VIDEO_CALLBACK: {
+ IBinder binder = (IBinder) msg.obj;
+ IVideoCallback callback = IVideoCallback.Stub
+ .asInterface((IBinder) msg.obj);
+ if (!mVideoCallbacks.containsKey(binder)) {
+ Log.i(this, "removeVideoProvider - skipped; not present.");
+ break;
+ }
+ mVideoCallbacks.remove(binder);
+ break;
+ }
case MSG_SET_CAMERA:
onSetCamera((String) msg.obj);
break;
@@ -469,9 +495,14 @@
* IVideoProvider stub implementation.
*/
private final class VideoProviderBinder extends IVideoProvider.Stub {
- public void setVideoCallback(IBinder videoCallbackBinder) {
+ public void addVideoCallback(IBinder videoCallbackBinder) {
mMessageHandler.obtainMessage(
- MSG_SET_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget();
+ MSG_ADD_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget();
+ }
+
+ public void removeVideoCallback(IBinder videoCallbackBinder) {
+ mMessageHandler.obtainMessage(
+ MSG_REMOVE_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget();
}
public void setCamera(String cameraId) {
@@ -609,21 +640,23 @@
public abstract void onSetPauseImage(String uri);
/**
- * Invokes callback method defined in In-Call UI.
+ * Invokes callback method defined in listening {@link InCallService} implementations.
*
* @param videoProfile The requested video connection profile.
*/
public void receiveSessionModifyRequest(VideoProfile videoProfile) {
- if (mVideoCallback != null) {
+ if (mVideoCallbacks != null) {
try {
- mVideoCallback.receiveSessionModifyRequest(videoProfile);
+ for (IVideoCallback callback : mVideoCallbacks.values()) {
+ callback.receiveSessionModifyRequest(videoProfile);
+ }
} catch (RemoteException ignored) {
}
}
}
/**
- * Invokes callback method defined in In-Call UI.
+ * Invokes callback method defined in listening {@link InCallService} implementations.
*
* @param status Status of the session modify request. Valid values are
* {@link VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS},
@@ -634,17 +667,19 @@
*/
public void receiveSessionModifyResponse(int status,
VideoProfile requestedProfile, VideoProfile responseProfile) {
- if (mVideoCallback != null) {
+ if (mVideoCallbacks != null) {
try {
- mVideoCallback.receiveSessionModifyResponse(
- status, requestedProfile, responseProfile);
+ for (IVideoCallback callback : mVideoCallbacks.values()) {
+ callback.receiveSessionModifyResponse(status, requestedProfile,
+ responseProfile);
+ }
} catch (RemoteException ignored) {
}
}
}
/**
- * Invokes callback method defined in In-Call UI.
+ * Invokes callback method defined in listening {@link InCallService} implementations.
*
* Valid values are: {@link VideoProvider#SESSION_EVENT_RX_PAUSE},
* {@link VideoProvider#SESSION_EVENT_RX_RESUME},
@@ -654,66 +689,76 @@
* @param event The event.
*/
public void handleCallSessionEvent(int event) {
- if (mVideoCallback != null) {
+ if (mVideoCallbacks != null) {
try {
- mVideoCallback.handleCallSessionEvent(event);
+ for (IVideoCallback callback : mVideoCallbacks.values()) {
+ callback.handleCallSessionEvent(event);
+ }
} catch (RemoteException ignored) {
}
}
}
/**
- * Invokes callback method defined in In-Call UI.
+ * Invokes callback method defined in listening {@link InCallService} implementations.
*
* @param width The updated peer video width.
* @param height The updated peer video height.
*/
public void changePeerDimensions(int width, int height) {
- if (mVideoCallback != null) {
+ if (mVideoCallbacks != null) {
try {
- mVideoCallback.changePeerDimensions(width, height);
+ for (IVideoCallback callback : mVideoCallbacks.values()) {
+ callback.changePeerDimensions(width, height);
+ }
} catch (RemoteException ignored) {
}
}
}
/**
- * Invokes callback method defined in In-Call UI.
+ * Invokes callback method defined in listening {@link InCallService} implementations.
*
* @param dataUsage The updated data usage.
*/
public void changeCallDataUsage(long dataUsage) {
- if (mVideoCallback != null) {
+ if (mVideoCallbacks != null) {
try {
- mVideoCallback.changeCallDataUsage(dataUsage);
+ for (IVideoCallback callback : mVideoCallbacks.values()) {
+ callback.changeCallDataUsage(dataUsage);
+ }
} catch (RemoteException ignored) {
}
}
}
/**
- * Invokes callback method defined in In-Call UI.
+ * Invokes callback method defined in listening {@link InCallService} implementations.
*
* @param cameraCapabilities The changed camera capabilities.
*/
public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
- if (mVideoCallback != null) {
+ if (mVideoCallbacks != null) {
try {
- mVideoCallback.changeCameraCapabilities(cameraCapabilities);
+ for (IVideoCallback callback : mVideoCallbacks.values()) {
+ callback.changeCameraCapabilities(cameraCapabilities);
+ }
} catch (RemoteException ignored) {
}
}
}
/**
- * Invokes callback method defined in In-Call UI.
+ * Invokes callback method defined in listening {@link InCallService} implementations.
*
* @param videoQuality The updated video quality.
*/
public void changeVideoQuality(int videoQuality) {
- if (mVideoCallback != null) {
+ if (mVideoCallbacks != null) {
try {
- mVideoCallback.changeVideoQuality(videoQuality);
+ for (IVideoCallback callback : mVideoCallbacks.values()) {
+ callback.changeVideoQuality(videoQuality);
+ }
} catch (RemoteException ignored) {
}
}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 9812815..c039acf 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -427,6 +427,12 @@
videoProvider);
mAdapter.setVideoProvider(id, videoProvider);
}
+
+ @Override
+ public void onStatusHintsChanged(Conference conference, StatusHints statusHints) {
+ String id = mIdByConference.get(conference);
+ mAdapter.setStatusHints(id, statusHints);
+ }
};
private final Connection.Listener mConnectionListener = new Connection.Listener() {
@@ -903,8 +909,9 @@
conference.getVideoProvider() == null ?
null : conference.getVideoProvider().getInterface(),
conference.getVideoState(),
- conference.getConnectTimeMillis()
- );
+ conference.getConnectTimeMillis(),
+ conference.getStatusHints());
+
mAdapter.addConferenceCall(id, parcelableConference);
mAdapter.setVideoProvider(id, conference.getVideoProvider());
mAdapter.setVideoState(id, conference.getVideoState());
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 7cbc0fc..e5d6ae0 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -370,6 +370,11 @@
public abstract void registerCallback(VideoCall.Callback callback);
/**
+ * Clears the video call listener set via {@link #setVideoCallListener(Listener)}.
+ */
+ public abstract void unregisterCallback();
+
+ /**
* Sets the camera to be used for video recording in a video call.
*
* @param cameraId The id of the camera.
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index c5c3d11..1a30910 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -46,6 +46,7 @@
private final int mCallerDisplayNamePresentation;
private final GatewayInfo mGatewayInfo;
private final PhoneAccountHandle mAccountHandle;
+ private final boolean mIsVideoCallProviderChanged;
private final IVideoProvider mVideoCallProvider;
private InCallService.VideoCall mVideoCall;
private final String mParentCallId;
@@ -69,6 +70,7 @@
int callerDisplayNamePresentation,
GatewayInfo gatewayInfo,
PhoneAccountHandle accountHandle,
+ boolean isVideoCallProviderChanged,
IVideoProvider videoCallProvider,
String parentCallId,
List<String> childCallIds,
@@ -89,6 +91,7 @@
mCallerDisplayNamePresentation = callerDisplayNamePresentation;
mGatewayInfo = gatewayInfo;
mAccountHandle = accountHandle;
+ mIsVideoCallProviderChanged = isVideoCallProviderChanged;
mVideoCallProvider = videoCallProvider;
mParentCallId = parentCallId;
mChildCallIds = childCallIds;
@@ -232,6 +235,18 @@
return mExtras;
}
+ /**
+ * Indicates to the receiver of the {@link ParcelableCall} whether a change has occurred in the
+ * {@link android.telecom.InCallService.VideoCall} associated with this call. Since
+ * {@link #getVideoCall()} creates a new {@link VideoCallImpl}, it is useful to know whether
+ * the provider has changed (which can influence whether it is accessed).
+ *
+ * @return {@code true} if the video call changed, {@code false} otherwise.
+ */
+ public boolean isVideoCallProviderChanged() {
+ return mIsVideoCallProviderChanged;
+ }
+
/** Responsible for creating ParcelableCall objects for deserialized Parcels. */
public static final Parcelable.Creator<ParcelableCall> CREATOR =
new Parcelable.Creator<ParcelableCall> () {
@@ -252,6 +267,7 @@
int callerDisplayNamePresentation = source.readInt();
GatewayInfo gatewayInfo = source.readParcelable(classLoader);
PhoneAccountHandle accountHandle = source.readParcelable(classLoader);
+ boolean isVideoCallProviderChanged = source.readByte() == 1;
IVideoProvider videoCallProvider =
IVideoProvider.Stub.asInterface(source.readStrongBinder());
String parentCallId = source.readString();
@@ -276,6 +292,7 @@
callerDisplayNamePresentation,
gatewayInfo,
accountHandle,
+ isVideoCallProviderChanged,
videoCallProvider,
parentCallId,
childCallIds,
@@ -313,6 +330,7 @@
destination.writeInt(mCallerDisplayNamePresentation);
destination.writeParcelable(mGatewayInfo, 0);
destination.writeParcelable(mAccountHandle, 0);
+ destination.writeByte((byte) (mIsVideoCallProviderChanged ? 1 : 0));
destination.writeStrongBinder(
mVideoCallProvider != null ? mVideoCallProvider.asBinder() : null);
destination.writeString(mParentCallId);
diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java
index ab82549..e54e79d 100644
--- a/telecomm/java/android/telecom/ParcelableConference.java
+++ b/telecomm/java/android/telecom/ParcelableConference.java
@@ -34,25 +34,10 @@
private int mState;
private int mConnectionCapabilities;
private List<String> mConnectionIds;
- private long mConnectTimeMillis;
+ private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
private final IVideoProvider mVideoProvider;
private final int mVideoState;
-
- public ParcelableConference(
- PhoneAccountHandle phoneAccount,
- int state,
- int connectionCapabilities,
- 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;
- }
+ private StatusHints mStatusHints;
public ParcelableConference(
PhoneAccountHandle phoneAccount,
@@ -61,9 +46,17 @@
List<String> connectionIds,
IVideoProvider videoProvider,
int videoState,
- long connectTimeMillis) {
- this(phoneAccount, state, connectionCapabilities, connectionIds, videoProvider, videoState);
+ long connectTimeMillis,
+ StatusHints statusHints) {
+ mPhoneAccount = phoneAccount;
+ mState = state;
+ mConnectionCapabilities = connectionCapabilities;
+ mConnectionIds = connectionIds;
+ mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
+ mVideoProvider = videoProvider;
+ mVideoState = videoState;
mConnectTimeMillis = connectTimeMillis;
+ mStatusHints = statusHints;
}
@Override
@@ -113,6 +106,10 @@
return mVideoState;
}
+ public StatusHints getStatusHints() {
+ return mStatusHints;
+ }
+
public static final Parcelable.Creator<ParcelableConference> CREATOR =
new Parcelable.Creator<ParcelableConference> () {
@Override
@@ -124,13 +121,14 @@
List<String> connectionIds = new ArrayList<>(2);
source.readList(connectionIds, classLoader);
long connectTimeMillis = source.readLong();
+ StatusHints statusHints = source.readParcelable(classLoader);
IVideoProvider videoCallProvider =
IVideoProvider.Stub.asInterface(source.readStrongBinder());
int videoState = source.readInt();
return new ParcelableConference(phoneAccount, state, capabilities, connectionIds,
- videoCallProvider, videoState);
+ videoCallProvider, videoState, connectTimeMillis, statusHints);
}
@Override
@@ -156,5 +154,6 @@
destination.writeStrongBinder(
mVideoProvider != null ? mVideoProvider.asBinder() : null);
destination.writeInt(mVideoState);
+ destination.writeParcelable(mStatusHints, 0);
}
}
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index c1c1129..3d9acda 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -122,6 +122,11 @@
final void internalRemoveCall(Call call) {
mCallByTelecomCallId.remove(call.internalGetCallId());
mCalls.remove(call);
+
+ InCallService.VideoCall videoCall = call.getVideoCall();
+ if (videoCall != null) {
+ videoCall.unregisterCallback();
+ }
fireCallRemoved(call);
}
@@ -167,6 +172,10 @@
*/
final void destroy() {
for (Call call : mCalls) {
+ InCallService.VideoCall videoCall = call.getVideoCall();
+ if (videoCall != null) {
+ videoCall.unregisterCallback();
+ }
if (call.getState() != Call.STATE_DISCONNECTED) {
call.internalSetDisconnected();
}
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 4c423f2..4ecfd50 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -301,7 +301,7 @@
public VideoProvider(IVideoProvider videoProviderBinder) {
mVideoProviderBinder = videoProviderBinder;
try {
- mVideoProviderBinder.setVideoCallback(mVideoCallbackServant.getStub().asBinder());
+ mVideoProviderBinder.addVideoCallback(mVideoCallbackServant.getStub().asBinder());
} catch (RemoteException e) {
}
}
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index 7bef688..3779d1a 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -166,7 +166,7 @@
mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
mBinder = new VideoCallListenerBinder();
- mVideoProvider.setVideoCallback(mBinder);
+ mVideoProvider.addVideoCallback(mBinder);
}
/** {@inheritDoc} */
@@ -175,6 +175,15 @@
}
/** {@inheritDoc} */
+ public void unregisterCallback() {
+ mCallback = null;
+ try {
+ mVideoProvider.removeVideoCallback(mBinder);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /** {@inheritDoc} */
public void setCamera(String cameraId) {
try {
mVideoProvider.setCamera(cameraId);
diff --git a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
index e96d9d3..bff3865 100644
--- a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
+++ b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
@@ -25,7 +25,9 @@
* @hide
*/
oneway interface IVideoProvider {
- void setVideoCallback(IBinder videoCallbackBinder);
+ void addVideoCallback(IBinder videoCallbackBinder);
+
+ void removeVideoCallback(IBinder videoCallbackBinder);
void setCamera(String cameraId);
diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
index 84d1c545..0443c3e 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
@@ -115,4 +115,12 @@
* - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
*/
void callSessionTtyModeReceived(in IImsCallSession session, in int mode);
+
+ /**
+ * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
+ *
+ * @param session The call session.
+ * @param isMultiParty {@code true} if the session became multiparty, {@code false} otherwise.
+ */
+ void callSessionMultipartyStateChanged(in IImsCallSession session, in boolean isMultiParty);
}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index b156d0c..d2fb0dd 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -808,7 +808,7 @@
if (mRttCapabilities == null) {
if(getRttCapabilities() == null) {
Log.e(TAG, "Can not get RTT capabilities");
- //throw new IllegalStateException("RTT chip is not working");
+ throw new IllegalStateException("RTT chip is not working");
}
}
@@ -866,6 +866,15 @@
return true;
}
+ /**
+ * Request to start an RTT ranging
+ *
+ * @param params -- RTT request Parameters
+ * @param listener -- Call back to inform RTT result
+ * @exception throw IllegalArgumentException when params are illegal
+ * throw IllegalStateException when RttCapabilities do not exist
+ */
+
public void startRanging(RttParams[] params, RttListener listener) {
int index = 0;
for(RttParams rttParam : params) {
@@ -874,9 +883,9 @@
}
index++;
}
-
validateChannel();
ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
+ Log.i(TAG, "Send RTT request to RTT Service");
sAsyncChannel.sendMessage(CMD_OP_START_RANGING,
0, putListener(listener), parcelableParams);
}
@@ -1024,6 +1033,7 @@
}
@Override
public void handleMessage(Message msg) {
+ Log.i(TAG, "RTT manager get message: " + msg.what);
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
@@ -1049,10 +1059,10 @@
Object listener = getListener(msg.arg2);
if (listener == null) {
- if (DBG) Log.d(TAG, "invalid listener key = " + msg.arg2);
+ Log.e(TAG, "invalid listener key = " + msg.arg2 );
return;
} else {
- if (DBG) Log.d(TAG, "listener key = " + msg.arg2);
+ Log.i(TAG, "listener key = " + msg.arg2);
}
switch (msg.what) {
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index c6f2991..b731316 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -243,6 +243,7 @@
* The band which AP resides on
* 0-2G 1-5G
* By default, 2G is chosen
+ * @hide
*/
public int apBand = 0;
@@ -251,6 +252,7 @@
* 2G 1-11
* 5G 36,40,44,48,149,153,157,161,165
* 0 - find a random available channel according to the apBand
+ * @hide
*/
public int apChannel = 0;
@@ -953,7 +955,7 @@
if (!TextUtils.isEmpty(FQDN)) {
/* this is passpoint configuration; it must not have an SSID */
if (!TextUtils.isEmpty(SSID)) {
- return "no SSID";
+ return "SSID not expected for Passpoint: '" + SSID + "'";
}
/* this is passpoint configuration; it must have a providerFriendlyName */
if (TextUtils.isEmpty(providerFriendlyName)) {
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 6917971..3525ec2 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -56,6 +56,8 @@
/** @hide */
public static final String ALTSUBJECT_MATCH_KEY = "altsubject_match";
/** @hide */
+ public static final String DOM_SUFFIX_MATCH_KEY = "domain_suffix_match";
+ /** @hide */
public static final String OPP_KEY_CACHING = "proactive_key_caching";
/**
* String representing the keystore OpenSSL ENGINE's ID.
@@ -577,6 +579,36 @@
}
/**
+ * Set the domain_suffix_match directive on wpa_supplicant. This is the parameter to use
+ * for Hotspot 2.0 defined matching of AAA server certs per WFA HS2.0 spec, section 7.3.3.2,
+ * second paragraph.
+ *
+ * From wpa_supplicant documentation:
+ * Constraint for server domain name. If set, this FQDN is used as a suffix match requirement
+ * for the AAAserver certificate in SubjectAltName dNSName element(s). If a matching dNSName is
+ * found, this constraint is met. If no dNSName values are present, this constraint is matched
+ * against SubjectName CN using same suffix match comparison.
+ * Suffix match here means that the host/domain name is compared one label at a time starting
+ * from the top-level domain and all the labels in domain_suffix_match shall be included in the
+ * certificate. The certificate may include additional sub-level labels in addition to the
+ * required labels.
+ * For example, domain_suffix_match=example.com would match test.example.com but would not
+ * match test-example.com.
+ * @param domain The domain value
+ */
+ public void setDomainSuffixMatch(String domain) {
+ setFieldValue(DOM_SUFFIX_MATCH_KEY, domain);
+ }
+
+ /**
+ * Get the domain_suffix_match value. See setDomSuffixMatch.
+ * @return The domain value.
+ */
+ public String getDomainSubjectMatch() {
+ return getFieldValue(DOM_SUFFIX_MATCH_KEY, "");
+ }
+
+ /**
* Set realm for passpoint credential
* @param realm the realm
*/