Loading core/java/android/net/CaptivePortalTracker.java +27 −95 Original line number Diff line number Diff line Loading @@ -16,22 +16,16 @@ package android.net; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.UserHandle; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; Loading @@ -46,7 +40,6 @@ import android.telephony.CellInfoGsm; import android.telephony.CellInfoLte; import android.telephony.CellInfoWcdma; import android.telephony.TelephonyManager; import android.text.TextUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; Loading @@ -60,8 +53,6 @@ import java.net.URL; import java.net.UnknownHostException; import java.util.List; import com.android.internal.R; /** * This class allows captive portal detection on a network. * @hide Loading @@ -71,7 +62,6 @@ public class CaptivePortalTracker extends StateMachine { private static final String TAG = "CaptivePortalTracker"; private static final String DEFAULT_SERVER = "clients3.google.com"; private static final String NOTIFICATION_ID = "CaptivePortal.Notification"; private static final int SOCKET_TIMEOUT_MS = 10000; Loading @@ -93,7 +83,6 @@ public class CaptivePortalTracker extends StateMachine { private String mServer; private String mUrl; private boolean mNotificationShown = false; private boolean mIsCaptivePortalCheckEnabled = false; private IConnectivityManager mConnService; private TelephonyManager mTelephonyManager; Loading Loading @@ -192,12 +181,12 @@ public class CaptivePortalTracker extends StateMachine { private class DefaultState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); setNotificationOff(); } @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); if (DBG) log(getName() + message.toString()); switch (message.what) { case CMD_DETECT_PORTAL: NetworkInfo info = (NetworkInfo) message.obj; Loading @@ -219,24 +208,25 @@ public class CaptivePortalTracker extends StateMachine { private class NoActiveNetworkState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); mNetworkInfo = null; /* Clear any previous notification */ setNotificationVisible(false); } @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); if (DBG) log(getName() + message.toString()); InetAddress server; NetworkInfo info; switch (message.what) { case CMD_CONNECTIVITY_CHANGE: info = (NetworkInfo) message.obj; if (info.getType() == ConnectivityManager.TYPE_WIFI) { if (info.isConnected() && isActiveNetwork(info)) { mNetworkInfo = info; transitionTo(mDelayedCaptiveCheckState); } } else { log(getName() + " not a wifi connectivity change, ignore"); } break; default: return NOT_HANDLED; Loading @@ -248,7 +238,7 @@ public class CaptivePortalTracker extends StateMachine { private class ActiveNetworkState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); setNotificationOff(); } @Override Loading Loading @@ -281,7 +271,6 @@ public class CaptivePortalTracker extends StateMachine { private class DelayedCaptiveCheckState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); Message message = obtainMessage(CMD_DELAYED_CAPTIVE_CHECK, ++mDelayedCheckToken, 0); if (mDeviceProvisioned) { sendMessageDelayed(message, DELAYED_CHECK_INTERVAL_MS); Loading @@ -292,7 +281,7 @@ public class CaptivePortalTracker extends StateMachine { @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); if (DBG) log(getName() + message.toString()); switch (message.what) { case CMD_DELAYED_CAPTIVE_CHECK: if (message.arg1 == mDelayedCheckToken) { Loading @@ -308,7 +297,12 @@ public class CaptivePortalTracker extends StateMachine { if (captive) { // Setup Wizard will assist the user in connecting to a captive // portal, so make the notification visible unless during setup setNotificationVisible(true); try { mConnService.setProvisioningNotificationVisible(true, mNetworkInfo.getType(), mNetworkInfo.getExtraInfo(), mUrl); } catch(RemoteException e) { e.printStackTrace(); } } } else { Intent intent = new Intent( Loading Loading @@ -366,6 +360,15 @@ public class CaptivePortalTracker extends StateMachine { return false; } private void setNotificationOff() { try { mConnService.setProvisioningNotificationVisible(false, ConnectivityManager.TYPE_NONE, null, null); } catch (RemoteException e) { log("setNotificationOff: " + e); } } /** * Do a URL fetch on a known server to see if we get the data we expect. * Measure the response time and broadcast that. Loading Loading @@ -435,77 +438,6 @@ public class CaptivePortalTracker extends StateMachine { return null; } private void setNotificationVisible(boolean visible) { // if it should be hidden and it is already hidden, then noop if (!visible && !mNotificationShown) { if (DBG) log("setNotivicationVisible: false and not shown, so noop"); return; } Resources r = Resources.getSystem(); NotificationManager notificationManager = (NotificationManager) mContext .getSystemService(Context.NOTIFICATION_SERVICE); if (visible) { CharSequence title; CharSequence details; int icon; String url = null; switch (mNetworkInfo.getType()) { case ConnectivityManager.TYPE_WIFI: title = r.getString(R.string.wifi_available_sign_in, 0); details = r.getString(R.string.network_available_sign_in_detailed, mNetworkInfo.getExtraInfo()); icon = R.drawable.stat_notify_wifi_in_range; url = mUrl; break; case ConnectivityManager.TYPE_MOBILE: title = r.getString(R.string.network_available_sign_in, 0); // TODO: Change this to pull from NetworkInfo once a printable // name has been added to it details = mTelephonyManager.getNetworkOperatorName(); icon = R.drawable.stat_notify_rssi_in_range; try { url = mConnService.getMobileProvisioningUrl(); if (TextUtils.isEmpty(url)) { url = mConnService.getMobileRedirectedProvisioningUrl(); } } catch(RemoteException e) { e.printStackTrace(); } if (TextUtils.isEmpty(url)) { url = mUrl; } break; default: title = r.getString(R.string.network_available_sign_in, 0); details = r.getString(R.string.network_available_sign_in_detailed, mNetworkInfo.getExtraInfo()); icon = R.drawable.stat_notify_rssi_in_range; url = mUrl; break; } Notification notification = new Notification(); notification.when = 0; notification.icon = icon; notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0); notification.tickerText = title; notification.setLatestEventInfo(mContext, title, details, notification.contentIntent); if (DBG) log("setNotivicationVisible: make visible"); notificationManager.notify(NOTIFICATION_ID, 1, notification); } else { if (DBG) log("setNotivicationVisible: cancel notification"); notificationManager.cancel(NOTIFICATION_ID, 1); } mNotificationShown = visible; } private void sendFailedCaptivePortalCheckBroadcast(long requestTimestampMs) { sendNetworkConditionsBroadcast(false /* response received */, false /* ignored */, requestTimestampMs, 0 /* ignored */); Loading core/java/android/net/ConnectivityManager.java +42 −47 Original line number Diff line number Diff line Loading @@ -623,6 +623,29 @@ public class ConnectivityManager { } } /** * Returns details about the Provisioning or currently active default data network. When * connected, this network is the default route for outgoing connections. * You should always check {@link NetworkInfo#isConnected()} before initiating * network traffic. This may return {@code null} when there is no default * network. * * @return a {@link NetworkInfo} object for the current default network * or {@code null} if no network default network is currently active * * <p>This method requires the call to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * {@hide} */ public NetworkInfo getProvisioningOrActiveNetworkInfo() { try { return mService.getProvisioningOrActiveNetworkInfo(); } catch (RemoteException e) { return null; } } /** * Returns the IP information for the current default network. * Loading Loading @@ -1357,63 +1380,19 @@ public class ConnectivityManager { } /** * The ResultReceiver resultCode for checkMobileProvisioning (CMP_RESULT_CODE) */ /** * No connection was possible to the network. * {@hide} */ public static final int CMP_RESULT_CODE_NO_CONNECTION = 0; /** * A connection was made to the internet, all is well. * {@hide} */ public static final int CMP_RESULT_CODE_CONNECTABLE = 1; /** * A connection was made but there was a redirection, we appear to be in walled garden. * This is an indication of a warm sim on a mobile network. * {@hide} */ public static final int CMP_RESULT_CODE_REDIRECTED = 2; /** * A connection was made but no dns server was available to resolve a name to address. * This is an indication of a warm sim on a mobile network. * Check mobile provisioning. * * {@hide} */ public static final int CMP_RESULT_CODE_NO_DNS = 3; /** * A connection was made but could not open a TCP connection. * This is an indication of a warm sim on a mobile network. * {@hide} */ public static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 4; /** * Check mobile provisioning. The resultCode passed to * onReceiveResult will be one of the CMP_RESULT_CODE_xxxx values above. * This may take a minute or more to complete. * * @param sendNotificaiton, when true a notification will be sent to user. * @param suggestedTimeOutMs, timeout in milliseconds * @param resultReceiver needs to be supplied to receive the result * * @return time out that will be used, maybe less that suggestedTimeOutMs * -1 if an error. * * {@hide} */ public int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs, ResultReceiver resultReceiver) { public int checkMobileProvisioning(int suggestedTimeOutMs) { int timeOutMs = -1; try { timeOutMs = mService.checkMobileProvisioning(sendNotification, suggestedTimeOutMs, resultReceiver); timeOutMs = mService.checkMobileProvisioning(suggestedTimeOutMs); } catch (RemoteException e) { } return timeOutMs; Loading Loading @@ -1481,4 +1460,20 @@ public class ConnectivityManager { return null; } } /** * Set sign in error notification to visible or in visible * * @param visible * @param networkType * * {@hide} */ public void setProvisioningNotificationVisible(boolean visible, int networkType, String extraInfo, String url) { try { mService.setProvisioningNotificationVisible(visible, networkType, extraInfo, url); } catch (RemoteException e) { } } } core/java/android/net/IConnectivityManager.aidl +4 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ interface IConnectivityManager NetworkInfo getNetworkInfo(int networkType); NetworkInfo[] getAllNetworkInfo(); NetworkInfo getProvisioningOrActiveNetworkInfo(); boolean isNetworkSupported(int networkType); LinkProperties getActiveLinkProperties(); Loading Loading @@ -141,7 +143,7 @@ interface IConnectivityManager int findConnectionTypeForIface(in String iface); int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs, in ResultReceiver resultReceiver); int checkMobileProvisioning(int suggestedTimeOutMs); String getMobileProvisioningUrl(); Loading @@ -153,4 +155,5 @@ interface IConnectivityManager LinkInfo[] getAllLinkInfo(); void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo, in String url); } core/java/android/net/MobileDataStateTracker.java +80 −14 Original line number Diff line number Diff line Loading @@ -61,8 +61,12 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { private ITelephony mPhoneService; private String mApnType; private NetworkInfo mNetworkInfo; private boolean mTeardownRequested = false; private Handler mTarget; private Context mContext; private LinkProperties mLinkProperties; private LinkCapabilities mLinkCapabilities; private boolean mPrivateDnsRouteSet = false; private boolean mDefaultRouteSet = false; Loading Loading @@ -106,6 +110,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { IntentFilter filter = new IntentFilter(); filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN); filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); mContext.registerReceiver(new MobileDataStateReceiver(), filter); Loading Loading @@ -184,10 +189,41 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { public void releaseWakeLock() { } private void updateLinkProperitesAndCapatilities(Intent intent) { mLinkProperties = intent.getParcelableExtra( PhoneConstants.DATA_LINK_PROPERTIES_KEY); if (mLinkProperties == null) { loge("CONNECTED event did not supply link properties."); mLinkProperties = new LinkProperties(); } mLinkCapabilities = intent.getParcelableExtra( PhoneConstants.DATA_LINK_CAPABILITIES_KEY); if (mLinkCapabilities == null) { loge("CONNECTED event did not supply link capabilities."); mLinkCapabilities = new LinkCapabilities(); } } private class MobileDataStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(TelephonyIntents. ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN)) { String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY); String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY); if (!TextUtils.equals(mApnType, apnType)) { return; } if (DBG) { log("Broadcast received: " + intent.getAction() + " apnType=" + apnType + " apnName=" + apnName); } // Make us in the connecting state until we make a new TYPE_MOBILE_PROVISIONING mMobileDataState = PhoneConstants.DataState.CONNECTING; updateLinkProperitesAndCapatilities(intent); setDetailedState(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, "", apnName); } else if (intent.getAction().equals(TelephonyIntents. ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY); if (VDBG) { Loading Loading @@ -249,18 +285,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { setDetailedState(DetailedState.SUSPENDED, reason, apnName); break; case CONNECTED: mLinkProperties = intent.getParcelableExtra( PhoneConstants.DATA_LINK_PROPERTIES_KEY); if (mLinkProperties == null) { loge("CONNECTED event did not supply link properties."); mLinkProperties = new LinkProperties(); } mLinkCapabilities = intent.getParcelableExtra( PhoneConstants.DATA_LINK_CAPABILITIES_KEY); if (mLinkCapabilities == null) { loge("CONNECTED event did not supply link capabilities."); mLinkCapabilities = new LinkCapabilities(); } updateLinkProperitesAndCapatilities(intent); setDetailedState(DetailedState.CONNECTED, reason, apnName); break; } Loading Loading @@ -319,8 +344,8 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { String reason = intent.getStringExtra(PhoneConstants.FAILURE_REASON_KEY); String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY); if (DBG) { log("Received " + intent.getAction() + " broadcast" + (reason == null ? "" : "(" + reason + ")")); log("Broadcast received: " + intent.getAction() + " reason=" + reason == null ? "null" : reason); } setDetailedState(DetailedState.FAILED, reason, apnName); } else { Loading Loading @@ -412,6 +437,13 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { return (setEnableApn(mApnType, false) != PhoneConstants.APN_REQUEST_FAILED); } /** * @return true if this is ready to operate */ public boolean isReady() { return mDataConnectionTrackerAc != null; } @Override public void captivePortalCheckComplete() { // not implemented Loading Loading @@ -574,6 +606,40 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { } } /** * Inform DCT mobile provisioning has started, it ends when provisioning completes. */ public void enableMobileProvisioning(String url) { if (DBG) log("enableMobileProvisioning(url=" + url + ")"); final AsyncChannel channel = mDataConnectionTrackerAc; if (channel != null) { Message msg = Message.obtain(); msg.what = DctConstants.CMD_ENABLE_MOBILE_PROVISIONING; msg.setData(Bundle.forPair(DctConstants.PROVISIONING_URL_KEY, url)); channel.sendMessage(msg); } } /** * Return if this network is the provisioning network. Valid only if connected. * @param met */ public boolean isProvisioningNetwork() { boolean retVal; try { Message msg = Message.obtain(); msg.what = DctConstants.CMD_IS_PROVISIONING_APN; msg.setData(Bundle.forPair(DctConstants.APN_TYPE_KEY, mApnType)); Message result = mDataConnectionTrackerAc.sendMessageSynchronously(msg); retVal = result.arg1 == DctConstants.ENABLED; } catch (NullPointerException e) { loge("isProvisioningNetwork: X " + e); retVal = false; } if (DBG) log("isProvisioningNetwork: retVal=" + retVal); return retVal; } @Override public void addStackedLink(LinkProperties link) { mLinkProperties.addStackedLink(link); Loading core/java/android/net/NetworkInfo.java +7 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,12 @@ public class NetworkInfo implements Parcelable { VERIFYING_POOR_LINK, /** Checking if network is a captive portal */ CAPTIVE_PORTAL_CHECK, /** * Network is connected to provisioning network * TODO: Probably not needed when we add TYPE_PROVISIONING_NETWORK * @hide */ CONNECTED_TO_PROVISIONING_NETWORK } /** Loading @@ -108,6 +114,7 @@ public class NetworkInfo implements Parcelable { stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED); stateMap.put(DetailedState.FAILED, State.DISCONNECTED); stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED); stateMap.put(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, State.CONNECTED); } private int mNetworkType; Loading Loading
core/java/android/net/CaptivePortalTracker.java +27 −95 Original line number Diff line number Diff line Loading @@ -16,22 +16,16 @@ package android.net; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.UserHandle; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; Loading @@ -46,7 +40,6 @@ import android.telephony.CellInfoGsm; import android.telephony.CellInfoLte; import android.telephony.CellInfoWcdma; import android.telephony.TelephonyManager; import android.text.TextUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; Loading @@ -60,8 +53,6 @@ import java.net.URL; import java.net.UnknownHostException; import java.util.List; import com.android.internal.R; /** * This class allows captive portal detection on a network. * @hide Loading @@ -71,7 +62,6 @@ public class CaptivePortalTracker extends StateMachine { private static final String TAG = "CaptivePortalTracker"; private static final String DEFAULT_SERVER = "clients3.google.com"; private static final String NOTIFICATION_ID = "CaptivePortal.Notification"; private static final int SOCKET_TIMEOUT_MS = 10000; Loading @@ -93,7 +83,6 @@ public class CaptivePortalTracker extends StateMachine { private String mServer; private String mUrl; private boolean mNotificationShown = false; private boolean mIsCaptivePortalCheckEnabled = false; private IConnectivityManager mConnService; private TelephonyManager mTelephonyManager; Loading Loading @@ -192,12 +181,12 @@ public class CaptivePortalTracker extends StateMachine { private class DefaultState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); setNotificationOff(); } @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); if (DBG) log(getName() + message.toString()); switch (message.what) { case CMD_DETECT_PORTAL: NetworkInfo info = (NetworkInfo) message.obj; Loading @@ -219,24 +208,25 @@ public class CaptivePortalTracker extends StateMachine { private class NoActiveNetworkState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); mNetworkInfo = null; /* Clear any previous notification */ setNotificationVisible(false); } @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); if (DBG) log(getName() + message.toString()); InetAddress server; NetworkInfo info; switch (message.what) { case CMD_CONNECTIVITY_CHANGE: info = (NetworkInfo) message.obj; if (info.getType() == ConnectivityManager.TYPE_WIFI) { if (info.isConnected() && isActiveNetwork(info)) { mNetworkInfo = info; transitionTo(mDelayedCaptiveCheckState); } } else { log(getName() + " not a wifi connectivity change, ignore"); } break; default: return NOT_HANDLED; Loading @@ -248,7 +238,7 @@ public class CaptivePortalTracker extends StateMachine { private class ActiveNetworkState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); setNotificationOff(); } @Override Loading Loading @@ -281,7 +271,6 @@ public class CaptivePortalTracker extends StateMachine { private class DelayedCaptiveCheckState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); Message message = obtainMessage(CMD_DELAYED_CAPTIVE_CHECK, ++mDelayedCheckToken, 0); if (mDeviceProvisioned) { sendMessageDelayed(message, DELAYED_CHECK_INTERVAL_MS); Loading @@ -292,7 +281,7 @@ public class CaptivePortalTracker extends StateMachine { @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); if (DBG) log(getName() + message.toString()); switch (message.what) { case CMD_DELAYED_CAPTIVE_CHECK: if (message.arg1 == mDelayedCheckToken) { Loading @@ -308,7 +297,12 @@ public class CaptivePortalTracker extends StateMachine { if (captive) { // Setup Wizard will assist the user in connecting to a captive // portal, so make the notification visible unless during setup setNotificationVisible(true); try { mConnService.setProvisioningNotificationVisible(true, mNetworkInfo.getType(), mNetworkInfo.getExtraInfo(), mUrl); } catch(RemoteException e) { e.printStackTrace(); } } } else { Intent intent = new Intent( Loading Loading @@ -366,6 +360,15 @@ public class CaptivePortalTracker extends StateMachine { return false; } private void setNotificationOff() { try { mConnService.setProvisioningNotificationVisible(false, ConnectivityManager.TYPE_NONE, null, null); } catch (RemoteException e) { log("setNotificationOff: " + e); } } /** * Do a URL fetch on a known server to see if we get the data we expect. * Measure the response time and broadcast that. Loading Loading @@ -435,77 +438,6 @@ public class CaptivePortalTracker extends StateMachine { return null; } private void setNotificationVisible(boolean visible) { // if it should be hidden and it is already hidden, then noop if (!visible && !mNotificationShown) { if (DBG) log("setNotivicationVisible: false and not shown, so noop"); return; } Resources r = Resources.getSystem(); NotificationManager notificationManager = (NotificationManager) mContext .getSystemService(Context.NOTIFICATION_SERVICE); if (visible) { CharSequence title; CharSequence details; int icon; String url = null; switch (mNetworkInfo.getType()) { case ConnectivityManager.TYPE_WIFI: title = r.getString(R.string.wifi_available_sign_in, 0); details = r.getString(R.string.network_available_sign_in_detailed, mNetworkInfo.getExtraInfo()); icon = R.drawable.stat_notify_wifi_in_range; url = mUrl; break; case ConnectivityManager.TYPE_MOBILE: title = r.getString(R.string.network_available_sign_in, 0); // TODO: Change this to pull from NetworkInfo once a printable // name has been added to it details = mTelephonyManager.getNetworkOperatorName(); icon = R.drawable.stat_notify_rssi_in_range; try { url = mConnService.getMobileProvisioningUrl(); if (TextUtils.isEmpty(url)) { url = mConnService.getMobileRedirectedProvisioningUrl(); } } catch(RemoteException e) { e.printStackTrace(); } if (TextUtils.isEmpty(url)) { url = mUrl; } break; default: title = r.getString(R.string.network_available_sign_in, 0); details = r.getString(R.string.network_available_sign_in_detailed, mNetworkInfo.getExtraInfo()); icon = R.drawable.stat_notify_rssi_in_range; url = mUrl; break; } Notification notification = new Notification(); notification.when = 0; notification.icon = icon; notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0); notification.tickerText = title; notification.setLatestEventInfo(mContext, title, details, notification.contentIntent); if (DBG) log("setNotivicationVisible: make visible"); notificationManager.notify(NOTIFICATION_ID, 1, notification); } else { if (DBG) log("setNotivicationVisible: cancel notification"); notificationManager.cancel(NOTIFICATION_ID, 1); } mNotificationShown = visible; } private void sendFailedCaptivePortalCheckBroadcast(long requestTimestampMs) { sendNetworkConditionsBroadcast(false /* response received */, false /* ignored */, requestTimestampMs, 0 /* ignored */); Loading
core/java/android/net/ConnectivityManager.java +42 −47 Original line number Diff line number Diff line Loading @@ -623,6 +623,29 @@ public class ConnectivityManager { } } /** * Returns details about the Provisioning or currently active default data network. When * connected, this network is the default route for outgoing connections. * You should always check {@link NetworkInfo#isConnected()} before initiating * network traffic. This may return {@code null} when there is no default * network. * * @return a {@link NetworkInfo} object for the current default network * or {@code null} if no network default network is currently active * * <p>This method requires the call to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * {@hide} */ public NetworkInfo getProvisioningOrActiveNetworkInfo() { try { return mService.getProvisioningOrActiveNetworkInfo(); } catch (RemoteException e) { return null; } } /** * Returns the IP information for the current default network. * Loading Loading @@ -1357,63 +1380,19 @@ public class ConnectivityManager { } /** * The ResultReceiver resultCode for checkMobileProvisioning (CMP_RESULT_CODE) */ /** * No connection was possible to the network. * {@hide} */ public static final int CMP_RESULT_CODE_NO_CONNECTION = 0; /** * A connection was made to the internet, all is well. * {@hide} */ public static final int CMP_RESULT_CODE_CONNECTABLE = 1; /** * A connection was made but there was a redirection, we appear to be in walled garden. * This is an indication of a warm sim on a mobile network. * {@hide} */ public static final int CMP_RESULT_CODE_REDIRECTED = 2; /** * A connection was made but no dns server was available to resolve a name to address. * This is an indication of a warm sim on a mobile network. * Check mobile provisioning. * * {@hide} */ public static final int CMP_RESULT_CODE_NO_DNS = 3; /** * A connection was made but could not open a TCP connection. * This is an indication of a warm sim on a mobile network. * {@hide} */ public static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 4; /** * Check mobile provisioning. The resultCode passed to * onReceiveResult will be one of the CMP_RESULT_CODE_xxxx values above. * This may take a minute or more to complete. * * @param sendNotificaiton, when true a notification will be sent to user. * @param suggestedTimeOutMs, timeout in milliseconds * @param resultReceiver needs to be supplied to receive the result * * @return time out that will be used, maybe less that suggestedTimeOutMs * -1 if an error. * * {@hide} */ public int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs, ResultReceiver resultReceiver) { public int checkMobileProvisioning(int suggestedTimeOutMs) { int timeOutMs = -1; try { timeOutMs = mService.checkMobileProvisioning(sendNotification, suggestedTimeOutMs, resultReceiver); timeOutMs = mService.checkMobileProvisioning(suggestedTimeOutMs); } catch (RemoteException e) { } return timeOutMs; Loading Loading @@ -1481,4 +1460,20 @@ public class ConnectivityManager { return null; } } /** * Set sign in error notification to visible or in visible * * @param visible * @param networkType * * {@hide} */ public void setProvisioningNotificationVisible(boolean visible, int networkType, String extraInfo, String url) { try { mService.setProvisioningNotificationVisible(visible, networkType, extraInfo, url); } catch (RemoteException e) { } } }
core/java/android/net/IConnectivityManager.aidl +4 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ interface IConnectivityManager NetworkInfo getNetworkInfo(int networkType); NetworkInfo[] getAllNetworkInfo(); NetworkInfo getProvisioningOrActiveNetworkInfo(); boolean isNetworkSupported(int networkType); LinkProperties getActiveLinkProperties(); Loading Loading @@ -141,7 +143,7 @@ interface IConnectivityManager int findConnectionTypeForIface(in String iface); int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs, in ResultReceiver resultReceiver); int checkMobileProvisioning(int suggestedTimeOutMs); String getMobileProvisioningUrl(); Loading @@ -153,4 +155,5 @@ interface IConnectivityManager LinkInfo[] getAllLinkInfo(); void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo, in String url); }
core/java/android/net/MobileDataStateTracker.java +80 −14 Original line number Diff line number Diff line Loading @@ -61,8 +61,12 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { private ITelephony mPhoneService; private String mApnType; private NetworkInfo mNetworkInfo; private boolean mTeardownRequested = false; private Handler mTarget; private Context mContext; private LinkProperties mLinkProperties; private LinkCapabilities mLinkCapabilities; private boolean mPrivateDnsRouteSet = false; private boolean mDefaultRouteSet = false; Loading Loading @@ -106,6 +110,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { IntentFilter filter = new IntentFilter(); filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN); filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); mContext.registerReceiver(new MobileDataStateReceiver(), filter); Loading Loading @@ -184,10 +189,41 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { public void releaseWakeLock() { } private void updateLinkProperitesAndCapatilities(Intent intent) { mLinkProperties = intent.getParcelableExtra( PhoneConstants.DATA_LINK_PROPERTIES_KEY); if (mLinkProperties == null) { loge("CONNECTED event did not supply link properties."); mLinkProperties = new LinkProperties(); } mLinkCapabilities = intent.getParcelableExtra( PhoneConstants.DATA_LINK_CAPABILITIES_KEY); if (mLinkCapabilities == null) { loge("CONNECTED event did not supply link capabilities."); mLinkCapabilities = new LinkCapabilities(); } } private class MobileDataStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(TelephonyIntents. ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN)) { String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY); String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY); if (!TextUtils.equals(mApnType, apnType)) { return; } if (DBG) { log("Broadcast received: " + intent.getAction() + " apnType=" + apnType + " apnName=" + apnName); } // Make us in the connecting state until we make a new TYPE_MOBILE_PROVISIONING mMobileDataState = PhoneConstants.DataState.CONNECTING; updateLinkProperitesAndCapatilities(intent); setDetailedState(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, "", apnName); } else if (intent.getAction().equals(TelephonyIntents. ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY); if (VDBG) { Loading Loading @@ -249,18 +285,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { setDetailedState(DetailedState.SUSPENDED, reason, apnName); break; case CONNECTED: mLinkProperties = intent.getParcelableExtra( PhoneConstants.DATA_LINK_PROPERTIES_KEY); if (mLinkProperties == null) { loge("CONNECTED event did not supply link properties."); mLinkProperties = new LinkProperties(); } mLinkCapabilities = intent.getParcelableExtra( PhoneConstants.DATA_LINK_CAPABILITIES_KEY); if (mLinkCapabilities == null) { loge("CONNECTED event did not supply link capabilities."); mLinkCapabilities = new LinkCapabilities(); } updateLinkProperitesAndCapatilities(intent); setDetailedState(DetailedState.CONNECTED, reason, apnName); break; } Loading Loading @@ -319,8 +344,8 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { String reason = intent.getStringExtra(PhoneConstants.FAILURE_REASON_KEY); String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY); if (DBG) { log("Received " + intent.getAction() + " broadcast" + (reason == null ? "" : "(" + reason + ")")); log("Broadcast received: " + intent.getAction() + " reason=" + reason == null ? "null" : reason); } setDetailedState(DetailedState.FAILED, reason, apnName); } else { Loading Loading @@ -412,6 +437,13 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { return (setEnableApn(mApnType, false) != PhoneConstants.APN_REQUEST_FAILED); } /** * @return true if this is ready to operate */ public boolean isReady() { return mDataConnectionTrackerAc != null; } @Override public void captivePortalCheckComplete() { // not implemented Loading Loading @@ -574,6 +606,40 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker { } } /** * Inform DCT mobile provisioning has started, it ends when provisioning completes. */ public void enableMobileProvisioning(String url) { if (DBG) log("enableMobileProvisioning(url=" + url + ")"); final AsyncChannel channel = mDataConnectionTrackerAc; if (channel != null) { Message msg = Message.obtain(); msg.what = DctConstants.CMD_ENABLE_MOBILE_PROVISIONING; msg.setData(Bundle.forPair(DctConstants.PROVISIONING_URL_KEY, url)); channel.sendMessage(msg); } } /** * Return if this network is the provisioning network. Valid only if connected. * @param met */ public boolean isProvisioningNetwork() { boolean retVal; try { Message msg = Message.obtain(); msg.what = DctConstants.CMD_IS_PROVISIONING_APN; msg.setData(Bundle.forPair(DctConstants.APN_TYPE_KEY, mApnType)); Message result = mDataConnectionTrackerAc.sendMessageSynchronously(msg); retVal = result.arg1 == DctConstants.ENABLED; } catch (NullPointerException e) { loge("isProvisioningNetwork: X " + e); retVal = false; } if (DBG) log("isProvisioningNetwork: retVal=" + retVal); return retVal; } @Override public void addStackedLink(LinkProperties link) { mLinkProperties.addStackedLink(link); Loading
core/java/android/net/NetworkInfo.java +7 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,12 @@ public class NetworkInfo implements Parcelable { VERIFYING_POOR_LINK, /** Checking if network is a captive portal */ CAPTIVE_PORTAL_CHECK, /** * Network is connected to provisioning network * TODO: Probably not needed when we add TYPE_PROVISIONING_NETWORK * @hide */ CONNECTED_TO_PROVISIONING_NETWORK } /** Loading @@ -108,6 +114,7 @@ public class NetworkInfo implements Parcelable { stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED); stateMap.put(DetailedState.FAILED, State.DISCONNECTED); stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED); stateMap.put(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, State.CONNECTED); } private int mNetworkType; Loading