1 /* 2 * Copyright (C) 2016 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.android.test.util.wifistrengthscanner; 18 19 import android.app.Activity; 20 import android.app.Instrumentation; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.net.wifi.ScanResult; 26 import android.net.wifi.WifiInfo; 27 import android.net.wifi.WifiManager; 28 import android.os.Bundle; 29 import android.os.Environment; 30 import android.os.ParcelFileDescriptor; 31 import android.util.Log; 32 33 import java.io.FileInputStream; 34 import java.io.IOException; 35 import java.util.ArrayList; 36 import java.util.List; 37 import java.util.concurrent.CountDownLatch; 38 import java.util.concurrent.TimeUnit; 39 40 public class WifiStrengthScannerInstrumentation extends Instrumentation { 41 private static final String TAG = WifiStrengthScannerInstrumentation.class.getCanonicalName(); 42 private final static String SD_CARD_PATH = 43 Environment.getExternalStorageDirectory().getAbsolutePath() + "/"; 44 private final int NUMBER_OF_WIFI_LEVELS = 101; 45 private final int INVALID_RSSI = -127; 46 private Bundle mArguments; 47 private CountDownLatch mLatch; 48 private boolean scanReceived; 49 50 @Override onCreate(Bundle arguments)51 public void onCreate(Bundle arguments) { 52 super.onCreate(arguments); 53 mArguments = arguments; 54 start(); 55 } 56 57 @Override onStart()58 public void onStart() { 59 super.onStart(); 60 try { 61 mLatch = new CountDownLatch(1); 62 getContext().registerReceiver(new WifiScanReceiver(), 63 new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); 64 WifiManager wifiManager = 65 (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); 66 scanReceived = false; 67 wifiManager.startScan(); 68 mLatch.await(10000, TimeUnit.MILLISECONDS); 69 70 if (!scanReceived) { 71 sendFailureStatus("no_scan_received"); 72 finish(Activity.RESULT_CANCELED, new Bundle()); 73 return; 74 } 75 76 WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 77 Bundle bundle = new Bundle(); 78 bundle.putString("suplicant_state", wifiInfo.getSupplicantState().name()); 79 80 String bssid = wifiInfo.getBSSID(); 81 bundle.putString("bssid", bssid); 82 // zero counts as a level, so the max level is one less that the number of levels. 83 bundle.putInt("wifi_max_level", NUMBER_OF_WIFI_LEVELS - 1); 84 85 bundle.putInt("wifi_info_wifi_level", 86 WifiManager.calculateSignalLevel(wifiInfo.getRssi(), NUMBER_OF_WIFI_LEVELS)); 87 bundle.putInt("wifi_info_rssi", wifiInfo.getRssi()); 88 bundle.putInt("wifi_info_frequency", wifiInfo.getFrequency()); 89 90 ScanResult result = getScanResult(wifiManager, bssid); 91 if (result != null) { 92 bundle.putInt("scan_result_wifi_level", wifiManager.calculateSignalLevel(result 93 .level, NUMBER_OF_WIFI_LEVELS)); 94 bundle.putInt("scan_result_rssi", result.level); 95 bundle.putInt("scan_result_frequency", result.frequency); 96 } 97 98 int dumpsysRssi = getRssiFromDumpsys(bssid); 99 bundle.putInt("dumpsys_rssi", dumpsysRssi); 100 bundle.putInt("dumpsys_wifi_level", 101 WifiManager.calculateSignalLevel(dumpsysRssi, NUMBER_OF_WIFI_LEVELS)); 102 sendStatus(Activity.RESULT_OK, bundle); 103 finish(Activity.RESULT_OK, new Bundle()); 104 } catch (IOException e) { 105 Log.e(TAG, Log.getStackTraceString(e)); 106 sendFailureStatus("io_exception"); 107 finish(Activity.RESULT_CANCELED, new Bundle()); 108 } catch (InterruptedException e) { 109 Log.e(TAG, Log.getStackTraceString(e)); 110 sendFailureStatus("interrupted_exception"); 111 finish(Activity.RESULT_CANCELED, new Bundle()); 112 } 113 } 114 getScanResult(WifiManager wifiManager, String bssid)115 private ScanResult getScanResult(WifiManager wifiManager, String bssid) { 116 List<ScanResult> scanResults = wifiManager.getScanResults(); 117 for (ScanResult scanResult : scanResults) { 118 if (scanResult.BSSID.equals(bssid)) { 119 return scanResult; 120 } 121 } 122 123 return null; 124 } 125 sendFailureStatus(String update)126 private void sendFailureStatus(String update) { 127 Bundle result = new Bundle(); 128 result.putString("wifi_strength_scanner_failure", update); 129 sendStatus(Activity.RESULT_CANCELED, result); 130 } 131 getRssiFromDumpsys(String bssid)132 private Integer getRssiFromDumpsys(String bssid) throws IOException, InterruptedException { 133 List<String> dumpsysLines = getDumpsysWifiLastScanResults(); 134 135 for (int i = 2; i < dumpsysLines.size(); i++) { 136 String line = dumpsysLines.get(i); 137 if (line != null && line.contains(bssid)) { 138 String[] tokens = line.trim().split("\\s\\s+"); 139 return Integer.parseInt(tokens[2]); 140 } 141 } 142 143 return INVALID_RSSI; 144 } 145 getDumpsysWifiLastScanResults()146 private List<String> getDumpsysWifiLastScanResults() throws IOException, InterruptedException { 147 String dumpsysWifi = executeCommand("dumpsys wifi"); 148 String[] lines = dumpsysWifi.split("\n"); 149 List<String> scanResults = new ArrayList<>(); 150 151 boolean scansStarted = false; 152 for (String line : lines) { 153 if (line.startsWith("Latest scan results:")) { 154 scansStarted = true; 155 } 156 157 if (scansStarted) { 158 if ("".equals(line.trim())) { 159 break; 160 } 161 162 scanResults.add(line); 163 } 164 } 165 166 return scanResults; 167 } 168 executeCommand(String cmd)169 private String executeCommand(String cmd) throws IOException, InterruptedException { 170 StringBuilder result = new StringBuilder(); 171 try { 172 ParcelFileDescriptor pfd = getUiAutomation().executeShellCommand(cmd); 173 byte[] buf = new byte[1024]; 174 int bytesRead; 175 FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); 176 while ((bytesRead = fis.read(buf)) != -1) { 177 result.append(new String(buf, 0, bytesRead)); 178 } 179 fis.close(); 180 } catch (IOException e) { 181 throw new IOException(String.format("Fails to execute command: %s ", cmd), e); 182 } 183 184 return result.toString(); 185 } 186 187 private class WifiScanReceiver extends BroadcastReceiver { 188 @Override onReceive(Context context, Intent intent)189 public void onReceive(Context context, Intent intent) { 190 Log.d(TAG, "scan results received."); 191 scanReceived = true; 192 mLatch.countDown(); 193 } 194 } 195 } 196