WifiRttManager.java revision 58019f524f8180423a6e46b83fa3564267612e39
117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenpackage android.net.wifi.rtt;
217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport static android.Manifest.permission.ACCESS_COARSE_LOCATION;
417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport static android.Manifest.permission.ACCESS_WIFI_STATE;
517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport static android.Manifest.permission.CHANGE_WIFI_STATE;
617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.Nullable;
817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.RequiresPermission;
958019f524f8180423a6e46b83fa3564267612e39Etan Cohenimport android.annotation.SdkConstant;
1017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.SystemService;
1117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.content.Context;
1217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Binder;
1317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Handler;
1417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Looper;
1517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.RemoteException;
1617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.util.Log;
1717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
1817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport java.util.List;
1917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
2017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen/**
2117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * This class provides the primary API for measuring distance (range) to other devices using the
2217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * IEEE 802.11mc Wi-Fi Round Trip Time (RTT) technology.
2317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <p>
2417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * The devices which can be ranged include:
2517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <li>Access Points (APs)
2658019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <li>Wi-Fi Aware peers
2717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <p>
2817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Ranging requests are triggered using
2917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * {@link #startRanging(RangingRequest, RangingResultCallback, Handler)}. Results (in case of
3017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * successful operation) are returned in the {@link RangingResultCallback#onRangingResults(List)}
3117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * callback.
3258019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <p>
3358019f524f8180423a6e46b83fa3564267612e39Etan Cohen *     Wi-Fi RTT may not be usable at some points, e.g. when Wi-Fi is disabled. To validate that
3458019f524f8180423a6e46b83fa3564267612e39Etan Cohen *     the functionality is available use the {@link #isAvailable()} function. To track
3558019f524f8180423a6e46b83fa3564267612e39Etan Cohen *     changes in RTT usability register for the {@link #ACTION_WIFI_RTT_STATE_CHANGED}
3658019f524f8180423a6e46b83fa3564267612e39Etan Cohen *     broadcast. Note that this broadcast is not sticky - you should register for it and then
3758019f524f8180423a6e46b83fa3564267612e39Etan Cohen *     check the above API to avoid a race condition.
3817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen *
3917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @hide RTT_API
4017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen */
4117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen@SystemService(Context.WIFI_RTT2_SERVICE)
4217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenpublic class WifiRttManager {
4317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    private static final String TAG = "WifiRttManager";
4417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    private static final boolean VDBG = true;
4517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
4617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    private final Context mContext;
4717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    private final IWifiRttManager mService;
4817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
4958019f524f8180423a6e46b83fa3564267612e39Etan Cohen    /**
5058019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * Broadcast intent action to indicate that the state of Wi-Fi RTT availability has changed.
5158019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * Use the {@link #isAvailable()} to query the current status.
5258019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
5358019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * the broadcast to check the current state of Wi-Fi RTT.
5458019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
5558019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * components will be launched.
5658019f524f8180423a6e46b83fa3564267612e39Etan Cohen     */
5758019f524f8180423a6e46b83fa3564267612e39Etan Cohen    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
5858019f524f8180423a6e46b83fa3564267612e39Etan Cohen    public static final String ACTION_WIFI_RTT_STATE_CHANGED =
5958019f524f8180423a6e46b83fa3564267612e39Etan Cohen            "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED";
6058019f524f8180423a6e46b83fa3564267612e39Etan Cohen
6117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    /** @hide */
6217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    public WifiRttManager(Context context, IWifiRttManager service) {
6317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        mContext = context;
6417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        mService = service;
6517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    }
6617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
6717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    /**
6858019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * Returns the current status of RTT API: whether or not RTT is available. To track
6958019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * changes in the state of RTT API register for the
7058019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * {@link #ACTION_WIFI_RTT_STATE_CHANGED} broadcast.
7158019f524f8180423a6e46b83fa3564267612e39Etan Cohen     *
7258019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * @return A boolean indicating whether the app can use the RTT API at this time (true) or
7358019f524f8180423a6e46b83fa3564267612e39Etan Cohen     * not (false).
7458019f524f8180423a6e46b83fa3564267612e39Etan Cohen     */
7558019f524f8180423a6e46b83fa3564267612e39Etan Cohen    public boolean isAvailable() {
7658019f524f8180423a6e46b83fa3564267612e39Etan Cohen        try {
7758019f524f8180423a6e46b83fa3564267612e39Etan Cohen            return mService.isAvailable();
7858019f524f8180423a6e46b83fa3564267612e39Etan Cohen        } catch (RemoteException e) {
7958019f524f8180423a6e46b83fa3564267612e39Etan Cohen            throw e.rethrowFromSystemServer();
8058019f524f8180423a6e46b83fa3564267612e39Etan Cohen        }
8158019f524f8180423a6e46b83fa3564267612e39Etan Cohen    }
8258019f524f8180423a6e46b83fa3564267612e39Etan Cohen
8358019f524f8180423a6e46b83fa3564267612e39Etan Cohen    /**
8417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     * Initiate a request to range to a set of devices specified in the {@link RangingRequest}.
8517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     * Results will be returned in the {@link RangingResultCallback} set of callbacks.
8617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     *
8717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     * @param request  A request specifying a set of devices whose distance measurements are
8817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     *                 requested.
8917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     * @param callback A callback for the result of the ranging request.
9017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     * @param handler  The Handler on whose thread to execute the callbacks of the {@code
9117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     *                 callback} object. If a null is provided then the application's main thread
9217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     *                 will be used.
9317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen     */
9417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE})
9517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    public void startRanging(RangingRequest request, RangingResultCallback callback,
9617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen            @Nullable Handler handler) {
9717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        if (VDBG) {
9817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen            Log.v(TAG, "startRanging: request=" + request + ", callback=" + callback + ", handler="
9917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen                    + handler);
10017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        }
10117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
10217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
10317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        Binder binder = new Binder();
10417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        try {
10517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen            mService.startRanging(binder, mContext.getOpPackageName(), request,
10617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen                    new RttCallbackProxy(looper, callback));
10717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        } catch (RemoteException e) {
10817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen            throw e.rethrowFromSystemServer();
10917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        }
11017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    }
11117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
11217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    private static class RttCallbackProxy extends IRttCallback.Stub {
11317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        private final Handler mHandler;
11417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        private final RangingResultCallback mCallback;
11517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
11617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        RttCallbackProxy(Looper looper, RangingResultCallback callback) {
11717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen            mHandler = new Handler(looper);
11817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen            mCallback = callback;
11917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        }
12017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen
12117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        @Override
122210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen        public void onRangingFailure(int status) throws RemoteException {
123210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen            if (VDBG) Log.v(TAG, "RttCallbackProxy: onRangingFailure: status=" + status);
12417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen            mHandler.post(() -> {
125210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen               mCallback.onRangingFailure(status);
126210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen            });
127210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen        }
128210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen
129210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen        @Override
130210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen        public void onRangingResults(List<RangingResult> results) throws RemoteException {
131210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen            if (VDBG) Log.v(TAG, "RttCallbackProxy: onRanginResults: results=" + results);
132210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen            mHandler.post(() -> {
133210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen               mCallback.onRangingResults(results);
13417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen            });
13517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen        }
13617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen    }
13717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen}
138