Separate wifi AP added by applications.
-Add field for tracking user approval of application added networks.
-Add WifiConfig fields for creating/updating application name
-Add permission to allow system apps to modify any network

Bug: 16953082

Change-Id: I12943563ef714c4287e13488578f020d136d006d
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 965f391..1cb7796 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -832,6 +832,14 @@
         android:permissionGroup="android.permission-group.NETWORK"
         android:protectionLevel="signature|system" />
 
+    <!-- @SystemApi @hide Allows an application to modify any wifi configuration, even if created
+	 by another application. Once reconfigured the original creator canot make any further
+	 modifications.
+	 <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
+	android:permissionGroup="android.permission-group.NETWORK"
+	android:protectionLevel="signature|system" />
+
     <!-- @hide -->
     <permission android:name="android.permission.ACCESS_WIMAX_STATE"
         android:permissionGroup="android.permission-group.NETWORK"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 83b65b2..ed4c021 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3620,6 +3620,14 @@
     <!-- Do not translate. Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
 
+    <!-- A notification is shown the first time a connection is attempted on an app owned AP -->
+    <!-- title for this message -->
+    <string name="wifi_connect_alert_title">Allow connection?</string>
+    <!-- message explaining who is connecting to what -->
+    <string name="wifi_connect_alert_message">%1$s would like to connect to %2$s</string>
+    <!-- default application in case name can not be found -->
+    <string name="wifi_connect_default_application">An application</string>
+
     <string name="wifi_p2p_dialog_title">Wi-Fi Direct</string>
     <string name="wifi_p2p_turnon_message">Start Wi-Fi Direct. This will turn off Wi-Fi client/hotspot.</string>
     <string name="wifi_p2p_failed_message">Couldn\'t start Wi-Fi Direct.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d5e4395..cb8bd6d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -898,6 +898,9 @@
   <java-symbol type="string" name="wifi_available_sign_in" />
   <java-symbol type="string" name="network_available_sign_in" />
   <java-symbol type="string" name="network_available_sign_in_detailed" />
+  <java-symbol type="string" name="wifi_connect_alert_title" />
+  <java-symbol type="string" name="wifi_connect_alert_message" />
+  <java-symbol type="string" name="wifi_connect_default_application" />
   <java-symbol type="string" name="wifi_p2p_dialog_title" />
   <java-symbol type="string" name="wifi_p2p_enabled_notification_message" />
   <java-symbol type="string" name="wifi_p2p_enabled_notification_title" />
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 4f5f31a..4e2b64b 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -17,6 +17,7 @@
 package android.net.wifi;
 
 import android.annotation.SystemApi;
+import android.content.pm.PackageManager;
 import android.net.IpConfiguration;
 import android.net.IpConfiguration.ProxySettings;
 import android.net.IpConfiguration.IpAssignment;
@@ -375,12 +376,34 @@
 
     /**
      * @hide
+     * Universal name for app creating the configuration
+     *    see {#link {@link PackageManager#getNameForUid(int)}
+     */
+    @SystemApi
+    public String creatorName;
+
+    /**
+     * @hide
+     * Universal name for app updating the configuration
+     *    see {#link {@link PackageManager#getNameForUid(int)}
+     */
+    @SystemApi
+    public String lastUpdateName;
+
+    /**
+     * @hide
      * Uid used by autoJoin
      */
     public String autoJoinBSSID;
 
     /**
      * @hide
+     * Status of user approval for connection
+     */
+    public int userApproved = USER_UNSPECIFIED;
+
+    /**
+     * @hide
      * BSSID list on which this configuration was seen.
      * TODO: prevent this list to grow infinitely, age-out the results
      */
@@ -614,6 +637,28 @@
     /** @hide */
     public static final int AUTO_JOIN_DELETED  = 200;
 
+    // States for the userApproved field
+    /**
+     * @hide
+     * User hasn't specified if connection is okay
+     */
+    public static final int USER_UNSPECIFIED = 0;
+    /**
+     * @hide
+     * User has approved this for connection
+     */
+    public static final int USER_APPROVED = 1;
+    /**
+     * @hide
+     * User has banned this from connection
+     */
+    public static final int USER_BANNED = 2;
+    /**
+     * @hide
+     * Waiting for user input
+     */
+    public static final int USER_PENDING = 3;
+
     /**
      * @hide
      */
@@ -826,6 +871,8 @@
         ephemeral = false;
         noInternetAccess = false;
         mIpConfiguration = new IpConfiguration();
+        lastUpdateUid = -1;
+        creatorUid = -1;
     }
 
     /**
@@ -1012,7 +1059,6 @@
         sbuf.append("IP config:\n");
         sbuf.append(mIpConfiguration.toString());
 
-        if (this.creatorUid != 0)  sbuf.append(" uid=" + Integer.toString(creatorUid));
         if (this.autoJoinBSSID != null) sbuf.append(" autoJoinBSSID=" + autoJoinBSSID);
         long now_ms = System.currentTimeMillis();
         if (this.blackListTimestamp != 0) {
@@ -1024,6 +1070,12 @@
                 sbuf.append(" blackListed: ").append(Long.toString(diff/1000)).append( "sec");
             }
         }
+        if (creatorUid != 0)  sbuf.append(" cuid=" + Integer.toString(creatorUid));
+        if (creatorName != null) sbuf.append(" cname=" + creatorName);
+        if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid);
+        if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName);
+        sbuf.append("userApproved=" + userApprovedAsString(userApproved));
+
         if (this.lastConnected != 0) {
             sbuf.append('\n');
             long diff = now_ms - this.lastConnected;
@@ -1128,6 +1180,20 @@
         return SSID;
     }
 
+    /** @hide **/
+    public static String userApprovedAsString(int userApproved) {
+        switch (userApproved) {
+            case USER_APPROVED:
+                return "USER_APPROVED";
+            case USER_BANNED:
+                return "USER_BANNED";
+            case USER_UNSPECIFIED:
+                return "USER_UNSPECIFIED";
+            default:
+                return "INVALID";
+        }
+    }
+
     /**
      * Get an identifier for associating credentials with this config
      * @param current configuration contains values for additional fields
@@ -1390,6 +1456,8 @@
             lastConnectUid = source.lastConnectUid;
             lastUpdateUid = source.lastUpdateUid;
             creatorUid = source.creatorUid;
+            creatorName = source.creatorName;
+            lastUpdateName = source.lastUpdateName;
             peerWifiConfiguration = source.peerWifiConfiguration;
             blackListTimestamp = source.blackListTimestamp;
             lastConnected = source.lastConnected;
@@ -1413,6 +1481,7 @@
                     = source.autoJoinUseAggressiveJoinAttemptThreshold;
             autoJoinBailedDueToLowRssi = source.autoJoinBailedDueToLowRssi;
             dirty = source.dirty;
+            userApproved = source.userApproved;
         }
     }
 
@@ -1460,6 +1529,8 @@
         dest.writeInt(creatorUid);
         dest.writeInt(lastConnectUid);
         dest.writeInt(lastUpdateUid);
+        dest.writeString(creatorName);
+        dest.writeString(lastUpdateName);
         dest.writeLong(blackListTimestamp);
         dest.writeLong(lastConnectionFailure);
         dest.writeInt(numConnectionFailures);
@@ -1477,6 +1548,7 @@
         dest.writeInt(numUserTriggeredJoinAttempts);
         dest.writeInt(autoJoinUseAggressiveJoinAttemptThreshold);
         dest.writeInt(autoJoinBailedDueToLowRssi ? 1 : 0);
+        dest.writeInt(userApproved);
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -1520,6 +1592,8 @@
                 config.creatorUid = in.readInt();
                 config.lastConnectUid = in.readInt();
                 config.lastUpdateUid = in.readInt();
+                config.creatorName = in.readString();
+                config.lastUpdateName = in.readString();
                 config.blackListTimestamp = in.readLong();
                 config.lastConnectionFailure = in.readLong();
                 config.numConnectionFailures = in.readInt();
@@ -1537,6 +1611,7 @@
                 config.numUserTriggeredJoinAttempts = in.readInt();
                 config.autoJoinUseAggressiveJoinAttemptThreshold = in.readInt();
                 config.autoJoinBailedDueToLowRssi = in.readInt() != 0;
+                config.userApproved = in.readInt();
                 return config;
             }