Home | History | Annotate | Download | only in jsonrpc
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.googlecode.android_scripting.jsonrpc;
     18 
     19 import java.io.IOException;
     20 import java.net.HttpURLConnection;
     21 import java.net.InetAddress;
     22 import java.net.InetSocketAddress;
     23 import java.net.URL;
     24 import java.security.PrivateKey;
     25 import java.security.cert.CertificateEncodingException;
     26 import java.security.cert.X509Certificate;
     27 import java.util.ArrayList;
     28 import java.util.Collection;
     29 import java.util.List;
     30 import java.util.Map;
     31 import java.util.Map.Entry;
     32 import java.util.Set;
     33 
     34 import org.apache.commons.codec.binary.Base64Codec;
     35 import org.json.JSONArray;
     36 import org.json.JSONException;
     37 import org.json.JSONObject;
     38 
     39 import com.android.internal.net.LegacyVpnInfo;
     40 import com.googlecode.android_scripting.ConvertUtils;
     41 import com.googlecode.android_scripting.Log;
     42 import com.googlecode.android_scripting.event.Event;
     43 //FIXME: Refactor classes, constants and conversions out of here
     44 import com.googlecode.android_scripting.facade.telephony.InCallServiceImpl;
     45 import com.googlecode.android_scripting.facade.telephony.TelephonyConstants;
     46 import com.googlecode.android_scripting.facade.telephony.TelephonyUtils;
     47 
     48 import android.annotation.NonNull;
     49 import android.bluetooth.BluetoothDevice;
     50 import android.bluetooth.BluetoothGattCharacteristic;
     51 import android.bluetooth.BluetoothGattDescriptor;
     52 import android.bluetooth.BluetoothGattService;
     53 import android.bluetooth.le.AdvertiseSettings;
     54 import android.content.ComponentName;
     55 import android.content.Intent;
     56 import android.graphics.Point;
     57 import android.location.Address;
     58 import android.location.Location;
     59 import android.net.DhcpInfo;
     60 import android.net.Network;
     61 import android.net.NetworkInfo;
     62 import android.net.Uri;
     63 import android.net.wifi.RttManager.RttCapabilities;
     64 import android.net.wifi.ScanResult;
     65 import android.net.wifi.WifiActivityEnergyInfo;
     66 import android.net.wifi.WifiChannel;
     67 import android.net.wifi.WifiConfiguration;
     68 import android.net.wifi.WifiEnterpriseConfig;
     69 import android.net.wifi.WifiInfo;
     70 import android.net.wifi.WifiScanner.ScanData;
     71 import android.net.wifi.p2p.WifiP2pDevice;
     72 import android.net.wifi.p2p.WifiP2pGroup;
     73 import android.net.wifi.p2p.WifiP2pInfo;
     74 import android.os.Bundle;
     75 import android.os.ParcelUuid;
     76 import android.telecom.Call;
     77 import android.telecom.CallAudioState;
     78 import android.telecom.PhoneAccount;
     79 import android.telecom.PhoneAccountHandle;
     80 import android.telecom.VideoProfile;
     81 import android.telecom.VideoProfile.CameraCapabilities;
     82 import android.telephony.CellIdentityCdma;
     83 import android.telephony.CellIdentityGsm;
     84 import android.telephony.CellIdentityLte;
     85 import android.telephony.CellIdentityWcdma;
     86 import android.telephony.CellInfoCdma;
     87 import android.telephony.CellInfoGsm;
     88 import android.telephony.CellInfoLte;
     89 import android.telephony.CellInfoWcdma;
     90 import android.telephony.CellLocation;
     91 import android.telephony.CellSignalStrengthCdma;
     92 import android.telephony.CellSignalStrengthGsm;
     93 import android.telephony.CellSignalStrengthLte;
     94 import android.telephony.CellSignalStrengthWcdma;
     95 import android.telephony.ModemActivityInfo;
     96 import android.telephony.NeighboringCellInfo;
     97 import android.telephony.SignalStrength;
     98 import android.telephony.SmsMessage;
     99 import android.telephony.SubscriptionInfo;
    100 import android.telephony.VoLteServiceState;
    101 import android.telephony.gsm.GsmCellLocation;
    102 import android.util.Base64;
    103 import android.util.DisplayMetrics;
    104 import android.util.SparseArray;
    105 
    106 import static com.googlecode.android_scripting.ConvertUtils.toNonNullString;
    107 
    108 public class JsonBuilder {
    109 
    110     @SuppressWarnings("unchecked")
    111     public static Object build(Object data) throws JSONException {
    112         if (data == null) {
    113             return JSONObject.NULL;
    114         }
    115         if (data instanceof Integer) {
    116             return data;
    117         }
    118         if (data instanceof Float) {
    119             return data;
    120         }
    121         if (data instanceof Double) {
    122             return data;
    123         }
    124         if (data instanceof Long) {
    125             return data;
    126         }
    127         if (data instanceof String) {
    128             return data;
    129         }
    130         if (data instanceof Boolean) {
    131             return data;
    132         }
    133         if (data instanceof JsonSerializable) {
    134             return ((JsonSerializable) data).toJSON();
    135         }
    136         if (data instanceof JSONObject) {
    137             return data;
    138         }
    139         if (data instanceof JSONArray) {
    140             return data;
    141         }
    142         if (data instanceof Set<?>) {
    143             List<Object> items = new ArrayList<Object>((Set<?>) data);
    144             return buildJsonList(items);
    145         }
    146         if (data instanceof Collection<?>) {
    147             List<Object> items = new ArrayList<Object>((Collection<?>) data);
    148             return buildJsonList(items);
    149         }
    150         if (data instanceof List<?>) {
    151             return buildJsonList((List<?>) data);
    152         }
    153         if (data instanceof Address) {
    154             return buildJsonAddress((Address) data);
    155         }
    156         if (data instanceof CallAudioState) {
    157             return buildJsonAudioState((CallAudioState) data);
    158         }
    159         if (data instanceof Location) {
    160             return buildJsonLocation((Location) data);
    161         }
    162         if (data instanceof Bundle) {
    163             return buildJsonBundle((Bundle) data);
    164         }
    165         if (data instanceof Intent) {
    166             return buildJsonIntent((Intent) data);
    167         }
    168         if (data instanceof Event) {
    169             return buildJsonEvent((Event) data);
    170         }
    171         if (data instanceof Map<?, ?>) {
    172             // TODO(damonkohler): I would like to make this a checked cast if
    173             // possible.
    174             return buildJsonMap((Map<String, ?>) data);
    175         }
    176         if (data instanceof ParcelUuid) {
    177             return data.toString();
    178         }
    179         if (data instanceof ScanResult) {
    180             return buildJsonScanResult((ScanResult) data);
    181         }
    182         if (data instanceof ScanData) {
    183             return buildJsonScanData((ScanData) data);
    184         }
    185         if (data instanceof android.bluetooth.le.ScanResult) {
    186             return buildJsonBleScanResult((android.bluetooth.le.ScanResult) data);
    187         }
    188         if (data instanceof AdvertiseSettings) {
    189             return buildJsonBleAdvertiseSettings((AdvertiseSettings) data);
    190         }
    191         if (data instanceof BluetoothGattService) {
    192             return buildJsonBluetoothGattService((BluetoothGattService) data);
    193         }
    194         if (data instanceof BluetoothGattCharacteristic) {
    195             return buildJsonBluetoothGattCharacteristic((BluetoothGattCharacteristic) data);
    196         }
    197         if (data instanceof BluetoothGattDescriptor) {
    198             return buildJsonBluetoothGattDescriptor((BluetoothGattDescriptor) data);
    199         }
    200         if (data instanceof BluetoothDevice) {
    201             return buildJsonBluetoothDevice((BluetoothDevice) data);
    202         }
    203         if (data instanceof CellLocation) {
    204             return buildJsonCellLocation((CellLocation) data);
    205         }
    206         if (data instanceof WifiInfo) {
    207             return buildJsonWifiInfo((WifiInfo) data);
    208         }
    209         if (data instanceof NeighboringCellInfo) {
    210             return buildNeighboringCellInfo((NeighboringCellInfo) data);
    211         }
    212         if (data instanceof Network) {
    213             return buildNetwork((Network) data);
    214         }
    215         if (data instanceof NetworkInfo) {
    216             return buildNetworkInfo((NetworkInfo) data);
    217         }
    218         if (data instanceof HttpURLConnection) {
    219             return buildHttpURLConnection((HttpURLConnection) data);
    220         }
    221         if (data instanceof InetSocketAddress) {
    222             return buildInetSocketAddress((InetSocketAddress) data);
    223         }
    224         if (data instanceof InetAddress) {
    225             return buildInetAddress((InetAddress) data);
    226         }
    227         if (data instanceof URL) {
    228             return buildURL((URL) data);
    229         }
    230         if (data instanceof Point) {
    231             return buildPoint((Point) data);
    232         }
    233         if (data instanceof SmsMessage) {
    234             return buildSmsMessage((SmsMessage) data);
    235         }
    236         if (data instanceof PhoneAccount) {
    237             return buildPhoneAccount((PhoneAccount) data);
    238         }
    239         if (data instanceof PhoneAccountHandle) {
    240             return buildPhoneAccountHandle((PhoneAccountHandle) data);
    241         }
    242         if (data instanceof SubscriptionInfo) {
    243             return buildSubscriptionInfoRecord((SubscriptionInfo) data);
    244         }
    245         if (data instanceof DhcpInfo) {
    246             return buildDhcpInfo((DhcpInfo) data);
    247         }
    248         if (data instanceof DisplayMetrics) {
    249             return buildDisplayMetrics((DisplayMetrics) data);
    250         }
    251         if (data instanceof RttCapabilities) {
    252             return buildRttCapabilities((RttCapabilities) data);
    253         }
    254         if (data instanceof WifiActivityEnergyInfo) {
    255             return buildWifiActivityEnergyInfo((WifiActivityEnergyInfo) data);
    256         }
    257         if (data instanceof WifiChannel) {
    258             return buildWifiChannel((WifiChannel) data);
    259         }
    260         if (data instanceof WifiConfiguration) {
    261             return buildWifiConfiguration((WifiConfiguration) data);
    262         }
    263         if (data instanceof WifiP2pDevice) {
    264             return buildWifiP2pDevice((WifiP2pDevice) data);
    265         }
    266         if (data instanceof WifiP2pInfo) {
    267             return buildWifiP2pInfo((WifiP2pInfo) data);
    268         }
    269         if (data instanceof WifiP2pGroup) {
    270             return buildWifiP2pGroup((WifiP2pGroup) data);
    271         }
    272         if (data instanceof byte[]) {
    273             JSONArray result = new JSONArray();
    274             for (byte b : (byte[]) data) {
    275                 result.put(b & 0xFF);
    276             }
    277             return result;
    278         }
    279         if (data instanceof Object[]) {
    280             return buildJSONArray((Object[]) data);
    281         }
    282         if (data instanceof CellInfoLte) {
    283             return buildCellInfoLte((CellInfoLte) data);
    284         }
    285         if (data instanceof CellInfoWcdma) {
    286             return buildCellInfoWcdma((CellInfoWcdma) data);
    287         }
    288         if (data instanceof CellInfoGsm) {
    289             return buildCellInfoGsm((CellInfoGsm) data);
    290         }
    291         if (data instanceof CellInfoCdma) {
    292             return buildCellInfoCdma((CellInfoCdma) data);
    293         }
    294         if (data instanceof Call) {
    295             return buildCall((Call) data);
    296         }
    297         if (data instanceof Call.Details) {
    298             return buildCallDetails((Call.Details) data);
    299         }
    300         if (data instanceof InCallServiceImpl.CallEvent<?>) {
    301             return buildCallEvent((InCallServiceImpl.CallEvent<?>) data);
    302         }
    303         if (data instanceof VideoProfile) {
    304             return buildVideoProfile((VideoProfile) data);
    305         }
    306         if (data instanceof CameraCapabilities) {
    307             return buildCameraCapabilities((CameraCapabilities) data);
    308         }
    309         if (data instanceof VoLteServiceState) {
    310             return buildVoLteServiceStateEvent((VoLteServiceState) data);
    311         }
    312         if (data instanceof LegacyVpnInfo) {
    313             return buildLegacyVpnInfo((LegacyVpnInfo) data);
    314         }
    315         if (data instanceof ModemActivityInfo) {
    316             return buildModemActivityInfo((ModemActivityInfo) data);
    317         }
    318         if (data instanceof SignalStrength) {
    319             return buildSignalStrength((SignalStrength) data);
    320         }
    321 
    322         return data.toString();
    323         // throw new JSONException("Failed to build JSON result. " +
    324         // data.getClass().getName());
    325     }
    326 
    327     private static JSONObject buildJsonAudioState(CallAudioState data)
    328             throws JSONException {
    329         JSONObject state = new JSONObject();
    330         state.put("isMuted", data.isMuted());
    331         state.put("AudioRoute", InCallServiceImpl.getAudioRouteString(data.getRoute()));
    332         return state;
    333     }
    334 
    335     private static Object buildDisplayMetrics(DisplayMetrics data)
    336             throws JSONException {
    337         JSONObject dm = new JSONObject();
    338         dm.put("widthPixels", data.widthPixels);
    339         dm.put("heightPixels", data.heightPixels);
    340         dm.put("noncompatHeightPixels", data.noncompatHeightPixels);
    341         dm.put("noncompatWidthPixels", data.noncompatWidthPixels);
    342         return dm;
    343     }
    344 
    345     private static Object buildInetAddress(InetAddress data) {
    346         JSONArray address = new JSONArray();
    347         address.put(data.getHostName());
    348         address.put(data.getHostAddress());
    349         return address;
    350     }
    351 
    352     private static Object buildInetSocketAddress(InetSocketAddress data) {
    353         JSONArray address = new JSONArray();
    354         address.put(data.getHostName());
    355         address.put(data.getPort());
    356         return address;
    357     }
    358 
    359     private static JSONObject buildJsonAddress(Address address)
    360             throws JSONException {
    361         JSONObject result = new JSONObject();
    362         result.put("admin_area", address.getAdminArea());
    363         result.put("country_code", address.getCountryCode());
    364         result.put("country_name", address.getCountryName());
    365         result.put("feature_name", address.getFeatureName());
    366         result.put("phone", address.getPhone());
    367         result.put("locality", address.getLocality());
    368         result.put("postal_code", address.getPostalCode());
    369         result.put("sub_admin_area", address.getSubAdminArea());
    370         result.put("thoroughfare", address.getThoroughfare());
    371         result.put("url", address.getUrl());
    372         return result;
    373     }
    374 
    375     private static JSONArray buildJSONArray(Object[] data) throws JSONException {
    376         JSONArray result = new JSONArray();
    377         for (Object o : data) {
    378             result.put(build(o));
    379         }
    380         return result;
    381     }
    382 
    383     private static JSONObject buildJsonBleAdvertiseSettings(
    384             AdvertiseSettings advertiseSettings) throws JSONException {
    385         JSONObject result = new JSONObject();
    386         result.put("mode", advertiseSettings.getMode());
    387         result.put("txPowerLevel", advertiseSettings.getTxPowerLevel());
    388         result.put("isConnectable", advertiseSettings.isConnectable());
    389         return result;
    390     }
    391 
    392     private static JSONObject buildJsonBleScanResult(
    393             android.bluetooth.le.ScanResult scanResult) throws JSONException {
    394         JSONObject result = new JSONObject();
    395         result.put("rssi", scanResult.getRssi());
    396         result.put("timestampNanos", scanResult.getTimestampNanos());
    397         result.put("deviceName", scanResult.getScanRecord().getDeviceName());
    398         result.put("txPowerLevel", scanResult.getScanRecord().getTxPowerLevel());
    399         result.put("advertiseFlags", scanResult.getScanRecord()
    400                 .getAdvertiseFlags());
    401         ArrayList<String> manufacturerDataList = new ArrayList<String>();
    402         ArrayList<Integer> idList = new ArrayList<Integer>();
    403         if (scanResult.getScanRecord().getManufacturerSpecificData() != null) {
    404             SparseArray<byte[]> manufacturerSpecificData = scanResult
    405                     .getScanRecord().getManufacturerSpecificData();
    406             for (int i = 0; i < manufacturerSpecificData.size(); i++) {
    407                 manufacturerDataList.add(ConvertUtils
    408                         .convertByteArrayToString(manufacturerSpecificData
    409                                 .valueAt(i)));
    410                 idList.add(manufacturerSpecificData.keyAt(i));
    411             }
    412         }
    413         result.put("manufacturerSpecificDataList", manufacturerDataList);
    414         result.put("manufacturerIdList", idList);
    415         ArrayList<String> serviceUuidList = new ArrayList<String>();
    416         ArrayList<String> serviceDataList = new ArrayList<String>();
    417         if (scanResult.getScanRecord().getServiceData() != null) {
    418             Map<ParcelUuid, byte[]> serviceDataMap = scanResult.getScanRecord()
    419                     .getServiceData();
    420             for (ParcelUuid serviceUuid : serviceDataMap.keySet()) {
    421                 serviceUuidList.add(serviceUuid.toString());
    422                 serviceDataList.add(ConvertUtils
    423                         .convertByteArrayToString(serviceDataMap
    424                                 .get(serviceUuid)));
    425             }
    426         }
    427         result.put("serviceUuidList", serviceUuidList);
    428         result.put("serviceDataList", serviceDataList);
    429         List<ParcelUuid> serviceUuids = scanResult.getScanRecord()
    430                 .getServiceUuids();
    431         String serviceUuidsString = "";
    432         if (serviceUuids != null && serviceUuids.size() > 0) {
    433             for (ParcelUuid uuid : serviceUuids) {
    434                 serviceUuidsString = serviceUuidsString + "," + uuid;
    435             }
    436         }
    437         result.put("serviceUuids", serviceUuidsString);
    438         result.put("scanRecord",
    439                 build(ConvertUtils.convertByteArrayToString(scanResult
    440                         .getScanRecord().getBytes())));
    441         result.put("deviceInfo", build(scanResult.getDevice()));
    442         return result;
    443     }
    444 
    445     private static JSONObject buildJsonBluetoothDevice(BluetoothDevice data)
    446             throws JSONException {
    447         JSONObject deviceInfo = new JSONObject();
    448         deviceInfo.put("address", data.getAddress());
    449         deviceInfo.put("state", data.getBondState());
    450         deviceInfo.put("name", data.getName());
    451         deviceInfo.put("type", data.getType());
    452         return deviceInfo;
    453     }
    454 
    455     private static Object buildJsonBluetoothGattCharacteristic(
    456             BluetoothGattCharacteristic data) throws JSONException {
    457         JSONObject result = new JSONObject();
    458         result.put("instanceId", data.getInstanceId());
    459         result.put("permissions", data.getPermissions());
    460         result.put("properties", data.getProperties());
    461         result.put("writeType", data.getWriteType());
    462         result.put("descriptorsList", build(data.getDescriptors()));
    463         result.put("uuid", data.getUuid().toString());
    464         result.put("value", build(data.getValue()));
    465 
    466         return result;
    467     }
    468 
    469     private static Object buildJsonBluetoothGattDescriptor(
    470             BluetoothGattDescriptor data) throws JSONException {
    471         JSONObject result = new JSONObject();
    472         result.put("instanceId", data.getInstanceId());
    473         result.put("permissions", data.getPermissions());
    474         result.put("characteristic", data.getCharacteristic());
    475         result.put("uuid", data.getUuid().toString());
    476         result.put("value", build(data.getValue()));
    477         return result;
    478     }
    479 
    480     private static Object buildJsonBluetoothGattService(
    481             BluetoothGattService data) throws JSONException {
    482         JSONObject result = new JSONObject();
    483         result.put("instanceId", data.getInstanceId());
    484         result.put("type", data.getType());
    485         result.put("gattCharacteristicList", build(data.getCharacteristics()));
    486         result.put("includedServices", build(data.getIncludedServices()));
    487         result.put("uuid", data.getUuid().toString());
    488         return result;
    489     }
    490 
    491     private static JSONObject buildJsonBundle(Bundle bundle)
    492             throws JSONException {
    493         JSONObject result = new JSONObject();
    494         for (String key : bundle.keySet()) {
    495             result.put(key, build(bundle.get(key)));
    496         }
    497         return result;
    498     }
    499 
    500     private static JSONObject buildJsonCellLocation(CellLocation cellLocation)
    501             throws JSONException {
    502         JSONObject result = new JSONObject();
    503         if (cellLocation instanceof GsmCellLocation) {
    504             GsmCellLocation location = (GsmCellLocation) cellLocation;
    505             result.put("lac", location.getLac());
    506             result.put("cid", location.getCid());
    507         }
    508         // TODO(damonkohler): Add support for CdmaCellLocation. Not supported
    509         // until API level 5.
    510         return result;
    511     }
    512 
    513     private static JSONObject buildDhcpInfo(DhcpInfo data) throws JSONException {
    514         JSONObject result = new JSONObject();
    515         result.put("ipAddress", data.ipAddress);
    516         result.put("dns1", data.dns1);
    517         result.put("dns2", data.dns2);
    518         result.put("gateway", data.gateway);
    519         result.put("serverAddress", data.serverAddress);
    520         result.put("leaseDuration", data.leaseDuration);
    521         return result;
    522     }
    523 
    524     private static JSONObject buildJsonEvent(Event event) throws JSONException {
    525         JSONObject result = new JSONObject();
    526         result.put("name", event.getName());
    527         result.put("data", build(event.getData()));
    528         result.put("time", event.getCreationTime());
    529         return result;
    530     }
    531 
    532     private static JSONObject buildJsonIntent(Intent data) throws JSONException {
    533         JSONObject result = new JSONObject();
    534         result.put("data", data.getDataString());
    535         result.put("type", data.getType());
    536         result.put("extras", build(data.getExtras()));
    537         result.put("categories", build(data.getCategories()));
    538         result.put("action", data.getAction());
    539         ComponentName component = data.getComponent();
    540         if (component != null) {
    541             result.put("packagename", component.getPackageName());
    542             result.put("classname", component.getClassName());
    543         }
    544         result.put("flags", data.getFlags());
    545         return result;
    546     }
    547 
    548     private static <T> JSONArray buildJsonList(final List<T> list)
    549             throws JSONException {
    550         JSONArray result = new JSONArray();
    551         for (T item : list) {
    552             result.put(build(item));
    553         }
    554         return result;
    555     }
    556 
    557     private static JSONObject buildJsonLocation(Location location)
    558             throws JSONException {
    559         JSONObject result = new JSONObject();
    560         result.put("altitude", location.getAltitude());
    561         result.put("latitude", location.getLatitude());
    562         result.put("longitude", location.getLongitude());
    563         result.put("time", location.getTime());
    564         result.put("accuracy", location.getAccuracy());
    565         result.put("speed", location.getSpeed());
    566         result.put("provider", location.getProvider());
    567         result.put("bearing", location.getBearing());
    568         return result;
    569     }
    570 
    571     private static JSONObject buildJsonMap(Map<String, ?> map)
    572             throws JSONException {
    573         JSONObject result = new JSONObject();
    574         for (Entry<String, ?> entry : map.entrySet()) {
    575             String key = entry.getKey();
    576             if (key == null) {
    577                 key = "";
    578             }
    579             result.put(key, build(entry.getValue()));
    580         }
    581         return result;
    582     }
    583 
    584     private static JSONObject buildJsonScanResult(ScanResult scanResult)
    585             throws JSONException {
    586         JSONObject result = new JSONObject();
    587         result.put("BSSID", scanResult.BSSID);
    588         result.put("SSID", scanResult.SSID);
    589         result.put("frequency", scanResult.frequency);
    590         result.put("level", scanResult.level);
    591         result.put("capabilities", scanResult.capabilities);
    592         result.put("timestamp", scanResult.timestamp);
    593         result.put("blackListTimestamp", scanResult.blackListTimestamp);
    594         result.put("centerFreq0", scanResult.centerFreq0);
    595         result.put("centerFreq1", scanResult.centerFreq1);
    596         result.put("channelWidth", scanResult.channelWidth);
    597         result.put("distanceCm", scanResult.distanceCm);
    598         result.put("distanceSdCm", scanResult.distanceSdCm);
    599         result.put("is80211McRTTResponder", scanResult.is80211mcResponder());
    600         result.put("numConnection", scanResult.numConnection);
    601         result.put("passpointNetwork", scanResult.isPasspointNetwork());
    602         result.put("numIpConfigFailures", scanResult.numIpConfigFailures);
    603         result.put("numUsage", scanResult.numUsage);
    604         result.put("seen", scanResult.seen);
    605         result.put("untrusted", scanResult.untrusted);
    606         result.put("operatorFriendlyName", scanResult.operatorFriendlyName);
    607         result.put("venueName", scanResult.venueName);
    608         if (scanResult.informationElements != null) {
    609             JSONArray infoEles = new JSONArray();
    610             for (ScanResult.InformationElement ie : scanResult.informationElements) {
    611                 JSONObject infoEle = new JSONObject();
    612                 infoEle.put("id", ie.id);
    613                 infoEle.put("bytes", Base64Codec.encodeBase64(ie.bytes).toString());
    614                 infoEles.put(infoEle);
    615             }
    616             result.put("InfomationElements", infoEles);
    617         } else {
    618             result.put("InfomationElements", null);
    619         }
    620         return result;
    621     }
    622 
    623     private static JSONObject buildJsonScanData(ScanData scanData)
    624             throws JSONException {
    625         JSONObject result = new JSONObject();
    626         result.put("Id", scanData.getId());
    627         result.put("Flags", scanData.getFlags());
    628         JSONArray scanResults = new JSONArray();
    629         for (ScanResult sr : scanData.getResults()) {
    630             scanResults.put(buildJsonScanResult(sr));
    631         }
    632         result.put("ScanResults", scanResults);
    633         return result;
    634     }
    635 
    636     private static JSONObject buildJsonWifiInfo(WifiInfo data)
    637             throws JSONException {
    638         JSONObject result = new JSONObject();
    639         result.put("hidden_ssid", data.getHiddenSSID());
    640         result.put("ip_address", data.getIpAddress());
    641         result.put("link_speed", data.getLinkSpeed());
    642         result.put("network_id", data.getNetworkId());
    643         result.put("rssi", data.getRssi());
    644         result.put("BSSID", data.getBSSID());
    645         result.put("mac_address", data.getMacAddress());
    646         // Trim the double quotes if exist
    647         String ssid = data.getSSID();
    648         if (ssid.charAt(0) == '"'
    649                 && ssid.charAt(ssid.length() - 1) == '"') {
    650             result.put("SSID", ssid.substring(1, ssid.length() - 1));
    651         } else {
    652             result.put("SSID", ssid);
    653         }
    654         String supplicantState = "";
    655         switch (data.getSupplicantState()) {
    656             case ASSOCIATED:
    657                 supplicantState = "associated";
    658                 break;
    659             case ASSOCIATING:
    660                 supplicantState = "associating";
    661                 break;
    662             case COMPLETED:
    663                 supplicantState = "completed";
    664                 break;
    665             case DISCONNECTED:
    666                 supplicantState = "disconnected";
    667                 break;
    668             case DORMANT:
    669                 supplicantState = "dormant";
    670                 break;
    671             case FOUR_WAY_HANDSHAKE:
    672                 supplicantState = "four_way_handshake";
    673                 break;
    674             case GROUP_HANDSHAKE:
    675                 supplicantState = "group_handshake";
    676                 break;
    677             case INACTIVE:
    678                 supplicantState = "inactive";
    679                 break;
    680             case INVALID:
    681                 supplicantState = "invalid";
    682                 break;
    683             case SCANNING:
    684                 supplicantState = "scanning";
    685                 break;
    686             case UNINITIALIZED:
    687                 supplicantState = "uninitialized";
    688                 break;
    689             default:
    690                 supplicantState = null;
    691         }
    692         result.put("supplicant_state", build(supplicantState));
    693         result.put("is_5ghz", data.is5GHz());
    694         result.put("is_24ghz", data.is24GHz());
    695         return result;
    696     }
    697 
    698     private static JSONObject buildNeighboringCellInfo(NeighboringCellInfo data)
    699             throws JSONException {
    700         JSONObject result = new JSONObject();
    701         result.put("cid", data.getCid());
    702         result.put("rssi", data.getRssi());
    703         result.put("lac", data.getLac());
    704         result.put("psc", data.getPsc());
    705         String networkType = TelephonyUtils.getNetworkTypeString(data.getNetworkType());
    706         result.put("network_type", build(networkType));
    707         return result;
    708     }
    709 
    710     private static JSONObject buildCellInfoLte(CellInfoLte data)
    711             throws JSONException {
    712         JSONObject result = new JSONObject();
    713         result.put("rat", "lte");
    714         result.put("registered", data.isRegistered());
    715         CellIdentityLte cellidentity = ((CellInfoLte) data).getCellIdentity();
    716         CellSignalStrengthLte signalstrength = ((CellInfoLte) data).getCellSignalStrength();
    717         result.put("mcc", cellidentity.getMcc());
    718         result.put("mnc", cellidentity.getMnc());
    719         result.put("cid", cellidentity.getCi());
    720         result.put("pcid", cellidentity.getPci());
    721         result.put("tac", cellidentity.getTac());
    722         result.put("rsrp", signalstrength.getDbm());
    723         result.put("asulevel", signalstrength.getAsuLevel());
    724         result.put("timing_advance", signalstrength.getTimingAdvance());
    725         return result;
    726     }
    727 
    728     private static JSONObject buildCellInfoGsm(CellInfoGsm data)
    729             throws JSONException {
    730         JSONObject result = new JSONObject();
    731         result.put("rat", "gsm");
    732         result.put("registered", data.isRegistered());
    733         CellIdentityGsm cellidentity = ((CellInfoGsm) data).getCellIdentity();
    734         CellSignalStrengthGsm signalstrength = ((CellInfoGsm) data).getCellSignalStrength();
    735         result.put("mcc", cellidentity.getMcc());
    736         result.put("mnc", cellidentity.getMnc());
    737         result.put("cid", cellidentity.getCid());
    738         result.put("lac", cellidentity.getLac());
    739         result.put("bsic", cellidentity.getBsic());
    740         result.put("arfcn", cellidentity.getArfcn());
    741         result.put("signal_strength", signalstrength.getDbm());
    742         result.put("asulevel", signalstrength.getAsuLevel());
    743         return result;
    744     }
    745 
    746     private static JSONObject buildCellInfoWcdma(CellInfoWcdma data)
    747             throws JSONException {
    748         JSONObject result = new JSONObject();
    749         result.put("rat", "wcdma");
    750         result.put("registered", data.isRegistered());
    751         CellIdentityWcdma cellidentity = ((CellInfoWcdma) data).getCellIdentity();
    752         CellSignalStrengthWcdma signalstrength = ((CellInfoWcdma) data).getCellSignalStrength();
    753         result.put("mcc", cellidentity.getMcc());
    754         result.put("mnc", cellidentity.getMnc());
    755         result.put("cid", cellidentity.getCid());
    756         result.put("lac", cellidentity.getLac());
    757         result.put("psc", cellidentity.getPsc());
    758         result.put("signal_strength", signalstrength.getDbm());
    759         result.put("asulevel", signalstrength.getAsuLevel());
    760         return result;
    761     }
    762 
    763     private static JSONObject buildCellInfoCdma(CellInfoCdma data)
    764             throws JSONException {
    765         JSONObject result = new JSONObject();
    766         result.put("rat", "cdma");
    767         result.put("registered", data.isRegistered());
    768         CellIdentityCdma cellidentity = ((CellInfoCdma) data).getCellIdentity();
    769         CellSignalStrengthCdma signalstrength = ((CellInfoCdma) data).getCellSignalStrength();
    770         result.put("network_id", cellidentity.getNetworkId());
    771         result.put("system_id", cellidentity.getSystemId());
    772         result.put("basestation_id", cellidentity.getBasestationId());
    773         result.put("longitude", cellidentity.getLongitude());
    774         result.put("latitude", cellidentity.getLatitude());
    775         result.put("cdma_dbm", signalstrength.getCdmaDbm());
    776         result.put("cdma_ecio", signalstrength.getCdmaEcio());
    777         result.put("evdo_dbm", signalstrength.getEvdoDbm());
    778         result.put("evdo_ecio", signalstrength.getEvdoEcio());
    779         result.put("evdo_snr", signalstrength.getEvdoSnr());
    780         return result;
    781     }
    782 
    783     private static Object buildHttpURLConnection(HttpURLConnection data)
    784             throws JSONException {
    785         JSONObject con = new JSONObject();
    786         try {
    787             con.put("ResponseCode", data.getResponseCode());
    788             con.put("ResponseMessage", data.getResponseMessage());
    789         } catch (IOException e) {
    790             e.printStackTrace();
    791             return con;
    792         }
    793         con.put("ContentLength", data.getContentLength());
    794         con.put("ContentEncoding", data.getContentEncoding());
    795         con.put("ContentType", data.getContentType());
    796         con.put("Date", data.getDate());
    797         con.put("ReadTimeout", data.getReadTimeout());
    798         con.put("HeaderFields", buildJsonMap(data.getHeaderFields()));
    799         con.put("URL", buildURL(data.getURL()));
    800         return con;
    801     }
    802 
    803     private static Object buildNetwork(Network data) throws JSONException {
    804         JSONObject nw = new JSONObject();
    805         nw.put("netId", data.netId);
    806         return nw;
    807     }
    808 
    809     private static Object buildNetworkInfo(NetworkInfo data)
    810             throws JSONException {
    811         JSONObject info = new JSONObject();
    812         info.put("isAvailable", data.isAvailable());
    813         info.put("isConnected", data.isConnected());
    814         info.put("isFailover", data.isFailover());
    815         info.put("isRoaming", data.isRoaming());
    816         info.put("ExtraInfo", data.getExtraInfo());
    817         info.put("FailedReason", data.getReason());
    818         info.put("TypeName", data.getTypeName());
    819         info.put("SubtypeName", data.getSubtypeName());
    820         info.put("State", data.getState().name().toString());
    821         return info;
    822     }
    823 
    824     private static Object buildURL(URL data) throws JSONException {
    825         JSONObject url = new JSONObject();
    826         url.put("Authority", data.getAuthority());
    827         url.put("Host", data.getHost());
    828         url.put("Path", data.getPath());
    829         url.put("Port", data.getPort());
    830         url.put("Protocol", data.getProtocol());
    831         return url;
    832     }
    833 
    834     /**
    835      * Builds a json representation of a {@link PhoneAccount}.
    836      * @param data The PhoneAccount convert to JSON.
    837      * @return A JSONObject representation of a {@link PhoneAccount}.
    838      * @throws JSONException
    839      */
    840     private static JSONObject buildPhoneAccount(@NonNull PhoneAccount data)
    841             throws JSONException {
    842         JSONObject acct = new JSONObject();
    843         acct.put("Address", toNonNullString(data.getAddress(), Uri::toSafeString));
    844         acct.put("SubscriptionAddress", toNonNullString(data.getSubscriptionAddress(),
    845                 Uri::toSafeString));
    846         acct.put("Label", toNonNullString(data.getLabel()));
    847         acct.put("ShortDescription", toNonNullString(data.getShortDescription()));
    848         return acct;
    849     }
    850 
    851     private static Object buildPhoneAccountHandle(PhoneAccountHandle data)
    852             throws JSONException {
    853         JSONObject msg = new JSONObject();
    854         msg.put("id", data.getId());
    855         msg.put("ComponentName", data.getComponentName().flattenToString());
    856         return msg;
    857     }
    858 
    859     private static Object buildSubscriptionInfoRecord(SubscriptionInfo data)
    860             throws JSONException {
    861         JSONObject msg = new JSONObject();
    862         msg.put("subscriptionId", data.getSubscriptionId());
    863         msg.put("iccId", data.getIccId());
    864         msg.put("simSlotIndex", data.getSimSlotIndex());
    865         msg.put("displayName", data.getDisplayName());
    866         msg.put("nameSource", data.getNameSource());
    867         msg.put("iconTint", data.getIconTint());
    868         msg.put("number", data.getNumber());
    869         msg.put("dataRoaming", data.getDataRoaming());
    870         msg.put("mcc", data.getMcc());
    871         msg.put("mnc", data.getMnc());
    872         return msg;
    873     }
    874 
    875     private static Object buildPoint(Point data) throws JSONException {
    876         JSONObject point = new JSONObject();
    877         point.put("x", data.x);
    878         point.put("y", data.y);
    879         return point;
    880     }
    881 
    882     private static Object buildRttCapabilities(RttCapabilities data)
    883             throws JSONException {
    884         JSONObject cap = new JSONObject();
    885         cap.put("bwSupported", data.bwSupported);
    886         cap.put("lciSupported", data.lciSupported);
    887         cap.put("lcrSupported", data.lcrSupported);
    888         cap.put("oneSidedRttSupported", data.oneSidedRttSupported);
    889         cap.put("preambleSupported", data.preambleSupported);
    890         cap.put("twoSided11McRttSupported", data.twoSided11McRttSupported);
    891         return cap;
    892     }
    893 
    894     private static Object buildSmsMessage(SmsMessage data) throws JSONException {
    895         JSONObject msg = new JSONObject();
    896         msg.put("originatingAddress", data.getOriginatingAddress());
    897         msg.put("messageBody", data.getMessageBody());
    898         return msg;
    899     }
    900 
    901     private static JSONObject buildWifiActivityEnergyInfo(
    902             WifiActivityEnergyInfo data) throws JSONException {
    903         JSONObject result = new JSONObject();
    904         result.put("ControllerEnergyUsed", data.getControllerEnergyUsed());
    905         result.put("ControllerIdleTimeMillis",
    906                 data.getControllerIdleTimeMillis());
    907         result.put("ControllerRxTimeMillis", data.getControllerRxTimeMillis());
    908         result.put("ControllerTxTimeMillis", data.getControllerTxTimeMillis());
    909         result.put("StackState", data.getStackState());
    910         result.put("TimeStamp", data.getTimeStamp());
    911         return result;
    912     }
    913 
    914     private static Object buildWifiChannel(WifiChannel data) throws JSONException {
    915         JSONObject channel = new JSONObject();
    916         channel.put("channelNum", data.channelNum);
    917         channel.put("freqMHz", data.freqMHz);
    918         channel.put("isDFS", data.isDFS);
    919         channel.put("isValid", data.isValid());
    920         return channel;
    921     }
    922 
    923     private static Object buildWifiConfiguration(WifiConfiguration data)
    924             throws JSONException {
    925         JSONObject config = new JSONObject();
    926         config.put("networkId", data.networkId);
    927         // Trim the double quotes if exist
    928         if (data.SSID.charAt(0) == '"'
    929                 && data.SSID.charAt(data.SSID.length() - 1) == '"') {
    930             config.put("SSID", data.SSID.substring(1, data.SSID.length() - 1));
    931         } else {
    932             config.put("SSID", data.SSID);
    933         }
    934         config.put("BSSID", data.BSSID);
    935         config.put("priority", data.priority);
    936         config.put("hiddenSSID", data.hiddenSSID);
    937         config.put("FQDN", data.FQDN);
    938         config.put("providerFriendlyName", data.providerFriendlyName);
    939         config.put("isPasspoint", data.isPasspoint());
    940         config.put("hiddenSSID", data.hiddenSSID);
    941         if (data.status == WifiConfiguration.Status.CURRENT) {
    942             config.put("status", "CURRENT");
    943         } else if (data.status == WifiConfiguration.Status.DISABLED) {
    944             config.put("status", "DISABLED");
    945         } else if (data.status == WifiConfiguration.Status.ENABLED) {
    946             config.put("status", "ENABLED");
    947         } else {
    948             config.put("status", "UNKNOWN");
    949         }
    950         // config.put("enterpriseConfig", buildWifiEnterpriseConfig(data.enterpriseConfig));
    951         return config;
    952     }
    953 
    954     private static Object buildWifiEnterpriseConfig(WifiEnterpriseConfig data)
    955             throws JSONException, CertificateEncodingException {
    956         JSONObject config = new JSONObject();
    957         config.put(WifiEnterpriseConfig.PLMN_KEY, data.getPlmn());
    958         config.put(WifiEnterpriseConfig.REALM_KEY, data.getRealm());
    959         config.put(WifiEnterpriseConfig.EAP_KEY, data.getEapMethod());
    960         config.put(WifiEnterpriseConfig.PHASE2_KEY, data.getPhase2Method());
    961         config.put(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, data.getAltSubjectMatch());
    962         X509Certificate caCert = data.getCaCertificate();
    963         String caCertString = Base64.encodeToString(caCert.getEncoded(), Base64.DEFAULT);
    964         config.put(WifiEnterpriseConfig.CA_CERT_KEY, caCertString);
    965         X509Certificate clientCert = data.getClientCertificate();
    966         String clientCertString = Base64.encodeToString(clientCert.getEncoded(), Base64.DEFAULT);
    967         config.put(WifiEnterpriseConfig.CLIENT_CERT_KEY, clientCertString);
    968         PrivateKey pk = data.getClientPrivateKey();
    969         String privateKeyString = Base64.encodeToString(pk.getEncoded(), Base64.DEFAULT);
    970         config.put(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, privateKeyString);
    971         config.put(WifiEnterpriseConfig.PASSWORD_KEY, data.getPassword());
    972         return config;
    973     }
    974 
    975     private static JSONObject buildWifiP2pDevice(WifiP2pDevice data)
    976             throws JSONException {
    977         JSONObject deviceInfo = new JSONObject();
    978         deviceInfo.put("Name", data.deviceName);
    979         deviceInfo.put("Address", data.deviceAddress);
    980         return deviceInfo;
    981     }
    982 
    983     private static JSONObject buildWifiP2pGroup(WifiP2pGroup data)
    984             throws JSONException {
    985         JSONObject group = new JSONObject();
    986         Log.d("build p2p group.");
    987         group.put("ClientList", build(data.getClientList()));
    988         group.put("Interface", data.getInterface());
    989         group.put("Networkname", data.getNetworkName());
    990         group.put("Owner", data.getOwner());
    991         group.put("Passphrase", data.getPassphrase());
    992         group.put("NetworkId", data.getNetworkId());
    993         return group;
    994     }
    995 
    996     private static JSONObject buildWifiP2pInfo(WifiP2pInfo data)
    997             throws JSONException {
    998         JSONObject info = new JSONObject();
    999         Log.d("build p2p info.");
   1000         info.put("groupFormed", data.groupFormed);
   1001         info.put("isGroupOwner", data.isGroupOwner);
   1002         info.put("groupOwnerAddress", data.groupOwnerAddress);
   1003         return info;
   1004     }
   1005 
   1006     private static <T> JSONObject buildCallEvent(InCallServiceImpl.CallEvent<T> callEvent)
   1007             throws JSONException {
   1008         JSONObject jsonEvent = new JSONObject();
   1009         jsonEvent.put("CallId", callEvent.getCallId());
   1010         jsonEvent.put("Event", build(callEvent.getEvent()));
   1011         return jsonEvent;
   1012     }
   1013 
   1014     private static JSONObject buildUri(Uri uri) throws JSONException {
   1015         return new JSONObject().put("Uri", build((uri != null) ? uri.toString() : ""));
   1016     }
   1017 
   1018     private static JSONObject buildCallDetails(Call.Details details) throws JSONException {
   1019 
   1020         JSONObject callDetails = new JSONObject();
   1021 
   1022         callDetails.put("Handle", buildUri(details.getHandle()));
   1023         callDetails.put("HandlePresentation",
   1024                 build(InCallServiceImpl.getCallPresentationInfoString(
   1025                         details.getHandlePresentation())));
   1026         callDetails.put("CallerDisplayName", build(details.getCallerDisplayName()));
   1027 
   1028         // TODO AccountHandle
   1029         // callDetails.put("AccountHandle", build(""));
   1030 
   1031         callDetails.put("Capabilities",
   1032                 build(InCallServiceImpl.getCallCapabilitiesString(details.getCallCapabilities())));
   1033 
   1034         callDetails.put("Properties",
   1035                 build(InCallServiceImpl.getCallPropertiesString(details.getCallProperties())));
   1036 
   1037         // TODO Parse fields in Disconnect Cause
   1038         callDetails.put("DisconnectCause", build((details.getDisconnectCause() != null) ? details
   1039                 .getDisconnectCause().toString() : ""));
   1040         callDetails.put("ConnectTimeMillis", build(details.getConnectTimeMillis()));
   1041 
   1042         // TODO: GatewayInfo
   1043         // callDetails.put("GatewayInfo", build(""));
   1044 
   1045         callDetails.put("VideoState",
   1046                 build(InCallServiceImpl.getVideoCallStateString(details.getVideoState())));
   1047 
   1048         // TODO: StatusHints
   1049         // callDetails.put("StatusHints", build(""));
   1050 
   1051         callDetails.put("Extras", build(details.getExtras()));
   1052 
   1053         return callDetails;
   1054     }
   1055 
   1056     private static JSONObject buildCall(Call call) throws JSONException {
   1057 
   1058         JSONObject callInfo = new JSONObject();
   1059 
   1060         callInfo.put("Parent", build(InCallServiceImpl.getCallId(call)));
   1061 
   1062         // TODO:Make a function out of this for consistency
   1063         ArrayList<String> children = new ArrayList<String>();
   1064         for (Call child : call.getChildren()) {
   1065             children.add(InCallServiceImpl.getCallId(child));
   1066         }
   1067         callInfo.put("Children", build(children));
   1068 
   1069         // TODO:Make a function out of this for consistency
   1070         ArrayList<String> conferenceables = new ArrayList<String>();
   1071         for (Call conferenceable : call.getChildren()) {
   1072             children.add(InCallServiceImpl.getCallId(conferenceable));
   1073         }
   1074         callInfo.put("ConferenceableCalls", build(conferenceables));
   1075 
   1076         callInfo.put("State", build(InCallServiceImpl.getCallStateString(call.getState())));
   1077         callInfo.put("CannedTextResponses", build(call.getCannedTextResponses()));
   1078         callInfo.put("VideoCall", InCallServiceImpl.getVideoCallId(call.getVideoCall()));
   1079         callInfo.put("Details", build(call.getDetails()));
   1080 
   1081         return callInfo;
   1082     }
   1083 
   1084     private static JSONObject buildVideoProfile(VideoProfile videoProfile) throws JSONException {
   1085         JSONObject profile = new JSONObject();
   1086 
   1087         profile.put("VideoState",
   1088                 InCallServiceImpl.getVideoCallStateString(videoProfile.getVideoState()));
   1089         profile.put("VideoQuality",
   1090                 InCallServiceImpl.getVideoCallQualityString(videoProfile.getQuality()));
   1091 
   1092         return profile;
   1093     }
   1094 
   1095     private static JSONObject buildCameraCapabilities(CameraCapabilities cameraCapabilities)
   1096             throws JSONException {
   1097         JSONObject capabilities = new JSONObject();
   1098 
   1099         capabilities.put("Height", build(cameraCapabilities.getHeight()));
   1100         capabilities.put("Width", build(cameraCapabilities.getWidth()));
   1101         capabilities.put("ZoomSupported", build(cameraCapabilities.isZoomSupported()));
   1102         capabilities.put("MaxZoom", build(cameraCapabilities.getMaxZoom()));
   1103 
   1104         return capabilities;
   1105     }
   1106 
   1107     private static JSONObject buildVoLteServiceStateEvent(
   1108             VoLteServiceState volteInfo)
   1109             throws JSONException {
   1110         JSONObject info = new JSONObject();
   1111         info.put(TelephonyConstants.VoLteServiceStateContainer.SRVCC_STATE,
   1112                 TelephonyUtils.getSrvccStateString(volteInfo.getSrvccState()));
   1113         return info;
   1114     }
   1115 
   1116     private static JSONObject buildLegacyVpnInfo(LegacyVpnInfo data) throws JSONException {
   1117         JSONObject info = new JSONObject();
   1118         if (data == null) {
   1119             return info;
   1120         }
   1121         info.put("state", data.state);
   1122         info.put("key", data.key);
   1123         String intentStr = "";
   1124         if (data.intent != null) {
   1125             intentStr = data.intent.toString();
   1126         }
   1127         info.put("intent", intentStr);
   1128         return info;
   1129     }
   1130 
   1131     private static JSONObject buildModemActivityInfo(ModemActivityInfo modemInfo)
   1132             throws JSONException {
   1133         JSONObject info = new JSONObject();
   1134 
   1135         info.put("Timestamp", modemInfo.getTimestamp());
   1136         info.put("SleepTimeMs", modemInfo.getSleepTimeMillis());
   1137         info.put("IdleTimeMs", modemInfo.getIdleTimeMillis());
   1138         // convert from int[] to List<Integer> for proper JSON translation
   1139         int[] txTimes = modemInfo.getTxTimeMillis();
   1140         List<Integer> tmp = new ArrayList<Integer>(txTimes.length);
   1141         for (int val : txTimes) {
   1142             tmp.add(val);
   1143         }
   1144         info.put("TxTimeMs", build(tmp));
   1145         info.put("RxTimeMs", modemInfo.getRxTimeMillis());
   1146         info.put("EnergyUsedMw", modemInfo.getEnergyUsed());
   1147         return info;
   1148     }
   1149 
   1150     private static JSONObject buildSignalStrength(SignalStrength signalStrength)
   1151             throws JSONException {
   1152         JSONObject info = new JSONObject();
   1153         info.put(TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM,
   1154                 signalStrength.getGsmSignalStrength());
   1155         info.put(
   1156                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_DBM,
   1157                 signalStrength.getGsmDbm());
   1158         info.put(
   1159                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_LEVEL,
   1160                 signalStrength.getGsmLevel());
   1161         info.put(
   1162                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_ASU_LEVEL,
   1163                 signalStrength.getGsmAsuLevel());
   1164         info.put(
   1165                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_GSM_BIT_ERROR_RATE,
   1166                 signalStrength.getGsmBitErrorRate());
   1167         info.put(
   1168                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_DBM,
   1169                 signalStrength.getCdmaDbm());
   1170         info.put(
   1171                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_LEVEL,
   1172                 signalStrength.getCdmaLevel());
   1173         info.put(
   1174                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_ASU_LEVEL,
   1175                 signalStrength.getCdmaAsuLevel());
   1176         info.put(
   1177                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_CDMA_ECIO,
   1178                 signalStrength.getCdmaEcio());
   1179         info.put(
   1180                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_EVDO_DBM,
   1181                 signalStrength.getEvdoDbm());
   1182         info.put(
   1183                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_EVDO_ECIO,
   1184                 signalStrength.getEvdoEcio());
   1185         info.put(TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE,
   1186                 signalStrength.getLteSignalStrength());
   1187         info.put(
   1188                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE_DBM,
   1189                 signalStrength.getLteDbm());
   1190         info.put(
   1191                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE_LEVEL,
   1192                 signalStrength.getLteLevel());
   1193         info.put(
   1194                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LTE_ASU_LEVEL,
   1195                 signalStrength.getLteAsuLevel());
   1196         info.put(
   1197                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_LEVEL,
   1198                 signalStrength.getLevel());
   1199         info.put(
   1200                 TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_ASU_LEVEL,
   1201                 signalStrength.getAsuLevel());
   1202         info.put(TelephonyConstants.SignalStrengthContainer.SIGNAL_STRENGTH_DBM,
   1203                 signalStrength.getDbm());
   1204         return info;
   1205     }
   1206 
   1207     private JsonBuilder() {
   1208         // This is a utility class.
   1209     }
   1210 }
   1211