From 49e3edff5156f471819e4ea2a88994bca70bd870 Mon Sep 17 00:00:00 2001 From: Paul Jensen Date: Fri, 22 May 2015 10:50:39 -0400 Subject: Add android.net.CaptivePortal class for captive-portal-handling-app callbacks This new class replaces the awkward string token and ConnectivityManager APIs used by apps handling captive portals. Bug:21343774 Change-Id: I1a2c69edb17322715bf8422bb4216b0ea60bfd59 --- Android.mk | 1 + api/current.txt | 12 ++- api/system-current.txt | 12 ++- core/java/android/net/CaptivePortal.java | 108 +++++++++++++++++++ core/java/android/net/ConnectivityManager.java | 119 ++++----------------- core/java/android/net/ICaptivePortal.aidl | 26 +++++ core/java/android/net/IConnectivityManager.aidl | 2 - .../CaptivePortalLoginActivity.java | 11 +- .../com/android/server/ConnectivityService.java | 10 -- .../server/connectivity/NetworkMonitor.java | 41 ++++--- 10 files changed, 205 insertions(+), 137 deletions(-) create mode 100644 core/java/android/net/CaptivePortal.java create mode 100644 core/java/android/net/ICaptivePortal.aidl diff --git a/Android.mk b/Android.mk index e96a932..1de3625 100644 --- a/Android.mk +++ b/Android.mk @@ -181,6 +181,7 @@ LOCAL_SRC_FILES += \ core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \ core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl \ core/java/android/hardware/usb/IUsbManager.aidl \ + core/java/android/net/ICaptivePortal.aidl \ core/java/android/net/IConnectivityManager.aidl \ core/java/android/net/IEthernetManager.aidl \ core/java/android/net/IEthernetServiceListener.aidl \ diff --git a/api/current.txt b/api/current.txt index 8a82ed0..d197f3d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -18115,6 +18115,14 @@ package android.mtp { package android.net { + public class CaptivePortal implements android.os.Parcelable { + method public int describeContents(); + method public void ignoreNetwork(); + method public void reportCaptivePortalDismissed(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public class ConnectivityManager { method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); method public boolean bindProcessToNetwork(android.net.Network); @@ -18131,7 +18139,6 @@ package android.net { 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 deprecated boolean isNetworkTypeValid(int); @@ -18140,7 +18147,6 @@ package android.net { 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 boolean requestBandwidthUpdate(android.net.Network); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback); @@ -18152,7 +18158,7 @@ package android.net { 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_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL"; 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"; diff --git a/api/system-current.txt b/api/system-current.txt index a382fb0..b91069a 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -19630,6 +19630,14 @@ package android.mtp { package android.net { + public class CaptivePortal implements android.os.Parcelable { + method public int describeContents(); + method public void ignoreNetwork(); + method public void reportCaptivePortalDismissed(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public class ConnectivityManager { method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); method public boolean bindProcessToNetwork(android.net.Network); @@ -19646,7 +19654,6 @@ package android.net { 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 deprecated boolean isNetworkTypeValid(int); @@ -19655,7 +19662,6 @@ package android.net { 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 boolean requestBandwidthUpdate(android.net.Network); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback); @@ -19667,7 +19673,7 @@ package android.net { 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_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL"; 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"; diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java new file mode 100644 index 0000000..ee05f28 --- /dev/null +++ b/core/java/android/net/CaptivePortal.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed urnder the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net; + +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.RemoteException; + +/** + * A class allowing apps handling the {@link ConnectivityManager#ACTION_CAPTIVE_PORTAL_SIGN_IN} + * activity to indicate to the system different outcomes of captive portal sign in. This class is + * passed as an extra named {@link ConnectivityManager#EXTRA_CAPTIVE_PORTAL} with the + * {@code ACTION_CAPTIVE_PORTAL_SIGN_IN} activity. + */ +public class CaptivePortal implements Parcelable { + /** @hide */ + public static final int APP_RETURN_DISMISSED = 0; + /** @hide */ + public static final int APP_RETURN_UNWANTED = 1; + /** @hide */ + public static final int APP_RETURN_WANTED_AS_IS = 2; + + private final IBinder mBinder; + + /** @hide */ + public CaptivePortal(IBinder binder) { + mBinder = binder; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeStrongBinder(mBinder); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + @Override + public CaptivePortal createFromParcel(Parcel in) { + return new CaptivePortal(in.readStrongBinder()); + } + + @Override + public CaptivePortal[] newArray(int size) { + return new CaptivePortal[size]; + } + }; + + /** + * 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. + */ + public void reportCaptivePortalDismissed() { + try { + ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_DISMISSED); + } catch (RemoteException e) { + } + } + + /** + * Indicate to the system that the user does not want to pursue signing in to the + * 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. + */ + public void ignoreNetwork() { + try { + ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_UNWANTED); + } catch (RemoteException e) { + } + } + + /** + * Indicate to the system 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. + * @hide + */ + public void useNetwork() { + try { + ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_WANTED_AS_IS); + } catch (RemoteException e) { + } + } +} diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 80476ea..a1bc417 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -102,26 +102,26 @@ public class ConnectivityManager { * 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 + * desire to sign in to the network. Apps handling this activity 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. *

- * 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. - *

- * When the app handling this action believes the user explicitly wants + * This activity includes a {@link CaptivePortal} extra named + * {@link #EXTRA_CAPTIVE_PORTAL} that can be used to indicate different + * outcomes of the captive portal sign in to the system: + *

    + *
  • 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 CaptivePortal#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.
  • + *
  • 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}. - *

    - * 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}. + * {@link CaptivePortal#ignoreNetwork}.

  • + *
*/ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL"; @@ -187,16 +187,15 @@ public class ConnectivityManager { * {@hide} */ 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)}. + * The lookup key for a {@link CaptivePortal} object included with the + * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN} intent. The {@code CaptivePortal} + * object can be used to either indicate to the system that the captive + * portal has been dismissed or that the user does not want to pursue + * signing in to captive portal. Retrieve it with + * {@link android.content.Intent#getParcelableExtra(String)}. */ - public static final String EXTRA_CAPTIVE_PORTAL_TOKEN = "captivePortalToken"; - + public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL"; /** * Broadcast action to indicate the change of data activity status * (idle or active) on a network in a recent period. @@ -1779,82 +1778,6 @@ public class ConnectivityManager { } } - /** {@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 diff --git a/core/java/android/net/ICaptivePortal.aidl b/core/java/android/net/ICaptivePortal.aidl new file mode 100644 index 0000000..a013e79 --- /dev/null +++ b/core/java/android/net/ICaptivePortal.aidl @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2015, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** + * Interface to inform NetworkMonitor of decisions of app handling captive portal. + * @hide + */ +interface ICaptivePortal +{ + oneway void appResponse(int response); +} diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 29557bb..78f8b95 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -96,8 +96,6 @@ interface IConnectivityManager 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/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index ddbcd78..a489f94 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -21,6 +21,7 @@ import android.app.LoadedApk; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; +import android.net.CaptivePortal; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.Network; @@ -62,7 +63,7 @@ public class CaptivePortalLoginActivity extends Activity { private URL mURL; private Network mNetwork; - private String mResponseToken; + private CaptivePortal mCaptivePortal; private NetworkCallback mNetworkCallback; private ConnectivityManager mCm; private boolean mLaunchBrowser = false; @@ -83,7 +84,7 @@ public class CaptivePortalLoginActivity extends Activity { done(Result.WANTED_AS_IS); } mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK); - mResponseToken = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_TOKEN); + mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL); // Also initializes proxy system properties. mCm.bindProcessToNetwork(mNetwork); @@ -155,13 +156,13 @@ public class CaptivePortalLoginActivity extends Activity { } switch (result) { case DISMISSED: - mCm.reportCaptivePortalDismissed(mNetwork, mResponseToken); + mCaptivePortal.reportCaptivePortalDismissed(); break; case UNWANTED: - mCm.ignoreNetworkWithCaptivePortal(mNetwork, mResponseToken); + mCaptivePortal.ignoreNetwork(); break; case WANTED_AS_IS: - mCm.useNetworkWithCaptivePortal(mNetwork, mResponseToken); + mCaptivePortal.useNetwork(); break; } finish(); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 7f124dc..54d864b 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2733,16 +2733,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - 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); - } - private 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 e472928..a6dc6a3 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -16,6 +16,10 @@ package com.android.server.connectivity; +import static android.net.CaptivePortal.APP_RETURN_DISMISSED; +import static android.net.CaptivePortal.APP_RETURN_UNWANTED; +import static android.net.CaptivePortal.APP_RETURN_WANTED_AS_IS; + import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -23,7 +27,9 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.net.CaptivePortal; import android.net.ConnectivityManager; +import android.net.ICaptivePortal; import android.net.NetworkRequest; import android.net.ProxyInfo; import android.net.TrafficStats; @@ -160,12 +166,12 @@ public class NetworkMonitor extends StateMachine { /** * Message to self indicating captive portal app finished. - * arg1 = one of: CAPTIVE_PORTAL_APP_RETURN_DISMISSED, - * CAPTIVE_PORTAL_APP_RETURN_UNWANTED, - * CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS + * arg1 = one of: APP_RETURN_DISMISSED, + * APP_RETURN_UNWANTED, + * APP_RETURN_WANTED_AS_IS * obj = mCaptivePortalLoggedInResponseToken as String */ - public static final int CMD_CAPTIVE_PORTAL_APP_FINISHED = BASE + 9; + private static final int CMD_CAPTIVE_PORTAL_APP_FINISHED = BASE + 9; /** * Request ConnectivityService display provisioning notification. @@ -234,7 +240,6 @@ public class NetworkMonitor extends StateMachine { private final State mLingeringState = new LingeringState(); private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null; - private String mCaptivePortalLoggedInResponseToken = null; private final LocalLog validationLogs = new LocalLog(20); // 20 lines @@ -268,8 +273,6 @@ public class NetworkMonitor extends StateMachine { mIsCaptivePortalCheckEnabled = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED, 1) == 1; - mCaptivePortalLoggedInResponseToken = String.valueOf(new Random().nextLong()); - start(); } @@ -314,22 +317,18 @@ public class NetworkMonitor extends StateMachine { transitionTo(mEvaluatingState); return HANDLED; case CMD_CAPTIVE_PORTAL_APP_FINISHED: - if (!mCaptivePortalLoggedInResponseToken.equals((String)message.obj)) - return HANDLED; log("CaptivePortal App responded with " + message.arg1); - // Previous token was sent out, come up with a new one. - mCaptivePortalLoggedInResponseToken = String.valueOf(new Random().nextLong()); switch (message.arg1) { - case ConnectivityManager.CAPTIVE_PORTAL_APP_RETURN_DISMISSED: + case APP_RETURN_DISMISSED: sendMessage(CMD_FORCE_REEVALUATION, 0 /* no UID */, 0); break; - case ConnectivityManager.CAPTIVE_PORTAL_APP_RETURN_WANTED_AS_IS: + case APP_RETURN_WANTED_AS_IS: mDontDisplaySigninNotification = true; // 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 ConnectivityManager.CAPTIVE_PORTAL_APP_RETURN_UNWANTED: + case APP_RETURN_UNWANTED: mDontDisplaySigninNotification = true; mUserDoesNotWant = true; mConnectivityServiceHandler.sendMessage(obtainMessage( @@ -380,8 +379,18 @@ public class NetworkMonitor extends StateMachine { 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.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL, + new CaptivePortal(new ICaptivePortal.Stub() { + @Override + public void appResponse(int response) { + if (response == APP_RETURN_WANTED_AS_IS) { + mContext.enforceCallingPermission( + android.Manifest.permission.CONNECTIVITY_INTERNAL, + "CaptivePortal"); + } + sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response); + } + })); intent.setFlags( Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(intent, UserHandle.CURRENT); -- cgit v1.1