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