blob: aecf9aea5b6a9376835d06a20dc42b3d464cff2b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
Irfan Sheriffa2a1b912010-06-07 09:03:04 -07002 * Copyright (C) 2010 The Android Open Source Project
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003 *
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
Irfan Sheriffd017f352013-02-20 13:30:44 -080017package com.android.server.wifi;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Irfan Sheriff330b1872012-09-16 12:27:57 -070019import android.app.ActivityManager;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -080020import android.app.AppOpsManager;
Jaikumar Ganesh7440fc22010-09-27 17:04:14 -070021import android.bluetooth.BluetoothAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.Context;
24import android.content.Intent;
25import android.content.IntentFilter;
26import android.content.pm.PackageManager;
Irfan Sheriff11aefad2013-03-06 07:57:41 -080027import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.net.DhcpInfo;
Robert Greenwalt4717c262012-10-31 14:32:53 -070029import android.net.DhcpResults;
30import android.net.LinkAddress;
Robert Greenwalt4717c262012-10-31 14:32:53 -070031import android.net.NetworkUtils;
32import android.net.RouteInfo;
Robert Greenwalt0451d592013-08-01 18:24:13 -070033import android.net.wifi.IWifiManager;
34import android.net.wifi.ScanResult;
35import android.net.wifi.BatchedScanResult;
36import android.net.wifi.BatchedScanSettings;
37import android.net.wifi.WifiConfiguration;
Jason Monk1aeaf842013-10-21 12:43:53 -040038import android.net.wifi.WifiConfiguration.ProxySettings;
Robert Greenwalt0451d592013-08-01 18:24:13 -070039import android.net.wifi.WifiInfo;
40import android.net.wifi.WifiManager;
41import android.net.wifi.WifiStateMachine;
42import android.net.wifi.WifiWatchdogStateMachine;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.os.Binder;
Irfan Sheriff0d255342010-07-28 09:35:20 -070044import android.os.Handler;
Irfan Sheriff227bec42011-02-15 19:30:27 -080045import android.os.Messenger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.os.HandlerThread;
47import android.os.IBinder;
Irfan Sheriff5321aef2010-02-12 12:35:59 -080048import android.os.INetworkManagementService;
Irfan Sheriff0d255342010-07-28 09:35:20 -070049import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.os.RemoteException;
Irfan Sheriff227bec42011-02-15 19:30:27 -080051import android.os.SystemProperties;
Irfan Sheriff330b1872012-09-16 12:27:57 -070052import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070053import android.os.WorkSource;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070054import android.os.AsyncTask;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.provider.Settings;
Nick Pelly6ccaa542012-06-15 15:22:47 -070056import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080057import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070059import java.io.FileNotFoundException;
60import java.io.BufferedReader;
Irfan Sherifff0afe412012-11-30 14:07:44 -080061import java.io.FileDescriptor;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070062import java.io.FileReader;
63import java.io.IOException;
Irfan Sherifff0afe412012-11-30 14:07:44 -080064import java.io.PrintWriter;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070065
Robert Greenwalt4717c262012-10-31 14:32:53 -070066import java.net.InetAddress;
67import java.net.Inet4Address;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import java.util.ArrayList;
Robert Greenwalt0451d592013-08-01 18:24:13 -070069import java.util.HashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import java.util.List;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070071
Irfan Sheriff07a22952013-03-27 13:27:39 -070072import java.util.concurrent.atomic.AtomicBoolean;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073
Irfan Sheriff11aefad2013-03-06 07:57:41 -080074import com.android.internal.R;
The Android Open Source Project10592532009-03-18 17:39:46 -070075import com.android.internal.app.IBatteryStats;
Irfan Sheriff616f3172011-09-11 19:59:01 -070076import com.android.internal.telephony.TelephonyIntents;
Wink Saville4b7ba092010-10-20 15:37:41 -070077import com.android.internal.util.AsyncChannel;
The Android Open Source Project10592532009-03-18 17:39:46 -070078import com.android.server.am.BatteryStatsService;
Irfan Sheriff11aefad2013-03-06 07:57:41 -080079import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED;
80import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED;
81import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED;
82import static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED;
83import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED;
84import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF;
85import static com.android.server.wifi.WifiController.CMD_SCREEN_ON;
86import static com.android.server.wifi.WifiController.CMD_SET_AP;
Vinit Deshapndea3038b22013-10-02 17:26:05 -070087import static com.android.server.wifi.WifiController.CMD_USER_PRESENT;
Irfan Sheriff11aefad2013-03-06 07:57:41 -080088import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089/**
90 * WifiService handles remote WiFi operation requests by implementing
Irfan Sheriffa2a1b912010-06-07 09:03:04 -070091 * the IWifiManager interface.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 *
93 * @hide
94 */
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080095public final class WifiService extends IWifiManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 private static final String TAG = "WifiService";
Dianne Hackborn5fd21692011-06-07 14:09:47 -070097 private static final boolean DBG = false;
Irfan Sheriffa2a1b912010-06-07 09:03:04 -070098
Irfan Sheriff11aefad2013-03-06 07:57:41 -080099 final WifiStateMachine mWifiStateMachine;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800101 private final Context mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800103 final LockList mLocks = new LockList();
Eric Shienbrood5711fad2009-03-27 20:25:31 -0700104 // some wifi lock statistics
Irfan Sheriff5876a422010-08-12 20:26:23 -0700105 private int mFullHighPerfLocksAcquired;
106 private int mFullHighPerfLocksReleased;
Eric Shienbrood5711fad2009-03-27 20:25:31 -0700107 private int mFullLocksAcquired;
108 private int mFullLocksReleased;
109 private int mScanLocksAcquired;
110 private int mScanLocksReleased;
The Android Open Source Project10592532009-03-18 17:39:46 -0700111
Robert Greenwalt58ff0212009-05-19 15:53:54 -0700112 private final List<Multicaster> mMulticasters =
113 new ArrayList<Multicaster>();
Robert Greenwalt5347bd42009-05-13 15:10:16 -0700114 private int mMulticastEnabled;
115 private int mMulticastDisabled;
116
The Android Open Source Project10592532009-03-18 17:39:46 -0700117 private final IBatteryStats mBatteryStats;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800118 private final AppOpsManager mAppOps;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800119
Irfan Sheriff227bec42011-02-15 19:30:27 -0800120 private String mInterfaceName;
121
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800122 /* Tracks the open wi-fi network notification */
123 private WifiNotificationController mNotificationController;
124 /* Polls traffic stats and notifies clients */
125 private WifiTrafficPoller mTrafficPoller;
126 /* Tracks the persisted states for wi-fi & airplane mode */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800127 final WifiSettingsStore mSettingsStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128
Robert Greenwalt0451d592013-08-01 18:24:13 -0700129 final boolean mBatchedScanSupported;
130
Dianne Hackborn03f3cb02010-09-17 23:12:26 -0700131 /**
Wink Saville4b7ba092010-10-20 15:37:41 -0700132 * Asynchronous channel to WifiStateMachine
133 */
Irfan Sheriff227bec42011-02-15 19:30:27 -0800134 private AsyncChannel mWifiStateMachineChannel;
Wink Saville4b7ba092010-10-20 15:37:41 -0700135
136 /**
Irfan Sheriff227bec42011-02-15 19:30:27 -0800137 * Handles client connections
138 */
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800139 private class ClientHandler extends Handler {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800140
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800141 ClientHandler(android.os.Looper looper) {
Wink Saville4b7ba092010-10-20 15:37:41 -0700142 super(looper);
Wink Saville4b7ba092010-10-20 15:37:41 -0700143 }
144
145 @Override
146 public void handleMessage(Message msg) {
147 switch (msg.what) {
148 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
149 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
Irfan Sheriff6bfc8882012-08-29 15:35:57 -0700150 if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
Irfan Sheriff302b06d2013-02-22 12:35:31 -0800151 // We track the clients by the Messenger
152 // since it is expected to be always available
Irfan Sheriffc808a192013-03-05 09:46:36 -0800153 mTrafficPoller.addClient(msg.replyTo);
Wink Saville4b7ba092010-10-20 15:37:41 -0700154 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800155 Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
156 }
157 break;
158 }
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800159 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
160 if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
Irfan Sheriff6bfc8882012-08-29 15:35:57 -0700161 if (DBG) Slog.d(TAG, "Send failed, client connection lost");
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800162 } else {
Irfan Sheriff6bfc8882012-08-29 15:35:57 -0700163 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800164 }
Irfan Sheriffc808a192013-03-05 09:46:36 -0800165 mTrafficPoller.removeClient(msg.replyTo);
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800166 break;
167 }
Irfan Sheriff227bec42011-02-15 19:30:27 -0800168 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
169 AsyncChannel ac = new AsyncChannel();
170 ac.connect(mContext, this, msg.replyTo);
171 break;
172 }
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800173 /* Client commands are forwarded to state machine */
174 case WifiManager.CONNECT_NETWORK:
Vinit Deshapnde10652a92013-09-09 16:24:36 -0700175 case WifiManager.SAVE_NETWORK: {
176 WifiConfiguration config = (WifiConfiguration) msg.obj;
Vinit Deshapndeffec3322013-09-16 12:41:12 -0700177 int networkId = msg.arg1;
178 if (config != null && config.isValid()) {
Jason Monk1aeaf842013-10-21 12:43:53 -0400179 // This is restricted because there is no UI for the user to
180 // monitor/control PAC.
181 if (config.proxySettings != ProxySettings.PAC) {
182 if (DBG) Slog.d(TAG, "Connect with config" + config);
183 mWifiStateMachine.sendMessage(Message.obtain(msg));
184 } else {
185 Slog.e(TAG, "ClientHandler.handleMessage cannot process msg with PAC");
186 if (msg.what == WifiManager.CONNECT_NETWORK) {
187 replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
188 } else {
189 replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
190 }
191 }
Vinit Deshapndeffec3322013-09-16 12:41:12 -0700192 } else if (config == null
193 && networkId != WifiConfiguration.INVALID_NETWORK_ID) {
194 if (DBG) Slog.d(TAG, "Connect with networkId" + networkId);
Vinit Deshapnde10652a92013-09-09 16:24:36 -0700195 mWifiStateMachine.sendMessage(Message.obtain(msg));
196 } else {
Vinit Deshapndeffec3322013-09-16 12:41:12 -0700197 Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg);
Vinit Deshapnde10652a92013-09-09 16:24:36 -0700198 if (msg.what == WifiManager.CONNECT_NETWORK) {
199 replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
200 } else {
201 replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
202 }
203 }
204 break;
205 }
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800206 case WifiManager.FORGET_NETWORK:
207 case WifiManager.START_WPS:
208 case WifiManager.CANCEL_WPS:
209 case WifiManager.DISABLE_NETWORK:
Yuhao Zhengf6307822012-08-14 14:21:25 -0700210 case WifiManager.RSSI_PKTCNT_FETCH: {
211 mWifiStateMachine.sendMessage(Message.obtain(msg));
212 break;
213 }
Wink Saville4b7ba092010-10-20 15:37:41 -0700214 default: {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800215 Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg);
Wink Saville4b7ba092010-10-20 15:37:41 -0700216 break;
217 }
218 }
219 }
Vinit Deshapnde10652a92013-09-09 16:24:36 -0700220
221 private void replyFailed(Message msg, int what) {
222 Message reply = msg.obtain();
223 reply.what = what;
224 reply.arg1 = WifiManager.INVALID_ARGS;
225 try {
226 msg.replyTo.send(reply);
227 } catch (RemoteException e) {
228 // There's not much we can do if reply can't be sent!
229 }
230 }
Wink Saville4b7ba092010-10-20 15:37:41 -0700231 }
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800232 private ClientHandler mClientHandler;
Irfan Sheriff227bec42011-02-15 19:30:27 -0800233
234 /**
235 * Handles interaction with WifiStateMachine
236 */
237 private class WifiStateMachineHandler extends Handler {
238 private AsyncChannel mWsmChannel;
239
240 WifiStateMachineHandler(android.os.Looper looper) {
241 super(looper);
242 mWsmChannel = new AsyncChannel();
243 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
244 }
245
246 @Override
247 public void handleMessage(Message msg) {
248 switch (msg.what) {
249 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
250 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
251 mWifiStateMachineChannel = mWsmChannel;
252 } else {
253 Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1);
254 mWifiStateMachineChannel = null;
255 }
256 break;
257 }
Irfan Sheriff6da83d52011-06-06 12:54:06 -0700258 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
259 Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1);
260 mWifiStateMachineChannel = null;
261 //Re-establish connection to state machine
262 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
263 break;
264 }
Irfan Sheriff227bec42011-02-15 19:30:27 -0800265 default: {
266 Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg);
267 break;
268 }
269 }
270 }
271 }
272 WifiStateMachineHandler mWifiStateMachineHandler;
Wink Saville4b7ba092010-10-20 15:37:41 -0700273
Isaac Levy654f5092011-07-13 17:41:45 -0700274 private WifiWatchdogStateMachine mWifiWatchdogStateMachine;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700275
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800276 public WifiService(Context context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 mContext = context;
Irfan Sheriff227bec42011-02-15 19:30:27 -0800278
279 mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
280
281 mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700282 mWifiStateMachine.enableRssiPolling(true);
The Android Open Source Project10592532009-03-18 17:39:46 -0700283 mBatteryStats = BatteryStatsService.getService();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800284 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800285
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800286 mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
Irfan Sheriffc808a192013-03-05 09:46:36 -0800287 mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800288 mSettingsStore = new WifiSettingsStore(mContext);
289
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800290 HandlerThread wifiThread = new HandlerThread("WifiService");
291 wifiThread.start();
292 mClientHandler = new ClientHandler(wifiThread.getLooper());
293 mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
294 mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
295 mWifiController.start();
296
Robert Greenwalt0451d592013-08-01 18:24:13 -0700297 mBatchedScanSupported = mContext.getResources().getBoolean(
298 R.bool.config_wifi_batched_scan_supported);
299
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800300 registerForScanModeChange();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 mContext.registerReceiver(
302 new BroadcastReceiver() {
303 @Override
304 public void onReceive(Context context, Intent intent) {
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800305 if (mSettingsStore.handleAirplaneModeToggled()) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800306 mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 }
309 },
310 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
311
Irfan Sheriffe68d8582013-04-23 13:43:43 -0700312 // Adding optimizations of only receiving broadcasts when wifi is enabled
313 // can result in race conditions when apps toggle wifi in the background
314 // without active user involvement. Always receive broadcasts.
315 registerForBroadcasts();
Irfan Sheriff7b009782010-03-11 16:37:45 -0800316 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800317
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800318 private WifiController mWifiController;
319
Irfan Sheriff7b009782010-03-11 16:37:45 -0800320 /**
321 * Check if Wi-Fi needs to be enabled and start
322 * if needed
Irfan Sheriff60e3ba02010-04-02 12:18:45 -0700323 *
324 * This function is used only at boot time
Irfan Sheriff7b009782010-03-11 16:37:45 -0800325 */
Irfan Sheriff0d255342010-07-28 09:35:20 -0700326 public void checkAndStartWifi() {
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800327 /* Check if wi-fi needs to be enabled */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800328 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
Irfan Sheriff7b009782010-03-11 16:37:45 -0800329 Slog.i(TAG, "WifiService starting up with Wi-Fi " +
330 (wifiEnabled ? "enabled" : "disabled"));
Irfan Sherifff03d6202012-05-17 12:33:46 -0700331
332 // If we are already disabled (could be due to airplane mode), avoid changing persist
333 // state here
334 if (wifiEnabled) setWifiEnabled(wifiEnabled);
Isaac Levybc7dfb52011-06-06 15:34:01 -0700335
Isaac Levy654f5092011-07-13 17:41:45 -0700336 mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
337 makeWifiWatchdogStateMachine(mContext);
338
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800339 }
340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 /**
342 * see {@link android.net.wifi.WifiManager#pingSupplicant()}
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700343 * @return {@code true} if the operation succeeds, {@code false} otherwise
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 */
345 public boolean pingSupplicant() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700346 enforceAccessPermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800347 if (mWifiStateMachineChannel != null) {
348 return mWifiStateMachine.syncPingSupplicant(mWifiStateMachineChannel);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700349 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800350 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700351 return false;
352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 }
354
355 /**
356 * see {@link android.net.wifi.WifiManager#startScan()}
David Christie6942a122013-07-25 15:25:07 -0700357 *
358 * <p>If workSource is null, all blame is given to the calling uid.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 */
David Christie6942a122013-07-25 15:25:07 -0700360 public void startScan(WorkSource workSource) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 enforceChangePermission();
David Christie6942a122013-07-25 15:25:07 -0700362 if (workSource != null) {
363 enforceWorkSourcePermission();
David Christie6ab22842013-09-13 17:11:53 -0700364 // WifiManager currently doesn't use names, so need to clear names out of the
365 // supplied WorkSource to allow future WorkSource combining.
366 workSource.clearNames();
David Christie6942a122013-07-25 15:25:07 -0700367 }
368 mWifiStateMachine.startScan(Binder.getCallingUid(), workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 }
370
Robert Greenwalt0451d592013-08-01 18:24:13 -0700371 private class BatchedScanRequest extends DeathRecipient {
Robert Greenwalta029ea12013-09-25 16:38:12 -0700372 final BatchedScanSettings settings;
373 final int uid;
374 final int pid;
375 final WorkSource workSource;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700376
Robert Greenwalta029ea12013-09-25 16:38:12 -0700377 BatchedScanRequest(BatchedScanSettings settings, IBinder binder, WorkSource ws) {
Robert Greenwalt0451d592013-08-01 18:24:13 -0700378 super(0, null, binder, null);
379 this.settings = settings;
Robert Greenwalt126755c2013-09-05 18:32:12 -0700380 this.uid = getCallingUid();
381 this.pid = getCallingPid();
Robert Greenwalta029ea12013-09-25 16:38:12 -0700382 workSource = ws;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700383 }
384 public void binderDied() {
Robert Greenwalt82f42182013-09-19 17:27:43 -0700385 stopBatchedScan(settings, uid, pid);
Robert Greenwalt0451d592013-08-01 18:24:13 -0700386 }
387 public String toString() {
388 return "BatchedScanRequest{settings=" + settings + ", binder=" + mBinder + "}";
389 }
Robert Greenwalt126755c2013-09-05 18:32:12 -0700390
Robert Greenwalt82f42182013-09-19 17:27:43 -0700391 public boolean isSameApp(int uid, int pid) {
392 return (this.uid == uid && this.pid == pid);
Robert Greenwalt126755c2013-09-05 18:32:12 -0700393 }
Robert Greenwalt0451d592013-08-01 18:24:13 -0700394 }
395
396 private final List<BatchedScanRequest> mBatchedScanners = new ArrayList<BatchedScanRequest>();
397
398 public boolean isBatchedScanSupported() {
399 return mBatchedScanSupported;
400 }
401
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700402 public void pollBatchedScan() {
403 enforceChangePermission();
404 if (mBatchedScanSupported == false) return;
405 mWifiStateMachine.requestBatchedScanPoll();
406 }
407
Robert Greenwalt0451d592013-08-01 18:24:13 -0700408 /**
409 * see {@link android.net.wifi.WifiManager#requestBatchedScan()}
410 */
Robert Greenwalta029ea12013-09-25 16:38:12 -0700411 public boolean requestBatchedScan(BatchedScanSettings requested, IBinder binder,
412 WorkSource workSource) {
Robert Greenwalt0451d592013-08-01 18:24:13 -0700413 enforceChangePermission();
Robert Greenwalta029ea12013-09-25 16:38:12 -0700414 if (workSource != null) {
415 enforceWorkSourcePermission();
416 // WifiManager currently doesn't use names, so need to clear names out of the
417 // supplied WorkSource to allow future WorkSource combining.
418 workSource.clearNames();
419 }
Robert Greenwalt0451d592013-08-01 18:24:13 -0700420 if (mBatchedScanSupported == false) return false;
421 requested = new BatchedScanSettings(requested);
422 if (requested.isInvalid()) return false;
Robert Greenwalta029ea12013-09-25 16:38:12 -0700423 BatchedScanRequest r = new BatchedScanRequest(requested, binder, workSource);
Robert Greenwalt0451d592013-08-01 18:24:13 -0700424 synchronized(mBatchedScanners) {
425 mBatchedScanners.add(r);
426 resolveBatchedScannersLocked();
427 }
428 return true;
429 }
430
431 public List<BatchedScanResult> getBatchedScanResults(String callingPackage) {
432 enforceAccessPermission();
433 if (mBatchedScanSupported == false) return new ArrayList<BatchedScanResult>();
434 int userId = UserHandle.getCallingUserId();
435 int uid = Binder.getCallingUid();
436 long ident = Binder.clearCallingIdentity();
437 try {
438 if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
439 != AppOpsManager.MODE_ALLOWED) {
440 return new ArrayList<BatchedScanResult>();
441 }
442 int currentUser = ActivityManager.getCurrentUser();
443 if (userId != currentUser) {
444 return new ArrayList<BatchedScanResult>();
445 } else {
446 return mWifiStateMachine.syncGetBatchedScanResultsList();
447 }
448 } finally {
449 Binder.restoreCallingIdentity(ident);
450 }
451 }
452
453
Robert Greenwalt82f42182013-09-19 17:27:43 -0700454 public void stopBatchedScan(BatchedScanSettings settings) {
Robert Greenwalt0451d592013-08-01 18:24:13 -0700455 enforceChangePermission();
456 if (mBatchedScanSupported == false) return;
Robert Greenwalt82f42182013-09-19 17:27:43 -0700457 stopBatchedScan(settings, getCallingUid(), getCallingPid());
458 }
459
460 private void stopBatchedScan(BatchedScanSettings settings, int uid, int pid) {
Robert Greenwalt126755c2013-09-05 18:32:12 -0700461 ArrayList<BatchedScanRequest> found = new ArrayList<BatchedScanRequest>();
Robert Greenwalt0451d592013-08-01 18:24:13 -0700462 synchronized(mBatchedScanners) {
Robert Greenwalt0451d592013-08-01 18:24:13 -0700463 for (BatchedScanRequest r : mBatchedScanners) {
Robert Greenwalt82f42182013-09-19 17:27:43 -0700464 if (r.isSameApp(uid, pid) && (settings == null || settings.equals(r.settings))) {
Robert Greenwalt126755c2013-09-05 18:32:12 -0700465 found.add(r);
466 if (settings != null) break;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700467 }
468 }
Robert Greenwalt126755c2013-09-05 18:32:12 -0700469 for (BatchedScanRequest r : found) {
470 mBatchedScanners.remove(r);
471 }
472 if (found.size() != 0) {
Robert Greenwalt0451d592013-08-01 18:24:13 -0700473 resolveBatchedScannersLocked();
474 }
475 }
476 }
477
478 private void resolveBatchedScannersLocked() {
479 BatchedScanSettings setting = new BatchedScanSettings();
Robert Greenwalta029ea12013-09-25 16:38:12 -0700480 WorkSource responsibleWorkSource = null;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700481 int responsibleUid = 0;
Robert Greenwalta029ea12013-09-25 16:38:12 -0700482 double responsibleCsph = 0; // Channel Scans Per Hour
Robert Greenwalt0451d592013-08-01 18:24:13 -0700483
484 if (mBatchedScanners.size() == 0) {
Robert Greenwalta029ea12013-09-25 16:38:12 -0700485 mWifiStateMachine.setBatchedScanSettings(null, 0, 0, null);
Robert Greenwalt0451d592013-08-01 18:24:13 -0700486 return;
487 }
Robert Greenwalt0451d592013-08-01 18:24:13 -0700488 for (BatchedScanRequest r : mBatchedScanners) {
489 BatchedScanSettings s = r.settings;
Robert Greenwalta029ea12013-09-25 16:38:12 -0700490
491 // evaluate responsibility
492 int currentChannelCount;
493 int currentScanInterval;
494 double currentCsph;
495
496 if (s.channelSet == null || s.channelSet.isEmpty()) {
497 // all channels - 11 B and 9 A channels roughly.
498 currentChannelCount = 9 + 11;
499 } else {
500 currentChannelCount = s.channelSet.size();
501 // these are rough est - no real need to correct for reg-domain;
502 if (s.channelSet.contains("A")) currentChannelCount += (9 - 1);
503 if (s.channelSet.contains("B")) currentChannelCount += (11 - 1);
504
505 }
506 if (s.scanIntervalSec == BatchedScanSettings.UNSPECIFIED) {
507 currentScanInterval = BatchedScanSettings.DEFAULT_INTERVAL_SEC;
508 } else {
509 currentScanInterval = s.scanIntervalSec;
510 }
511 currentCsph = 60 * 60 * currentChannelCount / currentScanInterval;
512
513 if (currentCsph > responsibleCsph) {
514 responsibleUid = r.uid;
515 responsibleWorkSource = r.workSource;
516 responsibleCsph = currentCsph;
517 }
518
Robert Greenwalt0451d592013-08-01 18:24:13 -0700519 if (s.maxScansPerBatch != BatchedScanSettings.UNSPECIFIED &&
520 s.maxScansPerBatch < setting.maxScansPerBatch) {
521 setting.maxScansPerBatch = s.maxScansPerBatch;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700522 }
523 if (s.maxApPerScan != BatchedScanSettings.UNSPECIFIED &&
Robert Greenwalt82f42182013-09-19 17:27:43 -0700524 (setting.maxApPerScan == BatchedScanSettings.UNSPECIFIED ||
Robert Greenwalt13820af2013-09-20 15:13:08 -0700525 s.maxApPerScan > setting.maxApPerScan)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -0700526 setting.maxApPerScan = s.maxApPerScan;
527 }
528 if (s.scanIntervalSec != BatchedScanSettings.UNSPECIFIED &&
529 s.scanIntervalSec < setting.scanIntervalSec) {
530 setting.scanIntervalSec = s.scanIntervalSec;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700531 }
532 if (s.maxApForDistance != BatchedScanSettings.UNSPECIFIED &&
Robert Greenwalt13820af2013-09-20 15:13:08 -0700533 (setting.maxApForDistance == BatchedScanSettings.UNSPECIFIED ||
534 s.maxApForDistance > setting.maxApForDistance)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -0700535 setting.maxApForDistance = s.maxApForDistance;
536 }
Robert Greenwalt13820af2013-09-20 15:13:08 -0700537 if (s.channelSet != null && s.channelSet.size() != 0) {
538 if (setting.channelSet == null || setting.channelSet.size() != 0) {
539 if (setting.channelSet == null) setting.channelSet = new ArrayList<String>();
540 for (String i : s.channelSet) {
541 if (setting.channelSet.contains(i) == false) setting.channelSet.add(i);
542 }
543 } // else, ignore the constraint - we already use all channels
544 } else {
545 if (setting.channelSet == null || setting.channelSet.size() != 0) {
546 setting.channelSet = new ArrayList<String>();
Robert Greenwalt0451d592013-08-01 18:24:13 -0700547 }
548 }
549 }
Robert Greenwalt13820af2013-09-20 15:13:08 -0700550
551 setting.constrain();
Robert Greenwalta029ea12013-09-25 16:38:12 -0700552 mWifiStateMachine.setBatchedScanSettings(setting, responsibleUid, (int)responsibleCsph,
553 responsibleWorkSource);
Robert Greenwalt0451d592013-08-01 18:24:13 -0700554 }
555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 private void enforceAccessPermission() {
557 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
558 "WifiService");
559 }
560
561 private void enforceChangePermission() {
562 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
563 "WifiService");
564
565 }
566
David Christie6942a122013-07-25 15:25:07 -0700567 private void enforceWorkSourcePermission() {
568 mContext.enforceCallingPermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
569 "WifiService");
570
571 }
572
Robert Greenwaltfc1b15c2009-05-22 15:09:51 -0700573 private void enforceMulticastChangePermission() {
574 mContext.enforceCallingOrSelfPermission(
575 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
576 "WifiService");
577 }
578
Irfan Sheriffda6da092012-08-16 12:49:23 -0700579 private void enforceConnectivityInternalPermission() {
580 mContext.enforceCallingOrSelfPermission(
581 android.Manifest.permission.CONNECTIVITY_INTERNAL,
582 "ConnectivityService");
583 }
584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 /**
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700586 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
587 * @param enable {@code true} to enable, {@code false} to disable.
588 * @return {@code true} if the enable/disable operation was
589 * started or is already in the queue.
590 */
591 public synchronized boolean setWifiEnabled(boolean enable) {
592 enforceChangePermission();
Irfan Sheriffbd21b782012-05-16 13:13:54 -0700593 Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
594 + ", uid=" + Binder.getCallingUid());
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700595 if (DBG) {
Irfan Sheriff0d255342010-07-28 09:35:20 -0700596 Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700597 }
598
Irfan Sheriff61180692010-08-18 16:07:39 -0700599 /*
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800600 * Caller might not have WRITE_SECURE_SETTINGS,
601 * only CHANGE_WIFI_STATE is enforced
602 */
Irfan Sheriff5401f0b2011-12-07 16:27:49 -0800603
Irfan Sherifff03d6202012-05-17 12:33:46 -0700604 long ident = Binder.clearCallingIdentity();
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700605 try {
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800606 if (! mSettingsStore.handleWifiToggled(enable)) {
607 // Nothing to do if wifi cannot be toggled
608 return true;
609 }
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700610 } finally {
611 Binder.restoreCallingIdentity(ident);
612 }
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700613
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800614 mWifiController.sendMessage(CMD_WIFI_TOGGLED);
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700615 return true;
616 }
617
618 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 * see {@link WifiManager#getWifiState()}
620 * @return One of {@link WifiManager#WIFI_STATE_DISABLED},
621 * {@link WifiManager#WIFI_STATE_DISABLING},
622 * {@link WifiManager#WIFI_STATE_ENABLED},
623 * {@link WifiManager#WIFI_STATE_ENABLING},
624 * {@link WifiManager#WIFI_STATE_UNKNOWN}
625 */
626 public int getWifiEnabledState() {
627 enforceAccessPermission();
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700628 return mWifiStateMachine.syncGetWifiState();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 }
630
631 /**
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700632 * see {@link android.net.wifi.WifiManager#setWifiApEnabled(WifiConfiguration, boolean)}
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800633 * @param wifiConfig SSID, security and channel details as
634 * part of WifiConfiguration
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700635 * @param enabled true to enable and false to disable
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800636 */
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700637 public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800638 enforceChangePermission();
Yuhao Zheng8c461c62013-09-16 12:43:00 -0700639 // null wifiConfig is a meaningful input for CMD_SET_AP
640 if (wifiConfig == null || wifiConfig.isValid()) {
Vinit Deshapnde10652a92013-09-09 16:24:36 -0700641 mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig).sendToTarget();
642 } else {
643 Slog.e(TAG, "Invalid WifiConfiguration");
644 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800645 }
646
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700647 /**
648 * see {@link WifiManager#getWifiApState()}
649 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED},
650 * {@link WifiManager#WIFI_AP_STATE_DISABLING},
651 * {@link WifiManager#WIFI_AP_STATE_ENABLED},
652 * {@link WifiManager#WIFI_AP_STATE_ENABLING},
653 * {@link WifiManager#WIFI_AP_STATE_FAILED}
654 */
655 public int getWifiApEnabledState() {
Irfan Sheriff17b232b2010-06-24 11:32:26 -0700656 enforceAccessPermission();
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700657 return mWifiStateMachine.syncGetWifiApState();
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700658 }
659
660 /**
661 * see {@link WifiManager#getWifiApConfiguration()}
662 * @return soft access point configuration
663 */
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700664 public WifiConfiguration getWifiApConfiguration() {
665 enforceAccessPermission();
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800666 return mWifiStateMachine.syncGetWifiApConfiguration();
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800667 }
668
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700669 /**
670 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)}
671 * @param wifiConfig WifiConfiguration details for soft access point
672 */
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700673 public void setWifiApConfiguration(WifiConfiguration wifiConfig) {
Irfan Sheriff17b232b2010-06-24 11:32:26 -0700674 enforceChangePermission();
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800675 if (wifiConfig == null)
676 return;
Vinit Deshapnde10652a92013-09-09 16:24:36 -0700677 if (wifiConfig.isValid()) {
678 mWifiStateMachine.setWifiApConfiguration(wifiConfig);
679 } else {
680 Slog.e(TAG, "Invalid WifiConfiguration");
681 }
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800682 }
683
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800684 /**
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800685 * @param enable {@code true} to enable, {@code false} to disable.
686 * @return {@code true} if the enable/disable operation was
687 * started or is already in the queue.
688 */
Irfan Sheriff7ea33ea2013-04-19 08:39:53 -0700689 public boolean isScanAlwaysAvailable() {
Irfan Sheriff1ef840c2013-03-12 17:09:27 -0700690 enforceAccessPermission();
691 return mSettingsStore.isScanAlwaysAvailable();
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800692 }
693
694 /**
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700695 * see {@link android.net.wifi.WifiManager#disconnect()}
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800696 */
Irfan Sheriffe4984752010-08-19 11:29:22 -0700697 public void disconnect() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700698 enforceChangePermission();
Irfan Sheriffe4984752010-08-19 11:29:22 -0700699 mWifiStateMachine.disconnectCommand();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800700 }
701
702 /**
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700703 * see {@link android.net.wifi.WifiManager#reconnect()}
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800704 */
Irfan Sheriffe4984752010-08-19 11:29:22 -0700705 public void reconnect() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700706 enforceChangePermission();
Irfan Sheriffe4984752010-08-19 11:29:22 -0700707 mWifiStateMachine.reconnectCommand();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800708 }
709
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700710 /**
711 * see {@link android.net.wifi.WifiManager#reassociate()}
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700712 */
Irfan Sheriffe4984752010-08-19 11:29:22 -0700713 public void reassociate() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700714 enforceChangePermission();
Irfan Sheriffe4984752010-08-19 11:29:22 -0700715 mWifiStateMachine.reassociateCommand();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800716 }
717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 /**
719 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()}
720 * @return the list of configured networks
721 */
722 public List<WifiConfiguration> getConfiguredNetworks() {
723 enforceAccessPermission();
Irfan Sheriffe744cff2011-12-11 09:17:50 -0800724 if (mWifiStateMachineChannel != null) {
725 return mWifiStateMachine.syncGetConfiguredNetworks(mWifiStateMachineChannel);
726 } else {
727 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
728 return null;
729 }
Chung-yih Wanga8d15942009-10-09 11:01:49 +0800730 }
731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 /**
733 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)}
734 * @return the supplicant-assigned identifier for the new or updated
735 * network if the operation succeeds, or {@code -1} if it fails
736 */
Irfan Sheriff7aac5542009-12-22 21:42:17 -0800737 public int addOrUpdateNetwork(WifiConfiguration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 enforceChangePermission();
Jason Monk1aeaf842013-10-21 12:43:53 -0400739 if (config.proxySettings == ProxySettings.PAC) {
740 enforceConnectivityInternalPermission();
741 }
Vinit Deshapnde10652a92013-09-09 16:24:36 -0700742 if (config.isValid()) {
743 if (mWifiStateMachineChannel != null) {
744 return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config);
745 } else {
746 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
747 return -1;
748 }
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700749 } else {
Vinit Deshapnde10652a92013-09-09 16:24:36 -0700750 Slog.e(TAG, "bad network configuration");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700751 return -1;
752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753 }
754
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700755 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 * See {@link android.net.wifi.WifiManager#removeNetwork(int)}
757 * @param netId the integer that identifies the network configuration
758 * to the supplicant
759 * @return {@code true} if the operation succeeded
760 */
761 public boolean removeNetwork(int netId) {
762 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800763 if (mWifiStateMachineChannel != null) {
764 return mWifiStateMachine.syncRemoveNetwork(mWifiStateMachineChannel, netId);
Wink Saville4b7ba092010-10-20 15:37:41 -0700765 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800766 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Wink Saville4b7ba092010-10-20 15:37:41 -0700767 return false;
768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 }
770
771 /**
772 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)}
773 * @param netId the integer that identifies the network configuration
774 * to the supplicant
775 * @param disableOthers if true, disable all other networks.
776 * @return {@code true} if the operation succeeded
777 */
778 public boolean enableNetwork(int netId, boolean disableOthers) {
779 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800780 if (mWifiStateMachineChannel != null) {
781 return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId,
782 disableOthers);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700783 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800784 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700785 return false;
786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 }
788
789 /**
790 * See {@link android.net.wifi.WifiManager#disableNetwork(int)}
791 * @param netId the integer that identifies the network configuration
792 * to the supplicant
793 * @return {@code true} if the operation succeeded
794 */
795 public boolean disableNetwork(int netId) {
796 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800797 if (mWifiStateMachineChannel != null) {
798 return mWifiStateMachine.syncDisableNetwork(mWifiStateMachineChannel, netId);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700799 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800800 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700801 return false;
802 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 }
804
805 /**
806 * See {@link android.net.wifi.WifiManager#getConnectionInfo()}
807 * @return the Wi-Fi information, contained in {@link WifiInfo}.
808 */
809 public WifiInfo getConnectionInfo() {
810 enforceAccessPermission();
811 /*
812 * Make sure we have the latest information, by sending
813 * a status request to the supplicant.
814 */
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700815 return mWifiStateMachine.syncRequestConnectionInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 }
817
818 /**
819 * Return the results of the most recent access point scan, in the form of
820 * a list of {@link ScanResult} objects.
821 * @return the list of results
822 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800823 public List<ScanResult> getScanResults(String callingPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 enforceAccessPermission();
Irfan Sheriffdb831da2012-09-16 17:39:26 -0700825 int userId = UserHandle.getCallingUserId();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800826 int uid = Binder.getCallingUid();
Irfan Sheriffdb831da2012-09-16 17:39:26 -0700827 long ident = Binder.clearCallingIdentity();
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700828 try {
Robert Greenwalt0451d592013-08-01 18:24:13 -0700829 if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
830 != AppOpsManager.MODE_ALLOWED) {
831 return new ArrayList<ScanResult>();
832 }
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700833 int currentUser = ActivityManager.getCurrentUser();
834 if (userId != currentUser) {
835 return new ArrayList<ScanResult>();
836 } else {
837 return mWifiStateMachine.syncGetScanResultsList();
838 }
839 } finally {
840 Binder.restoreCallingIdentity(ident);
Irfan Sheriff330b1872012-09-16 12:27:57 -0700841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 }
843
844 /**
845 * Tell the supplicant to persist the current list of configured networks.
846 * @return {@code true} if the operation succeeded
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700847 *
848 * TODO: deprecate this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 */
850 public boolean saveConfiguration() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700851 boolean result = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800853 if (mWifiStateMachineChannel != null) {
854 return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700855 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800856 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700857 return false;
858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 }
860
861 /**
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700862 * Set the country code
863 * @param countryCode ISO 3166 country code.
Robert Greenwaltb5010cc2009-05-21 15:11:40 -0700864 * @param persist {@code true} if the setting should be remembered.
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700865 *
866 * The persist behavior exists so that wifi can fall back to the last
867 * persisted country code on a restart, when the locale information is
868 * not available from telephony.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 */
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700870 public void setCountryCode(String countryCode, boolean persist) {
871 Slog.i(TAG, "WifiService trying to set country code to " + countryCode +
872 " with persist set to " + persist);
Robert Greenwaltfcbced32014-03-07 16:51:41 -0800873 enforceConnectivityInternalPermission();
Robert Greenwalt304aad42013-05-31 17:57:10 -0700874 final long token = Binder.clearCallingIdentity();
875 try {
876 mWifiStateMachine.setCountryCode(countryCode, persist);
877 } finally {
878 Binder.restoreCallingIdentity(token);
879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 }
881
882 /**
Irfan Sheriff36f74132010-11-04 16:57:37 -0700883 * Set the operational frequency band
884 * @param band One of
885 * {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO},
886 * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ},
887 * {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ},
888 * @param persist {@code true} if the setting should be remembered.
889 *
890 */
891 public void setFrequencyBand(int band, boolean persist) {
892 enforceChangePermission();
893 if (!isDualBandSupported()) return;
894 Slog.i(TAG, "WifiService trying to set frequency band to " + band +
895 " with persist set to " + persist);
Robert Greenwalt304aad42013-05-31 17:57:10 -0700896 final long token = Binder.clearCallingIdentity();
897 try {
898 mWifiStateMachine.setFrequencyBand(band, persist);
899 } finally {
900 Binder.restoreCallingIdentity(token);
901 }
Irfan Sheriff36f74132010-11-04 16:57:37 -0700902 }
903
904
905 /**
906 * Get the operational frequency band
907 */
908 public int getFrequencyBand() {
909 enforceAccessPermission();
910 return mWifiStateMachine.getFrequencyBand();
911 }
912
913 public boolean isDualBandSupported() {
914 //TODO: Should move towards adding a driver API that checks at runtime
915 return mContext.getResources().getBoolean(
916 com.android.internal.R.bool.config_wifi_dual_band_support);
917 }
918
919 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 * Return the DHCP-assigned addresses from the last successful DHCP request,
921 * if any.
922 * @return the DHCP information
Robert Greenwalt4717c262012-10-31 14:32:53 -0700923 * @deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 */
925 public DhcpInfo getDhcpInfo() {
926 enforceAccessPermission();
Robert Greenwalt4717c262012-10-31 14:32:53 -0700927 DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults();
928 if (dhcpResults.linkProperties == null) return null;
929
930 DhcpInfo info = new DhcpInfo();
931 for (LinkAddress la : dhcpResults.linkProperties.getLinkAddresses()) {
932 InetAddress addr = la.getAddress();
933 if (addr instanceof Inet4Address) {
934 info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address)addr);
935 break;
936 }
937 }
938 for (RouteInfo r : dhcpResults.linkProperties.getRoutes()) {
939 if (r.isDefaultRoute()) {
940 InetAddress gateway = r.getGateway();
941 if (gateway instanceof Inet4Address) {
942 info.gateway = NetworkUtils.inetAddressToInt((Inet4Address)gateway);
943 }
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700944 } else if (r.hasGateway() == false) {
Robert Greenwalt4717c262012-10-31 14:32:53 -0700945 LinkAddress dest = r.getDestination();
946 if (dest.getAddress() instanceof Inet4Address) {
947 info.netmask = NetworkUtils.prefixLengthToNetmaskInt(
948 dest.getNetworkPrefixLength());
949 }
950 }
951 }
952 int dnsFound = 0;
953 for (InetAddress dns : dhcpResults.linkProperties.getDnses()) {
954 if (dns instanceof Inet4Address) {
955 if (dnsFound == 0) {
956 info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns);
957 } else {
958 info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns);
959 }
960 if (++dnsFound > 1) break;
961 }
962 }
963 InetAddress serverAddress = dhcpResults.serverAddress;
964 if (serverAddress instanceof Inet4Address) {
965 info.serverAddress = NetworkUtils.inetAddressToInt((Inet4Address)serverAddress);
966 }
967 info.leaseDuration = dhcpResults.leaseDuration;
968
969 return info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 }
971
Irfan Sheriff0d255342010-07-28 09:35:20 -0700972 /**
973 * see {@link android.net.wifi.WifiManager#startWifi}
974 *
975 */
976 public void startWifi() {
Irfan Sheriffda6da092012-08-16 12:49:23 -0700977 enforceConnectivityInternalPermission();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700978 /* TODO: may be add permissions for access only to connectivity service
979 * TODO: if a start issued, keep wifi alive until a stop issued irrespective
980 * of WifiLock & device idle status unless wifi enabled status is toggled
981 */
982
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800983 mWifiStateMachine.setDriverStart(true);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700984 mWifiStateMachine.reconnectCommand();
985 }
986
Irfan Sheriffda6da092012-08-16 12:49:23 -0700987 public void captivePortalCheckComplete() {
988 enforceConnectivityInternalPermission();
989 mWifiStateMachine.captivePortalCheckComplete();
990 }
991
Irfan Sheriff0d255342010-07-28 09:35:20 -0700992 /**
993 * see {@link android.net.wifi.WifiManager#stopWifi}
994 *
995 */
996 public void stopWifi() {
Irfan Sheriffda6da092012-08-16 12:49:23 -0700997 enforceConnectivityInternalPermission();
998 /*
Irfan Sheriff0d255342010-07-28 09:35:20 -0700999 * TODO: if a stop is issued, wifi is brought up only by startWifi
1000 * unless wifi enabled status is toggled
1001 */
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001002 mWifiStateMachine.setDriverStart(false);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001003 }
1004
Irfan Sheriff0d255342010-07-28 09:35:20 -07001005 /**
1006 * see {@link android.net.wifi.WifiManager#addToBlacklist}
1007 *
1008 */
1009 public void addToBlacklist(String bssid) {
1010 enforceChangePermission();
1011
1012 mWifiStateMachine.addToBlacklist(bssid);
1013 }
1014
1015 /**
1016 * see {@link android.net.wifi.WifiManager#clearBlacklist}
1017 *
1018 */
1019 public void clearBlacklist() {
1020 enforceChangePermission();
1021
1022 mWifiStateMachine.clearBlacklist();
1023 }
1024
Irfan Sheriff227bec42011-02-15 19:30:27 -08001025 /**
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -07001026 * enable TDLS for the local NIC to remote NIC
1027 * The APPs don't know the remote MAC address to identify NIC though,
1028 * so we need to do additional work to find it from remote IP address
1029 */
1030
1031 class TdlsTaskParams {
1032 public String remoteIpAddress;
1033 public boolean enable;
1034 }
1035
1036 class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> {
1037 @Override
1038 protected Integer doInBackground(TdlsTaskParams... params) {
1039
1040 // Retrieve parameters for the call
1041 TdlsTaskParams param = params[0];
1042 String remoteIpAddress = param.remoteIpAddress.trim();
1043 boolean enable = param.enable;
1044
1045 // Get MAC address of Remote IP
1046 String macAddress = null;
1047
1048 BufferedReader reader = null;
1049
1050 try {
1051 reader = new BufferedReader(new FileReader("/proc/net/arp"));
1052
1053 // Skip over the line bearing colum titles
1054 String line = reader.readLine();
1055
1056 while ((line = reader.readLine()) != null) {
1057 String[] tokens = line.split("[ ]+");
1058 if (tokens.length < 6) {
1059 continue;
1060 }
1061
1062 // ARP column format is
1063 // Address HWType HWAddress Flags Mask IFace
1064 String ip = tokens[0];
1065 String mac = tokens[3];
1066
1067 if (remoteIpAddress.equals(ip)) {
1068 macAddress = mac;
1069 break;
1070 }
1071 }
1072
1073 if (macAddress == null) {
1074 Slog.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " +
1075 "/proc/net/arp");
1076 } else {
1077 enableTdlsWithMacAddress(macAddress, enable);
1078 }
1079
1080 } catch (FileNotFoundException e) {
1081 Slog.e(TAG, "Could not open /proc/net/arp to lookup mac address");
1082 } catch (IOException e) {
1083 Slog.e(TAG, "Could not read /proc/net/arp to lookup mac address");
1084 } finally {
1085 try {
1086 if (reader != null) {
1087 reader.close();
1088 }
1089 }
1090 catch (IOException e) {
1091 // Do nothing
1092 }
1093 }
1094
1095 return 0;
1096 }
1097 }
1098
1099 public void enableTdls(String remoteAddress, boolean enable) {
1100 TdlsTaskParams params = new TdlsTaskParams();
1101 params.remoteIpAddress = remoteAddress;
1102 params.enable = enable;
1103 new TdlsTask().execute(params);
1104 }
1105
1106
1107 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) {
1108 mWifiStateMachine.enableTdls(remoteMacAddress, enable);
1109 }
1110
1111 /**
Irfan Sheriff227bec42011-02-15 19:30:27 -08001112 * Get a reference to handler. This is used by a client to establish
1113 * an AsyncChannel communication with WifiService
1114 */
Irfan Sheriff07573b32012-01-27 21:00:19 -08001115 public Messenger getWifiServiceMessenger() {
Irfan Sheriff35bbe272012-08-23 16:57:43 -07001116 enforceAccessPermission();
1117 enforceChangePermission();
Irfan Sheriffb8c0e002013-02-20 14:19:54 -08001118 return new Messenger(mClientHandler);
Irfan Sheriff227bec42011-02-15 19:30:27 -08001119 }
1120
Irfan Sheriff07573b32012-01-27 21:00:19 -08001121 /** Get a reference to WifiStateMachine handler for AsyncChannel communication */
1122 public Messenger getWifiStateMachineMessenger() {
1123 enforceAccessPermission();
1124 enforceChangePermission();
1125 return mWifiStateMachine.getMessenger();
1126 }
1127
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -08001128 /**
1129 * Get the IP and proxy configuration file
1130 */
1131 public String getConfigFile() {
1132 enforceAccessPermission();
1133 return mWifiStateMachine.getConfigFile();
1134 }
1135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
1137 @Override
1138 public void onReceive(Context context, Intent intent) {
1139 String action = intent.getAction();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 if (action.equals(Intent.ACTION_SCREEN_ON)) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001141 mWifiController.sendMessage(CMD_SCREEN_ON);
Vinit Deshapndea3038b22013-10-02 17:26:05 -07001142 } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
1143 mWifiController.sendMessage(CMD_USER_PRESENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001145 mWifiController.sendMessage(CMD_SCREEN_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 int pluggedType = intent.getIntExtra("plugged", 0);
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001148 mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null);
Irfan Sheriff65eaec82011-01-05 22:00:16 -08001149 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
1150 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
1151 BluetoothAdapter.STATE_DISCONNECTED);
1152 mWifiStateMachine.sendBluetoothAdapterStateChange(state);
Irfan Sheriff616f3172011-09-11 19:59:01 -07001153 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001154 boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);
1155 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 };
1159
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001160 /**
1161 * Observes settings changes to scan always mode.
1162 */
1163 private void registerForScanModeChange() {
1164 ContentObserver contentObserver = new ContentObserver(null) {
1165 @Override
1166 public void onChange(boolean selfChange) {
1167 mSettingsStore.handleWifiScanAlwaysAvailableToggled();
1168 mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED);
Dianne Hackborn58e0eef2010-09-16 01:22:10 -07001169 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001170 };
Jaikumar Ganesh7440fc22010-09-27 17:04:14 -07001171
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001172 mContext.getContentResolver().registerContentObserver(
1173 Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE),
1174 false, contentObserver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 }
1176
1177 private void registerForBroadcasts() {
1178 IntentFilter intentFilter = new IntentFilter();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
Vinit Deshapndea3038b22013-10-02 17:26:05 -07001180 intentFilter.addAction(Intent.ACTION_USER_PRESENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
1182 intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001183 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
Irfan Sheriff65eaec82011-01-05 22:00:16 -08001184 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
Irfan Sheriff616f3172011-09-11 19:59:01 -07001185 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 mContext.registerReceiver(mReceiver, intentFilter);
1187 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 @Override
1190 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1191 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1192 != PackageManager.PERMISSION_GRANTED) {
1193 pw.println("Permission Denial: can't dump WifiService from from pid="
1194 + Binder.getCallingPid()
1195 + ", uid=" + Binder.getCallingUid());
1196 return;
1197 }
Irfan Sheriffd8134ff2010-08-22 17:06:34 -07001198 pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 pw.println("Stay-awake conditions: " +
Christopher Tatec09cdce2012-09-10 16:50:14 -07001200 Settings.Global.getInt(mContext.getContentResolver(),
1201 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0));
Irfan Sherifff0afe412012-11-30 14:07:44 -08001202 pw.println("mMulticastEnabled " + mMulticastEnabled);
1203 pw.println("mMulticastDisabled " + mMulticastDisabled);
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001204 mWifiController.dump(fd, pw, args);
Irfan Sheriffb8c0e002013-02-20 14:19:54 -08001205 mSettingsStore.dump(fd, pw, args);
1206 mNotificationController.dump(fd, pw, args);
1207 mTrafficPoller.dump(fd, pw, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 pw.println("Latest scan results:");
Irfan Sheriffd8134ff2010-08-22 17:06:34 -07001210 List<ScanResult> scanResults = mWifiStateMachine.syncGetScanResultsList();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 if (scanResults != null && scanResults.size() != 0) {
1212 pw.println(" BSSID Frequency RSSI Flags SSID");
1213 for (ScanResult r : scanResults) {
1214 pw.printf(" %17s %9d %5d %-16s %s%n",
1215 r.BSSID,
1216 r.frequency,
1217 r.level,
1218 r.capabilities,
1219 r.SSID == null ? "" : r.SSID);
1220 }
1221 }
1222 pw.println();
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001223 pw.println("Locks acquired: " + mFullLocksAcquired + " full, " +
Irfan Sheriff5876a422010-08-12 20:26:23 -07001224 mFullHighPerfLocksAcquired + " full high perf, " +
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001225 mScanLocksAcquired + " scan");
1226 pw.println("Locks released: " + mFullLocksReleased + " full, " +
Irfan Sheriff5876a422010-08-12 20:26:23 -07001227 mFullHighPerfLocksReleased + " full high perf, " +
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001228 mScanLocksReleased + " scan");
1229 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 pw.println("Locks held:");
1231 mLocks.dump(pw);
Isaac Levybc7dfb52011-06-06 15:34:01 -07001232
Irfan Sherifff0afe412012-11-30 14:07:44 -08001233 mWifiWatchdogStateMachine.dump(fd, pw, args);
Isaac Levybc7dfb52011-06-06 15:34:01 -07001234 pw.println();
Irfan Sheriff60792372012-04-16 16:47:10 -07001235 mWifiStateMachine.dump(fd, pw, args);
Irfan Sherifff0afe412012-11-30 14:07:44 -08001236 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 }
1238
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001239 private class WifiLock extends DeathRecipient {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001240 WifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) {
1241 super(lockMode, tag, binder, ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242 }
1243
1244 public void binderDied() {
1245 synchronized (mLocks) {
1246 releaseWifiLockLocked(mBinder);
1247 }
1248 }
1249
1250 public String toString() {
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001251 return "WifiLock{" + mTag + " type=" + mMode + " binder=" + mBinder + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 }
1253 }
1254
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001255 class LockList {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 private List<WifiLock> mList;
1257
1258 private LockList() {
1259 mList = new ArrayList<WifiLock>();
1260 }
1261
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001262 synchronized boolean hasLocks() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 return !mList.isEmpty();
1264 }
1265
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001266 synchronized int getStrongestLockMode() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 if (mList.isEmpty()) {
1268 return WifiManager.WIFI_MODE_FULL;
1269 }
Irfan Sheriff5876a422010-08-12 20:26:23 -07001270
1271 if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) {
1272 return WifiManager.WIFI_MODE_FULL_HIGH_PERF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 }
Irfan Sheriff5876a422010-08-12 20:26:23 -07001274
1275 if (mFullLocksAcquired > mFullLocksReleased) {
1276 return WifiManager.WIFI_MODE_FULL;
1277 }
1278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 return WifiManager.WIFI_MODE_SCAN_ONLY;
1280 }
1281
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001282 synchronized void updateWorkSource(WorkSource ws) {
1283 for (int i = 0; i < mLocks.mList.size(); i++) {
1284 ws.add(mLocks.mList.get(i).mWorkSource);
1285 }
1286 }
1287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 private void addLock(WifiLock lock) {
1289 if (findLockByBinder(lock.mBinder) < 0) {
1290 mList.add(lock);
1291 }
1292 }
1293
1294 private WifiLock removeLock(IBinder binder) {
1295 int index = findLockByBinder(binder);
1296 if (index >= 0) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001297 WifiLock ret = mList.remove(index);
1298 ret.unlinkDeathRecipient();
1299 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001300 } else {
1301 return null;
1302 }
1303 }
1304
1305 private int findLockByBinder(IBinder binder) {
1306 int size = mList.size();
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001307 for (int i = size - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001308 if (mList.get(i).mBinder == binder)
1309 return i;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 return -1;
1312 }
1313
1314 private void dump(PrintWriter pw) {
1315 for (WifiLock l : mList) {
1316 pw.print(" ");
1317 pw.println(l);
1318 }
1319 }
1320 }
1321
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001322 void enforceWakeSourcePermission(int uid, int pid) {
Dianne Hackborne746f032010-09-13 16:02:57 -07001323 if (uid == android.os.Process.myUid()) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001324 return;
1325 }
1326 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
1327 pid, uid, null);
1328 }
1329
1330 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
Irfan Sheriff5876a422010-08-12 20:26:23 -07001332 if (lockMode != WifiManager.WIFI_MODE_FULL &&
1333 lockMode != WifiManager.WIFI_MODE_SCAN_ONLY &&
1334 lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF) {
1335 Slog.e(TAG, "Illegal argument, lockMode= " + lockMode);
1336 if (DBG) throw new IllegalArgumentException("lockMode=" + lockMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 return false;
1338 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001339 if (ws != null && ws.size() == 0) {
1340 ws = null;
1341 }
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001342 if (ws != null) {
1343 enforceWakeSourcePermission(Binder.getCallingUid(), Binder.getCallingPid());
1344 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001345 if (ws == null) {
1346 ws = new WorkSource(Binder.getCallingUid());
1347 }
1348 WifiLock wifiLock = new WifiLock(lockMode, tag, binder, ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 synchronized (mLocks) {
1350 return acquireWifiLockLocked(wifiLock);
1351 }
1352 }
1353
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001354 private void noteAcquireWifiLock(WifiLock wifiLock) throws RemoteException {
1355 switch(wifiLock.mMode) {
1356 case WifiManager.WIFI_MODE_FULL:
Irfan Sheriff5876a422010-08-12 20:26:23 -07001357 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001358 case WifiManager.WIFI_MODE_SCAN_ONLY:
Nick Pelly6ccaa542012-06-15 15:22:47 -07001359 mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001360 break;
1361 }
1362 }
1363
1364 private void noteReleaseWifiLock(WifiLock wifiLock) throws RemoteException {
1365 switch(wifiLock.mMode) {
1366 case WifiManager.WIFI_MODE_FULL:
Irfan Sheriff5876a422010-08-12 20:26:23 -07001367 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001368 case WifiManager.WIFI_MODE_SCAN_ONLY:
Nick Pelly6ccaa542012-06-15 15:22:47 -07001369 mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001370 break;
1371 }
1372 }
1373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 private boolean acquireWifiLockLocked(WifiLock wifiLock) {
Irfan Sheriffc89dd542010-09-28 08:40:54 -07001375 if (DBG) Slog.d(TAG, "acquireWifiLockLocked: " + wifiLock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 mLocks.addLock(wifiLock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001378
The Android Open Source Project10592532009-03-18 17:39:46 -07001379 long ident = Binder.clearCallingIdentity();
1380 try {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001381 noteAcquireWifiLock(wifiLock);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001382 switch(wifiLock.mMode) {
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001383 case WifiManager.WIFI_MODE_FULL:
1384 ++mFullLocksAcquired;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001385 break;
Irfan Sheriff5876a422010-08-12 20:26:23 -07001386 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
1387 ++mFullHighPerfLocksAcquired;
1388 break;
1389
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001390 case WifiManager.WIFI_MODE_SCAN_ONLY:
1391 ++mScanLocksAcquired;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001392 break;
The Android Open Source Project10592532009-03-18 17:39:46 -07001393 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001394 mWifiController.sendMessage(CMD_LOCKS_CHANGED);
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001395 return true;
The Android Open Source Project10592532009-03-18 17:39:46 -07001396 } catch (RemoteException e) {
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001397 return false;
The Android Open Source Project10592532009-03-18 17:39:46 -07001398 } finally {
1399 Binder.restoreCallingIdentity(ident);
1400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 }
1402
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001403 public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) {
1404 int uid = Binder.getCallingUid();
1405 int pid = Binder.getCallingPid();
1406 if (ws != null && ws.size() == 0) {
1407 ws = null;
1408 }
1409 if (ws != null) {
1410 enforceWakeSourcePermission(uid, pid);
1411 }
1412 long ident = Binder.clearCallingIdentity();
1413 try {
1414 synchronized (mLocks) {
1415 int index = mLocks.findLockByBinder(lock);
1416 if (index < 0) {
1417 throw new IllegalArgumentException("Wifi lock not active");
1418 }
1419 WifiLock wl = mLocks.mList.get(index);
1420 noteReleaseWifiLock(wl);
1421 wl.mWorkSource = ws != null ? new WorkSource(ws) : new WorkSource(uid);
1422 noteAcquireWifiLock(wl);
1423 }
1424 } catch (RemoteException e) {
1425 } finally {
1426 Binder.restoreCallingIdentity(ident);
1427 }
1428 }
1429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 public boolean releaseWifiLock(IBinder lock) {
1431 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
1432 synchronized (mLocks) {
1433 return releaseWifiLockLocked(lock);
1434 }
1435 }
1436
1437 private boolean releaseWifiLockLocked(IBinder lock) {
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001438 boolean hadLock;
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001439
The Android Open Source Project10592532009-03-18 17:39:46 -07001440 WifiLock wifiLock = mLocks.removeLock(lock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001441
Irfan Sheriffc89dd542010-09-28 08:40:54 -07001442 if (DBG) Slog.d(TAG, "releaseWifiLockLocked: " + wifiLock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001443
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001444 hadLock = (wifiLock != null);
1445
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001446 long ident = Binder.clearCallingIdentity();
1447 try {
1448 if (hadLock) {
Wink Savillece0ea1f2011-10-13 16:55:20 -07001449 noteReleaseWifiLock(wifiLock);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001450 switch(wifiLock.mMode) {
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001451 case WifiManager.WIFI_MODE_FULL:
1452 ++mFullLocksReleased;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001453 break;
Irfan Sheriff5876a422010-08-12 20:26:23 -07001454 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
1455 ++mFullHighPerfLocksReleased;
1456 break;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001457 case WifiManager.WIFI_MODE_SCAN_ONLY:
1458 ++mScanLocksReleased;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001459 break;
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001460 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001461 mWifiController.sendMessage(CMD_LOCKS_CHANGED);
The Android Open Source Project10592532009-03-18 17:39:46 -07001462 }
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001463 } catch (RemoteException e) {
1464 } finally {
1465 Binder.restoreCallingIdentity(ident);
The Android Open Source Project10592532009-03-18 17:39:46 -07001466 }
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001467
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001468 return hadLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 }
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001470
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001471 private abstract class DeathRecipient
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001472 implements IBinder.DeathRecipient {
1473 String mTag;
1474 int mMode;
1475 IBinder mBinder;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001476 WorkSource mWorkSource;
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001477
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001478 DeathRecipient(int mode, String tag, IBinder binder, WorkSource ws) {
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001479 super();
1480 mTag = tag;
1481 mMode = mode;
1482 mBinder = binder;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001483 mWorkSource = ws;
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001484 try {
1485 mBinder.linkToDeath(this, 0);
1486 } catch (RemoteException e) {
1487 binderDied();
1488 }
1489 }
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001490
1491 void unlinkDeathRecipient() {
1492 mBinder.unlinkToDeath(this, 0);
1493 }
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001494 }
1495
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001496 private class Multicaster extends DeathRecipient {
1497 Multicaster(String tag, IBinder binder) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001498 super(Binder.getCallingUid(), tag, binder, null);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001499 }
1500
1501 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001502 Slog.e(TAG, "Multicaster binderDied");
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001503 synchronized (mMulticasters) {
1504 int i = mMulticasters.indexOf(this);
1505 if (i != -1) {
1506 removeMulticasterLocked(i, mMode);
1507 }
1508 }
1509 }
1510
1511 public String toString() {
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001512 return "Multicaster{" + mTag + " binder=" + mBinder + "}";
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001513 }
1514
1515 public int getUid() {
1516 return mMode;
1517 }
1518 }
1519
Robert Greenwalte2d155a2009-10-21 14:58:34 -07001520 public void initializeMulticastFiltering() {
1521 enforceMulticastChangePermission();
Irfan Sheriffa8fbe1f2010-03-09 09:13:58 -08001522
Robert Greenwalte2d155a2009-10-21 14:58:34 -07001523 synchronized (mMulticasters) {
1524 // if anybody had requested filters be off, leave off
1525 if (mMulticasters.size() != 0) {
1526 return;
1527 } else {
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001528 mWifiStateMachine.startFilteringMulticastV4Packets();
Robert Greenwalte2d155a2009-10-21 14:58:34 -07001529 }
1530 }
1531 }
1532
Robert Greenwaltfc1b15c2009-05-22 15:09:51 -07001533 public void acquireMulticastLock(IBinder binder, String tag) {
1534 enforceMulticastChangePermission();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001535
1536 synchronized (mMulticasters) {
1537 mMulticastEnabled++;
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001538 mMulticasters.add(new Multicaster(tag, binder));
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001539 // Note that we could call stopFilteringMulticastV4Packets only when
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001540 // our new size == 1 (first call), but this function won't
1541 // be called often and by making the stopPacket call each
1542 // time we're less fragile and self-healing.
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001543 mWifiStateMachine.stopFilteringMulticastV4Packets();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001544 }
1545
1546 int uid = Binder.getCallingUid();
You Kim2bea5852012-10-23 22:56:51 +09001547 final long ident = Binder.clearCallingIdentity();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001548 try {
1549 mBatteryStats.noteWifiMulticastEnabled(uid);
1550 } catch (RemoteException e) {
1551 } finally {
1552 Binder.restoreCallingIdentity(ident);
1553 }
1554 }
1555
Robert Greenwaltfc1b15c2009-05-22 15:09:51 -07001556 public void releaseMulticastLock() {
1557 enforceMulticastChangePermission();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001558
1559 int uid = Binder.getCallingUid();
1560 synchronized (mMulticasters) {
1561 mMulticastDisabled++;
1562 int size = mMulticasters.size();
1563 for (int i = size - 1; i >= 0; i--) {
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001564 Multicaster m = mMulticasters.get(i);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001565 if ((m != null) && (m.getUid() == uid)) {
1566 removeMulticasterLocked(i, uid);
1567 }
1568 }
1569 }
1570 }
1571
1572 private void removeMulticasterLocked(int i, int uid)
1573 {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001574 Multicaster removed = mMulticasters.remove(i);
Irfan Sheriffa8fbe1f2010-03-09 09:13:58 -08001575
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001576 if (removed != null) {
1577 removed.unlinkDeathRecipient();
1578 }
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001579 if (mMulticasters.size() == 0) {
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001580 mWifiStateMachine.startFilteringMulticastV4Packets();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001581 }
1582
You Kim2bea5852012-10-23 22:56:51 +09001583 final long ident = Binder.clearCallingIdentity();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001584 try {
1585 mBatteryStats.noteWifiMulticastDisabled(uid);
1586 } catch (RemoteException e) {
1587 } finally {
1588 Binder.restoreCallingIdentity(ident);
1589 }
1590 }
1591
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001592 public boolean isMulticastEnabled() {
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001593 enforceAccessPermission();
1594
1595 synchronized (mMulticasters) {
1596 return (mMulticasters.size() > 0);
1597 }
1598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599}