Merge "Facade functions for wifi tethering tests"
diff --git a/Common/src/com/googlecode/android_scripting/facade/ApplicationManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/ApplicationManagerFacade.java
index 1292fe5..e8207c7 100644
--- a/Common/src/com/googlecode/android_scripting/facade/ApplicationManagerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/ApplicationManagerFacade.java
@@ -76,6 +76,14 @@
     mAndroidFacade.startActivity(intent);
   }
 
+  @Rpc(description = "Start activity with the given class name with result")
+  public Intent launchForResult(@RpcParameter(name = "className") String className) {
+    Intent intent = new Intent(Intent.ACTION_MAIN);
+    String packageName = className.substring(0, className.lastIndexOf("."));
+    intent.setClassName(packageName, className);
+    return mAndroidFacade.startActivityForResult(intent);
+  }
+
   @Rpc(description = "Launch the specified app.")
   public void appLaunch(@RpcParameter(name = "name") String name) {
       Intent LaunchIntent = mPackageManager.getLaunchIntentForPackage(name);
diff --git a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHspFacade.java b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHspFacade.java
index 50de64e..0af2b9c 100644
--- a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHspFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHspFacade.java
@@ -16,12 +16,10 @@
 
 package com.googlecode.android_scripting.facade.bluetooth;
 
-import java.util.List;
-
 import android.app.Service;
-import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
 import android.os.ParcelUuid;
@@ -32,6 +30,8 @@
 import com.googlecode.android_scripting.rpc.Rpc;
 import com.googlecode.android_scripting.rpc.RpcParameter;
 
+import java.util.List;
+
 public class BluetoothHspFacade extends RpcReceiver {
   static final ParcelUuid[] UUIDS = {
     BluetoothUuid.HSP, BluetoothUuid.Handsfree
@@ -142,6 +142,108 @@
       return sHspProfile.getConnectionState(device);
   }
 
+  /**
+   * Force SCO audio on DUT, ignore all other restrictions
+   *
+   * @param force True to force SCO audio, False to resume normal
+   * @return True if the setup is successful
+   */
+  @Rpc(description = "Force SCO audio connection on DUT")
+  public Boolean bluetoothHspForceScoAudio(
+          @RpcParameter(name = "force", description = "whether to force SCO audio")
+                  Boolean force) {
+    if (sHspProfile == null) {
+      return false;
+    }
+    sHspProfile.setForceScoAudio(force);
+    return true;
+  }
+
+  /**
+   * Connect SCO audio to a remote device
+   *
+   * @param deviceAddress the Bluetooth MAC address of remote device
+   * @return True if connection is successful, False otherwise
+   */
+  @Rpc(description = "Connect SCO audio for a remote device")
+  public Boolean bluetoothHspConnectAudio(
+          @RpcParameter(name = "deviceAddress", description = "MAC address of a bluetooth device.")
+                  String deviceAddress) {
+    if (sHspProfile == null) {
+      return false;
+    }
+    Log.d("Connected devices: " + sHspProfile.getConnectedDevices());
+    BluetoothDevice device = null;
+    if (sHspProfile.getConnectedDevices().size() > 1) {
+      Log.d("More than one device available");
+    }
+    try {
+      device = BluetoothFacade.getDevice(sHspProfile.getConnectedDevices(), deviceAddress);
+    } catch (Exception e) {
+      Log.d("Cannot find device " + deviceAddress);
+      return false;
+    }
+    return sHspProfile.connectAudio();
+  }
+
+  /**
+   * Disconnect SCO audio for a remote device
+   *
+   * @param deviceAddress the Bluetooth MAC address of remote device
+   * @return True if disconnection is successful, False otherwise
+   */
+  @Rpc(description = "Disconnect SCO audio for a remote device")
+  public Boolean bluetoothHspDisconnectAudio(
+          @RpcParameter(name = "deviceAddress", description = "MAC address of a bluetooth device.")
+                  String deviceAddress) {
+    if (sHspProfile == null) {
+      return false;
+    }
+    Log.d("Connected devices: " + sHspProfile.getConnectedDevices());
+    BluetoothDevice device = null;
+    if (sHspProfile.getConnectedDevices().size() > 1) {
+      Log.d("More than one device available");
+    }
+    try {
+      device = BluetoothFacade.getDevice(sHspProfile.getConnectedDevices(), deviceAddress);
+    } catch (Exception e) {
+      Log.d("Cannot find device " + deviceAddress);
+      return false;
+    }
+    if (!sHspProfile.isAudioConnected(device)) {
+      Log.d("SCO audio is not connected for device " + deviceAddress);
+      return false;
+    }
+    return sHspProfile.disconnectAudio();
+  }
+
+  /**
+   * Check if SCO audio is connected for a remote device
+   *
+   * @param deviceAddress the Bluetooth MAC address of remote device
+   * @return True if device is connected to us via SCO audio, False otherwise
+   */
+  @Rpc(description = "Check if SCO audio is connected for a remote device")
+  public Boolean bluetoothHspIsAudioConnected(
+          @RpcParameter(name = "deviceAddress", description = "MAC address of a bluetooth device.")
+                  String deviceAddress) {
+    if (sHspProfile == null) {
+      return false;
+    }
+    Log.d("Connected devices: " + sHspProfile.getConnectedDevices());
+    BluetoothDevice device = null;
+    if (sHspProfile.getConnectedDevices().size() > 1) {
+      Log.d("More than one device available");
+    }
+    try {
+      device = BluetoothFacade.getDevice(sHspProfile.getConnectedDevices(), deviceAddress);
+    } catch (Exception e) {
+      Log.d("Cannot find device " + deviceAddress);
+      return false;
+    }
+    return sHspProfile.isAudioConnected(device);
+  }
+
   @Override
   public void shutdown() {
   }
diff --git a/Common/src/com/googlecode/android_scripting/facade/bluetooth/GattClientFacade.java b/Common/src/com/googlecode/android_scripting/facade/bluetooth/GattClientFacade.java
index f9f012c..bd2da3a 100644
--- a/Common/src/com/googlecode/android_scripting/facade/bluetooth/GattClientFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/bluetooth/GattClientFacade.java
@@ -20,7 +20,6 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothGatt;
-import android.bluetooth.IBluetoothGatt;
 import android.bluetooth.BluetoothGattCallback;
 import android.bluetooth.BluetoothGattCharacteristic;
 import android.bluetooth.BluetoothGattDescriptor;
@@ -39,12 +38,11 @@
 import com.googlecode.android_scripting.rpc.RpcParameter;
 import com.googlecode.android_scripting.rpc.RpcStopEvent;
 
-import java.lang.reflect.*;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
-import java.util.concurrent.Callable;
 import java.util.UUID;
+import java.util.concurrent.Callable;
 
 public class GattClientFacade extends RpcReceiver {
     private final EventFacade mEventFacade;
@@ -99,6 +97,9 @@
      * @param macAddress the mac address of the ble device
      * @param autoConnect Whether to directly connect to the remote device (false) or to
      *       automatically connect as soon as the remote device becomes available (true)
+     * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client
+     *                      does not hold a GATT connection. It automatically disconnects when no
+     *                      other GATT connections are active for the remote device.
      * @param transport preferred transport for GATT connections to remote dual-mode devices
      *       TRANSPORT_AUTO or TRANSPORT_BREDR or TRANSPORT_LE
      * @return the index of the BluetoothGatt object
@@ -110,19 +111,15 @@
             @RpcParameter(name = "macAddress") String macAddress,
             @RpcParameter(name = "autoConnect") Boolean autoConnect,
             @RpcParameter(name = "transport") Integer transport,
+            @RpcParameter(name = "opportunistic") Boolean opportunistic,
             @RpcParameter(name = "phy") Integer phy)
             throws Exception {
         if (mGattCallbackList.get(index) != null) {
             BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
             if (phy == null) phy = BluetoothDevice.PHY_LE_1M;
 
-            BluetoothGatt mBluetoothGatt =
-                    device.connectGatt(
-                            mService.getApplicationContext(),
-                            autoConnect,
-                            mGattCallbackList.get(index),
-                            transport,
-                            phy);
+            BluetoothGatt mBluetoothGatt = device.connectGatt(mService.getApplicationContext(),
+                    autoConnect, mGattCallbackList.get(index), transport, opportunistic, phy, null);
             BluetoothGattCount += 1;
             mBluetoothGattList.put(BluetoothGattCount, mBluetoothGatt);
             return BluetoothGattCount;
@@ -1788,7 +1785,7 @@
     /**
      * Sets the characteristic notification of a bluetooth gatt
      *
-     * @param index the bluetooth gatt index
+     * @param gattIndex the bluetooth gatt index
      * @param characteristicIndex the characteristic index
      * @param enable Enable or disable notifications/indications for a given characteristic
      * @return true, if the requested notification status was set successfully
diff --git a/Common/src/com/googlecode/android_scripting/facade/telephony/TelephonyManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/telephony/TelephonyManagerFacade.java
index 4f3de5e..fd343df 100644
--- a/Common/src/com/googlecode/android_scripting/facade/telephony/TelephonyManagerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/telephony/TelephonyManagerFacade.java
@@ -1242,6 +1242,30 @@
         return null;
     }
 
+    /**
+    * Read the value of a NV item.
+    * @param itemId Integer the NV item id to be read.
+    * @return the NV item value String.
+    */
+    @Rpc(description = "Returns the NV item as a String")
+    public String telephonyNvReadItem(
+                   @RpcParameter(name = "itemId") Integer itemId) {
+        return mTelephonyManager.nvReadItem(itemId);
+    }
+
+    /**
+    * Write a value to a NV item.
+    * @param itemId Integer the NV item id to be written.
+    * @param itemValue String the NV item value to be written.
+    * @return true or false for successfully or unsuccessfully writing.
+    */
+    @Rpc(description = "Write the NV item by itemId and String value")
+    public Boolean telephonyNvWriteItem(
+                   @RpcParameter(name = "itemId") Integer itemId,
+                   @RpcParameter(name = "itemValue") String itemValue) {
+        return mTelephonyManager.nvWriteItem(itemId, itemValue);
+    }
+
     private StateChangeListener getStateChangeListenerForSubscription(
             int subId,
             boolean createIfNeeded) {
diff --git a/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java b/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
index fa15248..9499498 100644
--- a/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
+++ b/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
@@ -733,6 +733,8 @@
         result.put("mnc", cellidentity.getMnc());
         result.put("cid", cellidentity.getCid());
         result.put("lac", cellidentity.getLac());
+        result.put("bsic", cellidentity.getBsic());
+        result.put("arfcn", cellidentity.getArfcn());
         result.put("signal_strength", signalstrength.getDbm());
         result.put("asulevel", signalstrength.getAsuLevel());
         return result;
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..7c87dfa
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,6 @@
+bettyzhou@google.com
+bmahadev@google.com
+etancohen@google.com
+jpawlowski@google.com
+krisr@google.com
+tturney@google.com