1 
2 package com.googlecode.android_scripting.facade.wifi;
3 
4 import android.app.Service;
5 import android.content.Context;
6 import android.net.wifi.RttManager;
7 import android.net.wifi.RttManager.ResponderCallback;
8 import android.net.wifi.RttManager.ResponderConfig;
9 import android.net.wifi.RttManager.RttCapabilities;
10 import android.net.wifi.RttManager.RttListener;
11 import android.net.wifi.RttManager.RttParams;
12 import android.net.wifi.RttManager.RttResult;
13 import android.os.Bundle;
14 import android.os.Parcelable;
15 
16 import com.googlecode.android_scripting.facade.EventFacade;
17 import com.googlecode.android_scripting.facade.FacadeManager;
18 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
19 import com.googlecode.android_scripting.rpc.Rpc;
20 import com.googlecode.android_scripting.rpc.RpcParameter;
21 
22 import org.json.JSONArray;
23 import org.json.JSONException;
24 import org.json.JSONObject;
25 
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.Hashtable;
29 import java.util.Map;
30 
31 /**
32  * WifiRttManager functions.
33  */
34 public class WifiRttManagerFacade extends RpcReceiver {
35     private final Service mService;
36     private final RttManager mRtt;
37     private final EventFacade mEventFacade;
38     private final Map<Integer, RttListener> mRangingListeners;
39     private final Map<Integer, RttResponderCallback> mResponderCallbacks;
40 
WifiRttManagerFacade(FacadeManager manager)41     public WifiRttManagerFacade(FacadeManager manager) {
42         super(manager);
43         mService = manager.getService();
44         mRtt = (RttManager) mService.getSystemService(Context.WIFI_RTT_SERVICE);
45         mEventFacade = manager.getReceiver(EventFacade.class);
46         mRangingListeners = new Hashtable<Integer, RttListener>();
47         mResponderCallbacks = new HashMap<>();
48     }
49 
50     public static class RangingListener implements RttListener {
51         private static final String TAG = "WifiRttRanging";
52         private static int sCount = 0;
53         private final EventFacade mEventFacade;
54         public final int mId;
55 
RangingListener(EventFacade eventFacade)56         public RangingListener(EventFacade eventFacade) {
57             sCount += 1;
58             mId = sCount;
59             mEventFacade = eventFacade;
60         }
61 
packRttResult(RttResult result)62         private Bundle packRttResult(RttResult result) {
63             Bundle rttResult = new Bundle();
64             rttResult.putString("BSSID", result.bssid);
65             rttResult.putInt("txRate", result.txRate);
66             rttResult.putInt("rxRate", result.rxRate);
67             rttResult.putInt("distance", result.distance);
68             rttResult.putInt("distanceStandardDeviation",
69                     result.distanceStandardDeviation);
70             rttResult.putInt("distanceSpread", result.distanceSpread);
71             rttResult.putInt("burstDuration", result.burstDuration);
72             rttResult.putLong("rtt", result.rtt);
73             rttResult.putLong("rttStandardDeviation",
74                     result.rttStandardDeviation);
75             rttResult.putLong("rttSpread", result.rttSpread);
76             rttResult.putLong("ts", result.ts);
77             rttResult.putInt("rssi", result.rssi);
78             rttResult.putInt("rssiSpread", result.rssiSpread);
79             rttResult.putInt("retryAfterDuration", result.retryAfterDuration);
80             rttResult.putInt("measurementType", result.measurementType);
81             rttResult.putInt("status", result.status);
82             rttResult.putInt("frameNumberPerBurstPeer",
83                     result.frameNumberPerBurstPeer);
84             rttResult.putInt("successMeasurementFrameNumber",
85                     result.successMeasurementFrameNumber);
86             rttResult.putInt("measurementFrameNumber",
87                     result.measurementFrameNumber);
88             rttResult.putInt("burstNumber", result.burstNumber);
89             rttResult.putInt("status", result.status);
90             return rttResult;
91         }
92 
93         @Override
onSuccess(RttResult[] results)94         public void onSuccess(RttResult[] results) {
95             if (results == null) {
96                 mEventFacade
97                         .postEvent(RangingListener.TAG + mId + "onSuccess", null);
98                 return;
99             }
100             Bundle msg = new Bundle();
101             Parcelable[] resultBundles = new Parcelable[results.length];
102             for (int i = 0; i < results.length; i++) {
103                 resultBundles[i] = packRttResult(results[i]);
104             }
105             msg.putParcelableArray("Results", resultBundles);
106             mEventFacade
107                     .postEvent(RangingListener.TAG + mId + "onSuccess", msg);
108         }
109 
110         @Override
onFailure(int reason, String description)111         public void onFailure(int reason, String description) {
112             Bundle msg = new Bundle();
113             msg.putInt("Reason", reason);
114             msg.putString("Description", description);
115             mEventFacade
116                     .postEvent(RangingListener.TAG + mId + "onFailure", msg);
117         }
118 
119         @Override
onAborted()120         public void onAborted() {
121             mEventFacade.postEvent(RangingListener.TAG + mId + "onAborted",
122                     new Bundle());
123         }
124     }
125 
126     /**
127      * A {@link ResponderCallback} that handles success and failures for enabling RTT responder
128      * mode.
129      */
130     private static class RttResponderCallback extends ResponderCallback {
131         private static final String TAG = "WifiRtt";
132 
133         // A monotonic increasing counter for responder callback ids.
134         private static int sCount = 0;
135 
136         private final int mId;
137         private final EventFacade mEventFacade;
138 
RttResponderCallback(EventFacade eventFacade)139         RttResponderCallback(EventFacade eventFacade) {
140             sCount++;
141             mId = sCount;
142             mEventFacade = eventFacade;
143         }
144 
145         @Override
onResponderEnabled(ResponderConfig config)146         public void onResponderEnabled(ResponderConfig config) {
147             Bundle bundle = new Bundle();
148             bundle.putString("macAddress", config.macAddress);
149             bundle.putInt("frequency", config.frequency);
150             bundle.putInt("centerFreq0", config.centerFreq0);
151             bundle.putInt("centerFreq1", config.centerFreq1);
152             bundle.putInt("channelWidth", config.channelWidth);
153             bundle.putInt("preamble", config.preamble);
154             mEventFacade.postEvent(TAG + mId + "onResponderEnabled", bundle);
155         }
156 
157         @Override
onResponderEnableFailure(int reason)158         public void onResponderEnableFailure(int reason) {
159             Bundle bundle = new Bundle();
160             bundle.putInt("reason", reason);
161             mEventFacade.postEvent(TAG + mId + "onResponderEnableFailure", bundle);
162         }
163     }
164 
165     @Rpc(description = "Get wifi Rtt capabilities.")
wifiRttGetCapabilities()166     public RttCapabilities wifiRttGetCapabilities() {
167         return mRtt.getRttCapabilities();
168     }
169 
parseRttParam(JSONObject j)170     private RttParams parseRttParam(JSONObject j) throws JSONException {
171         RttParams result = new RttParams();
172         if (j.has("deviceType")) {
173             result.deviceType = j.getInt("deviceType");
174         }
175         if (j.has("requestType")) {
176             result.requestType = j.getInt("requestType");
177         }
178         if (j.has("bssid")) {
179             result.bssid = j.getString("bssid");
180         }
181         if (j.has("frequency")) {
182             result.frequency = j.getInt("frequency");
183         }
184         if (j.has("channelWidth")) {
185             result.channelWidth = j.getInt("channelWidth");
186         }
187         if (j.has("centerFreq0")) {
188             result.centerFreq0 = j.getInt("centerFreq0");
189         }
190         if (j.has("centerFreq1")) {
191             result.centerFreq1 = j.getInt("centerFreq1");
192         }
193         if (j.has("numberBurst")) {
194             result.numberBurst = j.getInt("numberBurst");
195         }
196         if (j.has("burstTimeout")) {
197             result.burstTimeout = j.getInt("burstTimeout");
198         }
199         if (j.has("interval")) {
200             result.interval = j.getInt("interval");
201         }
202         if (j.has("numSamplesPerBurst")) {
203             result.numSamplesPerBurst = j.getInt("numSamplesPerBurst");
204         }
205         if (j.has("numRetriesPerMeasurementFrame")) {
206             result.numRetriesPerMeasurementFrame = j
207                     .getInt("numRetriesPerMeasurementFrame");
208         }
209         if (j.has("numRetriesPerFTMR")) {
210             result.numRetriesPerFTMR = j.getInt("numRetriesPerFTMR");
211         }
212         if (j.has("LCIRequest")) {
213             result.LCIRequest = j.getBoolean("LCIRequest");
214         }
215         if (j.has("LCRRequest")) {
216             result.LCRRequest = j.getBoolean("LCRRequest");
217         }
218         if (j.has("preamble")) {
219             result.preamble = j.getInt("preamble");
220         }
221         if (j.has("bandwidth")) {
222             result.bandwidth = j.getInt("bandwidth");
223         }
224         return result;
225     }
226 
227     /**
228      * Start WiFi RTT ranging using the given params. Returns the id associated with the
229      * {@link RttListener} used for ranging.
230      */
231     @Rpc(description = "Start ranging.", returns = "Id of the listener associated with the "
232             + "started ranging.")
wifiRttStartRanging( @pcParametername = "params") JSONArray params)233     public Integer wifiRttStartRanging(
234             @RpcParameter(name = "params") JSONArray params)
235             throws JSONException {
236         RttParams[] rParams = new RttParams[params.length()];
237         for (int i = 0; i < params.length(); i++) {
238             rParams[i] = parseRttParam(params.getJSONObject(i));
239         }
240         RangingListener listener = new RangingListener(mEventFacade);
241         mRangingListeners.put(listener.mId, listener);
242         mRtt.startRanging(rParams, listener);
243         return listener.mId;
244     }
245 
246     /**
247      * Stop WiFi Rtt ranging for {@link RttListener} identified by the given {@code index}.
248      */
249     @Rpc(description = "Stop ranging.")
wifiRttStopRanging(@pcParametername = "index") Integer index)250     public void wifiRttStopRanging(@RpcParameter(name = "index") Integer index) {
251         mRtt.stopRanging(mRangingListeners.remove(index));
252     }
253 
254     /**
255      * Enable WiFi RTT responder role. Returns the id associated with the {@link ResponderCallback}
256      * used for enabling responder.
257      */
258     @Rpc(description = "Enable responder", returns = "Id of the callback associated with enabling")
wifiRttEnableResponder()259     public Integer wifiRttEnableResponder() {
260         RttResponderCallback callback = new RttResponderCallback(mEventFacade);
261         mResponderCallbacks.put(callback.mId, callback);
262         mRtt.enableResponder(callback);
263         return callback.mId;
264     }
265 
266     /**
267      * Disable WiFi RTT responder role for the {@link ResponderCallback} identified by the given
268      * {@code index}.
269      */
270     @Rpc(description = "Disable responder")
wifiRttDisableResponder(@pcParametername = "index") Integer index)271     public void wifiRttDisableResponder(@RpcParameter(name = "index") Integer index) {
272         mRtt.disableResponder(mResponderCallbacks.remove(index));
273     }
274 
275     @Override
shutdown()276     public void shutdown() {
277         ArrayList<Integer> keys = new ArrayList<Integer>(
278                 mRangingListeners.keySet());
279         for (int k : keys) {
280             wifiRttStopRanging(k);
281         }
282         for (int index : mResponderCallbacks.keySet()) {
283             wifiRttDisableResponder(index);
284         }
285     }
286 }
287