1 2package com.googlecode.android_scripting.facade.wifi; 3 4import android.app.Service; 5import android.content.Context; 6import android.net.wifi.RttManager; 7import android.net.wifi.RttManager.ResponderCallback; 8import android.net.wifi.RttManager.ResponderConfig; 9import android.net.wifi.RttManager.RttCapabilities; 10import android.net.wifi.RttManager.RttListener; 11import android.net.wifi.RttManager.RttParams; 12import android.net.wifi.RttManager.RttResult; 13import android.os.Bundle; 14import android.os.Parcelable; 15 16import com.googlecode.android_scripting.facade.EventFacade; 17import com.googlecode.android_scripting.facade.FacadeManager; 18import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 19import com.googlecode.android_scripting.rpc.Rpc; 20import com.googlecode.android_scripting.rpc.RpcParameter; 21 22import org.json.JSONArray; 23import org.json.JSONException; 24import org.json.JSONObject; 25 26import java.util.ArrayList; 27import java.util.HashMap; 28import java.util.Hashtable; 29import java.util.Map; 30 31/** 32 * WifiRttManager functions. 33 */ 34public 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 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 56 public RangingListener(EventFacade eventFacade) { 57 sCount += 1; 58 mId = sCount; 59 mEventFacade = eventFacade; 60 } 61 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 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 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 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 139 RttResponderCallback(EventFacade eventFacade) { 140 sCount++; 141 mId = sCount; 142 mEventFacade = eventFacade; 143 } 144 145 @Override 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 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.") 166 public RttCapabilities wifiRttGetCapabilities() { 167 return mRtt.getRttCapabilities(); 168 } 169 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.") 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.") 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") 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") 271 public void wifiRttDisableResponder(@RpcParameter(name = "index") Integer index) { 272 mRtt.disableResponder(mResponderCallbacks.remove(index)); 273 } 274 275 @Override 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