1 /*
2  * Copyright (C) 2022 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 android.wifi.mockwifi;
18 
19 import android.app.Service;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.os.Binder;
23 import android.os.IBinder;
24 import android.util.Log;
25 import android.wifi.mockwifi.nl80211.IClientInterfaceImp;
26 import android.wifi.mockwifi.nl80211.IWifiScannerImp;
27 import android.wifi.mockwifi.nl80211.WifiNL80211ManagerImp;
28 
29 import java.util.concurrent.CountDownLatch;
30 import java.util.concurrent.TimeUnit;
31 
32 public class MockWifiModemService extends Service {
33 
34     private static final String TAG = "MockWifiModemService";
35     public static final int TEST_TIMEOUT_MS = 30000;
36 
37     public static final int LATCH_MOCK_WIFI_MODEM_SERVICE_READY = 0;
38     public static final int LATCH_WIFI_INTERFACES_READY = 1;
39     public static final int LATCH_MAX = 2;
40 
41     public static final String METHOD_IDENTIFIER = ",";
42     public static final String CLASS_IDENTIFIER = "-";
43     private static final int NUM_MOCKED_INTERFACES = 1; // The number of HAL, now only support
44                                                         // nl80211 HAL
45     public static final String NL80211_INTERFACE_NAME = "android.wifi.mockwifimodem.nl80211";
46 
47     private static CountDownLatch[] sLatches;
48     private Object mLock = new Object();;
49     private static Context sContext;
50     private LocalBinder mBinder;
51 
52     private static WifiNL80211ManagerImp sWifiNL80211ManagerImp;
53 
54     // For local access to this Service.
55     class LocalBinder extends Binder {
getService()56         MockWifiModemService getService() {
57             return MockWifiModemService.this;
58         }
59     }
60 
61     @Override
onCreate()62     public void onCreate() {
63         Log.d(TAG, "Mock Wifi Modem Service Created");
64         sContext = getBaseContext();
65         sLatches = new CountDownLatch[LATCH_MAX];
66         for (int i = 0; i < LATCH_MAX; i++) {
67             if (i == LATCH_WIFI_INTERFACES_READY) {
68                 sLatches[i] = new CountDownLatch(NUM_MOCKED_INTERFACES); // make sure all HAL
69                                                                          // simulation is ready
70             } else {
71                 sLatches[i] = new CountDownLatch(1);
72             }
73         }
74         mBinder = new LocalBinder();
75         sWifiNL80211ManagerImp = new WifiNL80211ManagerImp(sContext);
76     }
77 
78     @Override
onBind(Intent intent)79     public IBinder onBind(Intent intent) {
80         if (NL80211_INTERFACE_NAME.equals(intent.getAction())) {
81             Log.i(TAG, "onBind-NL80211");
82             countDownLatch(LATCH_WIFI_INTERFACES_READY);
83             return sWifiNL80211ManagerImp;
84         }
85         countDownLatch(LATCH_MOCK_WIFI_MODEM_SERVICE_READY);
86         Log.i(TAG, "onBind-Local");
87         return mBinder;
88     }
89 
countDownLatch(int latchIndex)90     public void countDownLatch(int latchIndex) {
91         if (latchIndex < 0 || latchIndex >= sLatches.length) {
92             Log.e(TAG, "invalid latch index: " + latchIndex);
93             return;
94         }
95         synchronized (mLock) {
96             sLatches[latchIndex].countDown();
97         }
98     }
99 
waitForLatchCountdown(int latchIndex)100     public boolean waitForLatchCountdown(int latchIndex) {
101         return waitForLatchCountdown(latchIndex, TEST_TIMEOUT_MS);
102     }
103 
waitForLatchCountdown(int latchIndex, long waitMs)104     public boolean waitForLatchCountdown(int latchIndex, long waitMs) {
105         if (latchIndex < 0 || latchIndex >= sLatches.length) {
106             Log.e(TAG, "invalid latch index: " + latchIndex);
107             return false;
108         }
109         boolean complete = false;
110         try {
111             CountDownLatch latch;
112             synchronized (mLock) {
113                 latch = sLatches[latchIndex];
114             }
115             complete = latch.await(waitMs, TimeUnit.MILLISECONDS);
116         } catch (InterruptedException e) {
117         }
118         synchronized (mLock) {
119             sLatches[latchIndex] = new CountDownLatch(1);
120         }
121         return complete;
122     }
123 
124     /**
125      * Configures a mock client interface.
126      */
configureClientInterfaceMock(String ifaceName, IClientInterfaceImp.ClientInterfaceMock clientInterfaceMock)127     public boolean configureClientInterfaceMock(String ifaceName,
128             IClientInterfaceImp.ClientInterfaceMock clientInterfaceMock) {
129         if (sWifiNL80211ManagerImp == null) {
130             return false;
131         }
132         return sWifiNL80211ManagerImp.configureClientInterfaceMock(ifaceName, clientInterfaceMock);
133     }
134 
135     /**
136      * Configures a mock Wifi scanner interface.
137      */
configureWifiScannerInterfaceMock(String ifaceName, IWifiScannerImp.WifiScannerInterfaceMock wifiScannerInterfaceMock)138     public boolean configureWifiScannerInterfaceMock(String ifaceName,
139             IWifiScannerImp.WifiScannerInterfaceMock wifiScannerInterfaceMock) {
140         if (sWifiNL80211ManagerImp == null) {
141             return false;
142         }
143         return sWifiNL80211ManagerImp.configureWifiScannerInterfaceMock(ifaceName,
144                 wifiScannerInterfaceMock);
145     }
146 
147     /**
148      * Gets all configured methods from all mocked HALs.
149      */
getAllConfiguredMethods()150     public String getAllConfiguredMethods() {
151         // Get configured methods from all mocked HALs. (Now only supports WifiNL80211ManagerImp).
152         return sWifiNL80211ManagerImp.getConfiguredMethods();
153     }
154 
getWifiNL80211ManagerImp()155     public WifiNL80211ManagerImp getWifiNL80211ManagerImp() {
156         return sWifiNL80211ManagerImp;
157     }
158 }
159