Add captive portal API.

This API allows apps other than the system's CaptivePortalLogin
to handle signing in to captive portals.

bug:19416463
Change-Id: I27fce5856b635233e6ff66396d50ccabedd76cf5
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 77765a4..81ff2ab 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -58,24 +58,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) {
@@ -83,23 +72,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.
@@ -108,7 +93,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;
@@ -116,14 +101,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);
@@ -160,15 +145,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();
     }
 
@@ -192,11 +183,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);
@@ -225,7 +216,7 @@
                     if (urlConnection != null) urlConnection.disconnect();
                 }
                 if (httpResponseCode == 204) {
-                    done(CAPTIVE_PORTAL_APP_RETURN_APPEASED);
+                    done(Result.DISMISSED);
                 }
             }
         }).start();