17335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen/*
27335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * Copyright (C) 2016 The Android Open Source Project
37335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen *
47335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * Licensed under the Apache License, Version 2.0 (the "License");
57335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * you may not use this file except in compliance with the License.
67335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * You may obtain a copy of the License at
77335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen *
87335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen *      http://www.apache.org/licenses/LICENSE-2.0
97335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen *
107335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * Unless required by applicable law or agreed to in writing, software
117335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * distributed under the License is distributed on an "AS IS" BASIS,
127335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * See the License for the specific language governing permissions and
147335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * limitations under the License.
157335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen */
167335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
174b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohenpackage com.android.server.wifi.aware;
187335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
197335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.content.Context;
207335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.net.wifi.IRttManager;
217335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.net.wifi.RttManager;
227335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.os.Bundle;
237335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.os.Handler;
247335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.os.IBinder;
257335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.os.Looper;
267335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.os.Message;
277335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.os.Messenger;
287335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.os.RemoteException;
297335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.os.ServiceManager;
307335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.util.Log;
317335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport android.util.SparseArray;
327335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
337335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport com.android.internal.annotations.VisibleForTesting;
347335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport com.android.internal.util.AsyncChannel;
357335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
367335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport java.io.FileDescriptor;
377335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport java.io.PrintWriter;
387335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohenimport java.util.Arrays;
397335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
407335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
417335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen/**
424b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen * Manages interactions between the Aware and the RTT service. Duplicates some of the functionality
437335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen * of the RttManager.
447335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen */
454b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohenpublic class WifiAwareRttStateManager {
464b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen    private static final String TAG = "WifiAwareRttStateMgr";
477335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
48f9280778f0a448e40b457a88c4f7830201fca104Etan Cohen    private static final boolean DBG = false;
49f9280778f0a448e40b457a88c4f7830201fca104Etan Cohen    private static final boolean VDBG = false; // STOPSHIP if true
507335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
514b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen    private final SparseArray<WifiAwareClientState> mPendingOperations = new SparseArray<>();
527335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    private AsyncChannel mAsyncChannel;
537335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
547335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    /**
557335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen     * Initializes the connection to the RTT service.
567335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen     */
577335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    public void start(Context context, Looper looper) {
587335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        if (VDBG) Log.v(TAG, "start()");
597335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
607335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        IBinder b = ServiceManager.getService(Context.WIFI_RTT_SERVICE);
617335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        IRttManager service = IRttManager.Stub.asInterface(b);
627335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        if (service == null) {
637335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            Log.e(TAG, "start(): not able to get WIFI_RTT_SERVICE");
647335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            return;
657335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        }
667335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
677335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        startWithRttService(context, looper, service);
687335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    }
697335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
707335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    /**
717335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen     * Initializes the connection to the RTT service.
727335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen     */
737335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    @VisibleForTesting
747335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    public void startWithRttService(Context context, Looper looper, IRttManager service) {
757335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        Messenger messenger;
767335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        try {
777335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            messenger = service.getMessenger();
787335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        } catch (RemoteException e) {
797335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            Log.e(TAG, "start(): not able to getMessenger() of WIFI_RTT_SERVICE");
807335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            return;
817335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        }
827335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
837335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        mAsyncChannel = new AsyncChannel();
844b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen        mAsyncChannel.connect(context, new AwareRttHandler(looper), messenger);
857335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    }
867335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
874b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen    private WifiAwareClientState getAndRemovePendingOperationClient(int rangingId) {
884b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen        WifiAwareClientState client = mPendingOperations.get(rangingId);
897335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        mPendingOperations.delete(rangingId);
907335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        return client;
917335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    }
927335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
937335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    /**
947335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen     * Start a ranging operation for the client + peer MAC.
957335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen     */
964b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen    public void startRanging(int rangingId, WifiAwareClientState client,
977335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                             RttManager.RttParams[] params) {
987335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        if (VDBG) {
997335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            Log.v(TAG, "startRanging: rangingId=" + rangingId + ", parms="
1007335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    + Arrays.toString(params));
1017335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        }
1027335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
1037335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        if (mAsyncChannel == null) {
1047335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            Log.d(TAG, "startRanging(): AsyncChannel to RTT service not configured - failing");
1057335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            client.onRangingFailure(rangingId, RttManager.REASON_NOT_AVAILABLE,
1064b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen                    "Aware service not able to configure connection to RTT service");
1077335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            return;
1087335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        }
1097335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
1107335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        mPendingOperations.put(rangingId, client);
1117335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        RttManager.ParcelableRttParams pparams = new RttManager.ParcelableRttParams(params);
1127335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        mAsyncChannel.sendMessage(RttManager.CMD_OP_START_RANGING, 0, rangingId, pparams);
1137335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    }
1147335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
1154b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen    private class AwareRttHandler extends Handler {
1164b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen        AwareRttHandler(Looper looper) {
1177335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            super(looper);
1187335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        }
1197335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
1207335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        @Override
1217335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        public void handleMessage(Message msg) {
1227335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            if (VDBG) Log.v(TAG, "handleMessage(): " + msg.what);
1237335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
1247335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            // channel configuration messages
1257335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            switch (msg.what) {
1267335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
1277335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
1287335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
1297335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    } else {
1307335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        Log.e(TAG, "Failed to set up channel connection to RTT service");
1317335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        mAsyncChannel = null;
1327335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    }
1337335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    return;
1347335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
1357335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    /* NOP */
1367335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    return;
1377335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
1387335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    Log.e(TAG, "Channel connection to RTT service lost");
1397335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    mAsyncChannel = null;
1407335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    return;
1417335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            }
1427335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
1437335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            // RTT-specific messages
1444b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen            WifiAwareClientState client = getAndRemovePendingOperationClient(msg.arg2);
1457335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            if (client == null) {
1467335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                Log.e(TAG, "handleMessage(): RTT message (" + msg.what
1477335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        + ") -- cannot find registered pending operation client for ID "
1487335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        + msg.arg2);
1497335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                return;
1507335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            }
1517335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
1527335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            switch (msg.what) {
1537335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                case RttManager.CMD_OP_SUCCEEDED: {
1547335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    int rangingId = msg.arg2;
1557335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    RttManager.ParcelableRttResults results = (RttManager.ParcelableRttResults)
1567335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                            msg.obj;
1577335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    if (VDBG) {
1587335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        Log.v(TAG, "CMD_OP_SUCCEEDED: rangingId=" + rangingId + ", results="
1597335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                                + results);
1607335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    }
1617335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    for (int i = 0; i < results.mResults.length; ++i) {
1627335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        /*
1637335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                         * TODO: store peer ID rather than null in the return result.
1647335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                         */
1657335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        results.mResults[i].bssid = null;
1667335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    }
1677335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    client.onRangingSuccess(rangingId, results);
1687335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    break;
1697335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                }
1707335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                case RttManager.CMD_OP_FAILED: {
1717335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    int rangingId = msg.arg2;
1727335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    int reason = msg.arg1;
1737335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    String description = ((Bundle) msg.obj).getString(RttManager.DESCRIPTION_KEY);
1747335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    if (VDBG) {
1757335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        Log.v(TAG, "CMD_OP_FAILED: rangingId=" + rangingId + ", reason=" + reason
1767335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                                + ", description=" + description);
1777335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    }
1787335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    client.onRangingFailure(rangingId, reason, description);
1797335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    break;
1807335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                }
1817335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                case RttManager.CMD_OP_ABORTED: {
1827335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    int rangingId = msg.arg2;
1837335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    if (VDBG) {
1847335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                        Log.v(TAG, "CMD_OP_ABORTED: rangingId=" + rangingId);
1857335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    }
1867335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    client.onRangingAborted(rangingId);
1877335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    break;
1887335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                }
1897335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                default:
1907335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    Log.e(TAG, "handleMessage(): ignoring message " + msg.what);
1917335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen                    break;
1927335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen            }
1937335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        }
1947335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    }
1957335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen
1967335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    /**
1977335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen     * Dump the internal state of the class.
1987335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen     */
1997335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2004b13f1b486440044f27de0418e13afb8bd24f35cEtan Cohen        pw.println("WifiAwareRttStateManager:");
2017335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen        pw.println("  mPendingOperations: [" + mPendingOperations + "]");
2027335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen    }
2037335b7c3db2656c8379296593c7880ae56ccf9eaEtan Cohen}
204