1 package org.robolectric.shadows;
2 
3 import static android.bluetooth.BluetoothDevice.BOND_NONE;
4 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
5 import static org.robolectric.shadow.api.Shadow.directlyOn;
6 
7 import android.bluetooth.BluetoothDevice;
8 import android.bluetooth.BluetoothGatt;
9 import android.bluetooth.BluetoothGattCallback;
10 import android.bluetooth.IBluetooth;
11 import android.content.Context;
12 import android.os.ParcelUuid;
13 import org.robolectric.annotation.Implementation;
14 import org.robolectric.annotation.Implements;
15 import org.robolectric.annotation.RealObject;
16 import org.robolectric.util.ReflectionHelpers;
17 
18 @Implements(BluetoothDevice.class)
19 public class ShadowBluetoothDevice {
20 
newInstance(String address)21   public static BluetoothDevice newInstance(String address) {
22     return ReflectionHelpers.callConstructor(
23         BluetoothDevice.class, ReflectionHelpers.ClassParameter.from(String.class, address));
24   }
25 
26   @RealObject private BluetoothDevice realBluetoothDevice;
27   private String name;
28   private ParcelUuid[] uuids;
29   private int bondState = BOND_NONE;
30   private boolean createdBond = false;
31   private boolean fetchUuidsWithSdpResult = false;
32   private int fetchUuidsWithSdpCount = 0;
33 
34   /**
35    * Implements getService() in the same way the original method does, but ignores any Exceptions
36    * from invoking {@link android.bluetooth.BluetoothAdapter#getBluetoothService}.
37    */
38   @Implementation
getService()39   protected static IBluetooth getService() {
40     // Attempt to call the underlying getService method, but ignore any Exceptions. This allows us
41     // to easily create BluetoothDevices for testing purposes without having any actual Bluetooth
42     // capability.
43     try {
44       return directlyOn(BluetoothDevice.class, "getService");
45     } catch (Exception e) {
46       // No-op.
47     }
48     return null;
49   }
50 
setName(String name)51   public void setName(String name) {
52     this.name = name;
53   }
54 
55   @Implementation
getName()56   protected String getName() {
57     return name;
58   }
59 
60   /** Sets the return value for {@link BluetoothDevice#getUuids}. */
setUuids(ParcelUuid[] uuids)61   public void setUuids(ParcelUuid[] uuids) {
62     this.uuids = uuids;
63   }
64 
65   /**
66    * Overrides behavior of {@link BluetoothDevice#getUuids} to return pre-set result.
67    *
68    * @returns Value set by calling {@link ShadowBluetoothDevice#setUuids}. If setUuids has not
69    *     previously been called, will return null.
70    */
71   @Implementation
getUuids()72   protected ParcelUuid[] getUuids() {
73     return uuids;
74   }
75 
76   /** Sets value of bond state for {@link BluetoothDevice#getBondState}. */
setBondState(int bondState)77   public void setBondState(int bondState) {
78     this.bondState = bondState;
79   }
80 
81   /**
82    * Overrides behavior of {@link BluetoothDevice#getBondState} to return pre-set result.
83    *
84    * @returns Value set by calling {@link ShadowBluetoothDevice#setBondState}. If setBondState has
85    *     not previously been called, will return {@link BluetoothDevice#BOND_NONE} to indicate the
86    *     device is not bonded.
87    */
88   @Implementation
getBondState()89   protected int getBondState() {
90     return bondState;
91   }
92 
93   /** Sets whether this device has been bonded with. */
setCreatedBond(boolean createdBond)94   public void setCreatedBond(boolean createdBond) {
95     this.createdBond = createdBond;
96   }
97 
98   /** Returns whether this device has been bonded with. */
99   @Implementation
createBond()100   protected boolean createBond() {
101     return createdBond;
102   }
103 
104   /** Sets value of the return result for {@link BluetoothDevice#fetchUuidsWithSdp}. */
setFetchUuidsWithSdpResult(boolean fetchUuidsWithSdpResult)105   public void setFetchUuidsWithSdpResult(boolean fetchUuidsWithSdpResult) {
106     this.fetchUuidsWithSdpResult = fetchUuidsWithSdpResult;
107   }
108 
109   /**
110    * Overrides behavior of {@link BluetoothDevice#fetchUuidsWithSdp}. This method updates the
111    * counter which counts the number of invocations of this method.
112    *
113    * @returns Value set by calling {@link ShadowBluetoothDevice#setFetchUuidsWithSdpResult}. If not
114    *     previously set, will return false by default.
115    */
116   @Implementation
fetchUuidsWithSdp()117   protected boolean fetchUuidsWithSdp() {
118     fetchUuidsWithSdpCount++;
119     return fetchUuidsWithSdpResult;
120   }
121 
122   /** Returns the number of times fetchUuidsWithSdp has been called. */
getFetchUuidsWithSdpCount()123   public int getFetchUuidsWithSdpCount() {
124     return fetchUuidsWithSdpCount;
125   }
126 
127   @Implementation(minSdk = JELLY_BEAN_MR2)
connectGatt( Context context, boolean autoConnect, BluetoothGattCallback callback)128   protected BluetoothGatt connectGatt(
129       Context context, boolean autoConnect, BluetoothGattCallback callback) {
130     return ShadowBluetoothGatt.newInstance(realBluetoothDevice);
131   }
132 }
133