Add legacy VPN support in SL4A. am: 9d9222a94e
am: 31134cd32e

Change-Id: Iddd90337301a2a7bd5ac25299043eb12f9515809
diff --git a/Common/src/com/googlecode/android_scripting/facade/VpnFacade.java b/Common/src/com/googlecode/android_scripting/facade/VpnFacade.java
new file mode 100644
index 0000000..af6dc92
--- /dev/null
+++ b/Common/src/com/googlecode/android_scripting/facade/VpnFacade.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * 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 com.googlecode.android_scripting.facade;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.json.JSONObject;
+
+import com.android.internal.net.LegacyVpnInfo;
+import com.android.internal.net.VpnConfig;
+import com.android.internal.net.VpnProfile;
+import com.android.internal.util.ArrayUtils;
+import com.google.android.collect.Lists;
+import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
+import com.googlecode.android_scripting.rpc.Rpc;
+import com.googlecode.android_scripting.rpc.RpcParameter;
+
+import android.app.Service;
+import android.content.Context;
+import android.net.IConnectivityManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.security.Credentials;
+import android.security.KeyStore;
+
+/**
+ * Access NFC functions.
+ */
+public class VpnFacade extends RpcReceiver {
+
+    private final Service mService;
+    private final IConnectivityManager mConService;
+
+    public VpnFacade(FacadeManager manager) {
+        super(manager);
+        mService = manager.getService();
+        mConService = IConnectivityManager.Stub
+                .asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
+    }
+
+    static List<VpnProfile> loadVpnProfiles(KeyStore keyStore, int... excludeTypes) {
+        final ArrayList<VpnProfile> result = Lists.newArrayList();
+
+        for (String key : keyStore.list(Credentials.VPN)) {
+            final VpnProfile profile = VpnProfile.decode(key, keyStore.get(Credentials.VPN + key));
+            if (profile != null && !ArrayUtils.contains(excludeTypes, profile.type)) {
+                result.add(profile);
+            }
+        }
+        return result;
+    }
+
+    private VpnProfile genLegacyVpnProfile(JSONObject vpnProfileJson) {
+        VpnProfile vp = new VpnProfile(vpnProfileJson.optString("key", ""));
+        vp.name = vpnProfileJson.optString("name", "");
+        vp.type = vpnProfileJson.optInt("type", VpnProfile.TYPE_PPTP);
+        vp.server = vpnProfileJson.optString("server", "");
+        vp.username = vpnProfileJson.optString("username", "");
+        vp.password = vpnProfileJson.optString("password", "");
+        vp.dnsServers = vpnProfileJson.optString("dnsServers", "");
+        vp.searchDomains = vpnProfileJson.optString("searchDomains", "");
+        vp.routes = vpnProfileJson.optString("routes", "");
+        vp.mppe = vpnProfileJson.optBoolean("mppe", true);
+        vp.l2tpSecret = vpnProfileJson.optString("l2tpSecret", "");
+        vp.ipsecIdentifier = vpnProfileJson.optString("ipsecIdentifier", "");
+        vp.ipsecSecret = vpnProfileJson.optString("ipsecSecret", "");
+        vp.ipsecUserCert = vpnProfileJson.optString("ipsecUserCert", "");
+        vp.ipsecCaCert = vpnProfileJson.optString("ipsecCaCert", "");
+        vp.ipsecServerCert = vpnProfileJson.optString("ipsecServerCert", "");
+        vp.saveLogin = vpnProfileJson.optBoolean("saveLogin", false);
+        return vp;
+    }
+
+    @Rpc(description = "Start legacy VPN with a profile.")
+    public void vpnStartLegacyVpn(@RpcParameter(name = "vpnProfile") JSONObject vpnProfile)
+            throws RemoteException {
+        VpnProfile profile = genLegacyVpnProfile(vpnProfile);
+        mConService.startLegacyVpn(profile);
+    }
+
+    @Rpc(description = "Stop the current legacy VPN connection.")
+    public void vpnStopLegacyVpn() throws RemoteException {
+        mConService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, mService.getUserId());
+    }
+
+    @Rpc(description = "Get the info object of the currently active legacy VPN connection.")
+    public LegacyVpnInfo vpnGetLegacyVpnInfo() throws RemoteException {
+        return mConService.getLegacyVpnInfo(mService.getUserId());
+    }
+
+    @Override
+    public void shutdown() {
+    }
+
+}
diff --git a/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java b/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
index f9e83a1..11c4426 100644
--- a/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
+++ b/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
@@ -36,6 +36,15 @@
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import com.android.internal.net.LegacyVpnInfo;
+import com.googlecode.android_scripting.ConvertUtils;
+import com.googlecode.android_scripting.Log;
+import com.googlecode.android_scripting.event.Event;
+//FIXME: Refactor classes, constants and conversions out of here
+import com.googlecode.android_scripting.facade.telephony.InCallServiceImpl;
+import com.googlecode.android_scripting.facade.telephony.TelephonyConstants;
+import com.googlecode.android_scripting.facade.telephony.TelephonyUtils;
+
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothGattCharacteristic;
 import android.bluetooth.BluetoothGattDescriptor;
@@ -84,23 +93,15 @@
 import android.telephony.CellSignalStrengthWcdma;
 import android.telephony.ModemActivityInfo;
 import android.telephony.NeighboringCellInfo;
-import android.telephony.SmsMessage;
 import android.telephony.SignalStrength;
+import android.telephony.SmsMessage;
 import android.telephony.SubscriptionInfo;
-import android.telephony.gsm.GsmCellLocation;
 import android.telephony.VoLteServiceState;
+import android.telephony.gsm.GsmCellLocation;
 import android.util.Base64;
 import android.util.DisplayMetrics;
 import android.util.SparseArray;
 
-import com.googlecode.android_scripting.ConvertUtils;
-import com.googlecode.android_scripting.Log;
-import com.googlecode.android_scripting.event.Event;
-//FIXME: Refactor classes, constants and conversions out of here
-import com.googlecode.android_scripting.facade.telephony.InCallServiceImpl;
-import com.googlecode.android_scripting.facade.telephony.TelephonyUtils;
-import com.googlecode.android_scripting.facade.telephony.TelephonyConstants;
-
 public class JsonBuilder {
 
     @SuppressWarnings("unchecked")
@@ -127,7 +128,7 @@
             return data;
         }
         if (data instanceof JsonSerializable) {
-            return ((JsonSerializable)data).toJSON();
+            return ((JsonSerializable) data).toJSON();
         }
         if (data instanceof JSONObject) {
             return data;
@@ -268,7 +269,7 @@
         if (data instanceof byte[]) {
             JSONArray result = new JSONArray();
             for (byte b : (byte[]) data) {
-                result.put(b&0xFF);
+                result.put(b & 0xFF);
             }
             return result;
         }
@@ -305,6 +306,9 @@
         if (data instanceof VoLteServiceState) {
             return buildVoLteServiceStateEvent((VoLteServiceState) data);
         }
+        if (data instanceof LegacyVpnInfo) {
+            return buildLegacyVpnInfo((LegacyVpnInfo) data);
+        }
         if (data instanceof ModemActivityInfo) {
             return buildModemActivityInfo((ModemActivityInfo) data);
         }
@@ -312,7 +316,6 @@
             return buildSignalStrength((SignalStrength) data);
         }
 
-
         return data.toString();
         // throw new JSONException("Failed to build JSON result. " +
         // data.getClass().getName());
@@ -697,8 +700,7 @@
         result.put("rssi", data.getRssi());
         result.put("lac", data.getLac());
         result.put("psc", data.getPsc());
-        String networkType =
-                TelephonyUtils.getNetworkTypeString(data.getNetworkType());
+        String networkType = TelephonyUtils.getNetworkTypeString(data.getNetworkType());
         result.put("network_type", build(networkType));
         return result;
     }
@@ -708,10 +710,8 @@
         JSONObject result = new JSONObject();
         result.put("rat", "lte");
         result.put("registered", data.isRegistered());
-        CellIdentityLte cellidentity =
-                ((CellInfoLte) data).getCellIdentity();
-        CellSignalStrengthLte signalstrength =
-                ((CellInfoLte) data).getCellSignalStrength();
+        CellIdentityLte cellidentity = ((CellInfoLte) data).getCellIdentity();
+        CellSignalStrengthLte signalstrength = ((CellInfoLte) data).getCellSignalStrength();
         result.put("mcc", cellidentity.getMcc());
         result.put("mnc", cellidentity.getMnc());
         result.put("cid", cellidentity.getCi());
@@ -728,10 +728,8 @@
         JSONObject result = new JSONObject();
         result.put("rat", "gsm");
         result.put("registered", data.isRegistered());
-        CellIdentityGsm cellidentity =
-                ((CellInfoGsm) data).getCellIdentity();
-        CellSignalStrengthGsm signalstrength =
-                ((CellInfoGsm) data).getCellSignalStrength();
+        CellIdentityGsm cellidentity = ((CellInfoGsm) data).getCellIdentity();
+        CellSignalStrengthGsm signalstrength = ((CellInfoGsm) data).getCellSignalStrength();
         result.put("mcc", cellidentity.getMcc());
         result.put("mnc", cellidentity.getMnc());
         result.put("cid", cellidentity.getCid());
@@ -746,10 +744,8 @@
         JSONObject result = new JSONObject();
         result.put("rat", "wcdma");
         result.put("registered", data.isRegistered());
-        CellIdentityWcdma cellidentity =
-                ((CellInfoWcdma) data).getCellIdentity();
-        CellSignalStrengthWcdma signalstrength =
-                ((CellInfoWcdma) data).getCellSignalStrength();
+        CellIdentityWcdma cellidentity = ((CellInfoWcdma) data).getCellIdentity();
+        CellSignalStrengthWcdma signalstrength = ((CellInfoWcdma) data).getCellSignalStrength();
         result.put("mcc", cellidentity.getMcc());
         result.put("mnc", cellidentity.getMnc());
         result.put("cid", cellidentity.getCid());
@@ -765,10 +761,8 @@
         JSONObject result = new JSONObject();
         result.put("rat", "cdma");
         result.put("registered", data.isRegistered());
-        CellIdentityCdma cellidentity =
-                ((CellInfoCdma) data).getCellIdentity();
-        CellSignalStrengthCdma signalstrength =
-                ((CellInfoCdma) data).getCellSignalStrength();
+        CellIdentityCdma cellidentity = ((CellInfoCdma) data).getCellIdentity();
+        CellSignalStrengthCdma signalstrength = ((CellInfoCdma) data).getCellSignalStrength();
         result.put("network_id", cellidentity.getNetworkId());
         result.put("system_id", cellidentity.getSystemId());
         result.put("basestation_id", cellidentity.getBasestationId());
@@ -1102,11 +1096,26 @@
     }
 
     private static JSONObject buildVoLteServiceStateEvent(
-        VoLteServiceState volteInfo)
+            VoLteServiceState volteInfo)
             throws JSONException {
         JSONObject info = new JSONObject();
         info.put(TelephonyConstants.VoLteServiceStateContainer.SRVCC_STATE,
-            TelephonyUtils.getSrvccStateString(volteInfo.getSrvccState()));
+                TelephonyUtils.getSrvccStateString(volteInfo.getSrvccState()));
+        return info;
+    }
+
+    private static JSONObject buildLegacyVpnInfo(LegacyVpnInfo data) throws JSONException {
+        JSONObject info = new JSONObject();
+        if (data == null) {
+            return info;
+        }
+        info.put("state", data.state);
+        info.put("key", data.key);
+        String intentStr = "";
+        if (data.intent != null) {
+            intentStr = data.intent.toString();
+        }
+        info.put("intent", intentStr);
         return info;
     }
 
@@ -1117,10 +1126,10 @@
         info.put("Timestamp", modemInfo.getTimestamp());
         info.put("SleepTimeMs", modemInfo.getSleepTimeMillis());
         info.put("IdleTimeMs", modemInfo.getIdleTimeMillis());
-        //convert from int[] to List<Integer> for proper JSON translation
+        // convert from int[] to List<Integer> for proper JSON translation
         int[] txTimes = modemInfo.getTxTimeMillis();
         List<Integer> tmp = new ArrayList<Integer>(txTimes.length);
-        for(int val : txTimes) {
+        for (int val : txTimes) {
             tmp.add(val);
         }
         info.put("TxTimeMs", build(tmp));
@@ -1128,60 +1137,61 @@
         info.put("EnergyUsedMw", modemInfo.getEnergyUsed());
         return info;
     }
+
     private static JSONObject buildSignalStrength(SignalStrength signalStrength)
             throws JSONException {
         JSONObject info = new JSONObject();
         info.put(TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM,
-            signalStrength.getGsmSignalStrength());
+                signalStrength.getGsmSignalStrength());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_DBM,
-            signalStrength.getGsmDbm());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_DBM,
+                signalStrength.getGsmDbm());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_LEVEL,
-            signalStrength.getGsmLevel());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_LEVEL,
+                signalStrength.getGsmLevel());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_ASU_LEVEL,
-            signalStrength.getGsmAsuLevel());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_ASU_LEVEL,
+                signalStrength.getGsmAsuLevel());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_BIT_ERROR_RATE,
-            signalStrength.getGsmBitErrorRate());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_BIT_ERROR_RATE,
+                signalStrength.getGsmBitErrorRate());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_DBM,
-            signalStrength.getCdmaDbm());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_DBM,
+                signalStrength.getCdmaDbm());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_LEVEL,
-            signalStrength.getCdmaLevel());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_LEVEL,
+                signalStrength.getCdmaLevel());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_ASU_LEVEL,
-            signalStrength.getCdmaAsuLevel());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_ASU_LEVEL,
+                signalStrength.getCdmaAsuLevel());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_ECIO,
-            signalStrength.getCdmaEcio());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_ECIO,
+                signalStrength.getCdmaEcio());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_EVDO_DBM,
-            signalStrength.getEvdoDbm());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_EVDO_DBM,
+                signalStrength.getEvdoDbm());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_EVDO_ECIO,
-            signalStrength.getEvdoEcio());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_EVDO_ECIO,
+                signalStrength.getEvdoEcio());
         info.put(TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE,
-            signalStrength.getLteSignalStrength());
+                signalStrength.getLteSignalStrength());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE_DBM,
-            signalStrength.getLteDbm());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE_DBM,
+                signalStrength.getLteDbm());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE_LEVEL,
-            signalStrength.getLteLevel());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE_LEVEL,
+                signalStrength.getLteLevel());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE_ASU_LEVEL,
-            signalStrength.getLteAsuLevel());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE_ASU_LEVEL,
+                signalStrength.getLteAsuLevel());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LEVEL,
-            signalStrength.getLevel());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LEVEL,
+                signalStrength.getLevel());
         info.put(
-            TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_ASU_LEVEL,
-            signalStrength.getAsuLevel());
+                TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_ASU_LEVEL,
+                signalStrength.getAsuLevel());
         info.put(TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_DBM,
-            signalStrength.getDbm());
+                signalStrength.getDbm());
         return info;
     }
 
diff --git a/ScriptingLayer/src/com/googlecode/android_scripting/facade/FacadeConfiguration.java b/ScriptingLayer/src/com/googlecode/android_scripting/facade/FacadeConfiguration.java
index 2b9a089..420fffb 100644
--- a/ScriptingLayer/src/com/googlecode/android_scripting/facade/FacadeConfiguration.java
+++ b/ScriptingLayer/src/com/googlecode/android_scripting/facade/FacadeConfiguration.java
@@ -134,6 +134,7 @@
         sFacadeClassList.add(TelecomCallFacade.class);
         sFacadeClassList.add(CarrierConfigFacade.class);
         sFacadeClassList.add(NfcManagerFacade.class);
+        sFacadeClassList.add(VpnFacade.class);
 
         /* Compatibility reset to >= Marshmallow */
         if (sSdkLevel >= 23) {