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