blob: 6118503e95929f40671c862858ed88305ae39089 [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.wifi.IWifiManager;
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -080029import android.net.wifi.ScanResult;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.net.wifi.WifiInfo;
31import android.net.wifi.WifiManager;
Irfan Sheriff0d255342010-07-28 09:35:20 -070032import android.net.wifi.WifiStateMachine;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.net.wifi.WifiConfiguration;
Isaac Levy654f5092011-07-13 17:41:45 -070034import android.net.wifi.WifiWatchdogStateMachine;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.net.DhcpInfo;
Robert Greenwalt4717c262012-10-31 14:32:53 -070036import android.net.DhcpResults;
37import android.net.LinkAddress;
Robert Greenwalt4717c262012-10-31 14:32:53 -070038import android.net.NetworkUtils;
39import android.net.RouteInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.Binder;
Irfan Sheriff0d255342010-07-28 09:35:20 -070041import android.os.Handler;
Irfan Sheriff227bec42011-02-15 19:30:27 -080042import android.os.Messenger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.os.HandlerThread;
44import android.os.IBinder;
Irfan Sheriff5321aef2010-02-12 12:35:59 -080045import android.os.INetworkManagementService;
Irfan Sheriff0d255342010-07-28 09:35:20 -070046import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.os.RemoteException;
Irfan Sheriff227bec42011-02-15 19:30:27 -080048import android.os.SystemProperties;
Irfan Sheriff330b1872012-09-16 12:27:57 -070049import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070050import android.os.WorkSource;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070051import android.os.AsyncTask;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.provider.Settings;
Nick Pelly6ccaa542012-06-15 15:22:47 -070053import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080054import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070056import java.io.FileNotFoundException;
57import java.io.BufferedReader;
Irfan Sherifff0afe412012-11-30 14:07:44 -080058import java.io.FileDescriptor;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070059import java.io.FileReader;
60import java.io.IOException;
Irfan Sherifff0afe412012-11-30 14:07:44 -080061import java.io.PrintWriter;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070062
Robert Greenwalt4717c262012-10-31 14:32:53 -070063import java.net.InetAddress;
64import java.net.Inet4Address;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import java.util.List;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -070067
Irfan Sheriff07a22952013-03-27 13:27:39 -070068import java.util.concurrent.atomic.AtomicBoolean;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069
Irfan Sheriff11aefad2013-03-06 07:57:41 -080070import com.android.internal.R;
The Android Open Source Project10592532009-03-18 17:39:46 -070071import com.android.internal.app.IBatteryStats;
Irfan Sheriff616f3172011-09-11 19:59:01 -070072import com.android.internal.telephony.TelephonyIntents;
Wink Saville4b7ba092010-10-20 15:37:41 -070073import com.android.internal.util.AsyncChannel;
The Android Open Source Project10592532009-03-18 17:39:46 -070074import com.android.server.am.BatteryStatsService;
Irfan Sheriff11aefad2013-03-06 07:57:41 -080075import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED;
76import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED;
77import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED;
78import static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED;
79import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED;
80import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF;
81import static com.android.server.wifi.WifiController.CMD_SCREEN_ON;
82import static com.android.server.wifi.WifiController.CMD_SET_AP;
83import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084/**
85 * WifiService handles remote WiFi operation requests by implementing
Irfan Sheriffa2a1b912010-06-07 09:03:04 -070086 * the IWifiManager interface.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 *
88 * @hide
89 */
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080090public final class WifiService extends IWifiManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 private static final String TAG = "WifiService";
Dianne Hackborn5fd21692011-06-07 14:09:47 -070092 private static final boolean DBG = false;
Irfan Sheriffa2a1b912010-06-07 09:03:04 -070093
Irfan Sheriff11aefad2013-03-06 07:57:41 -080094 final WifiStateMachine mWifiStateMachine;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080096 private final Context mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097
Irfan Sheriff11aefad2013-03-06 07:57:41 -080098 final LockList mLocks = new LockList();
Eric Shienbrood5711fad2009-03-27 20:25:31 -070099 // some wifi lock statistics
Irfan Sheriff5876a422010-08-12 20:26:23 -0700100 private int mFullHighPerfLocksAcquired;
101 private int mFullHighPerfLocksReleased;
Eric Shienbrood5711fad2009-03-27 20:25:31 -0700102 private int mFullLocksAcquired;
103 private int mFullLocksReleased;
104 private int mScanLocksAcquired;
105 private int mScanLocksReleased;
The Android Open Source Project10592532009-03-18 17:39:46 -0700106
Robert Greenwalt58ff0212009-05-19 15:53:54 -0700107 private final List<Multicaster> mMulticasters =
108 new ArrayList<Multicaster>();
Robert Greenwalt5347bd42009-05-13 15:10:16 -0700109 private int mMulticastEnabled;
110 private int mMulticastDisabled;
111
The Android Open Source Project10592532009-03-18 17:39:46 -0700112 private final IBatteryStats mBatteryStats;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800113 private final AppOpsManager mAppOps;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800114
Irfan Sheriff227bec42011-02-15 19:30:27 -0800115 private String mInterfaceName;
116
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800117 /* Tracks the open wi-fi network notification */
118 private WifiNotificationController mNotificationController;
119 /* Polls traffic stats and notifies clients */
120 private WifiTrafficPoller mTrafficPoller;
121 /* Tracks the persisted states for wi-fi & airplane mode */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800122 final WifiSettingsStore mSettingsStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123
Dianne Hackborn03f3cb02010-09-17 23:12:26 -0700124 /**
Wink Saville4b7ba092010-10-20 15:37:41 -0700125 * Asynchronous channel to WifiStateMachine
126 */
Irfan Sheriff227bec42011-02-15 19:30:27 -0800127 private AsyncChannel mWifiStateMachineChannel;
Wink Saville4b7ba092010-10-20 15:37:41 -0700128
129 /**
Irfan Sheriff227bec42011-02-15 19:30:27 -0800130 * Handles client connections
131 */
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800132 private class ClientHandler extends Handler {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800133
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800134 ClientHandler(android.os.Looper looper) {
Wink Saville4b7ba092010-10-20 15:37:41 -0700135 super(looper);
Wink Saville4b7ba092010-10-20 15:37:41 -0700136 }
137
138 @Override
139 public void handleMessage(Message msg) {
140 switch (msg.what) {
141 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
142 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
Irfan Sheriff6bfc8882012-08-29 15:35:57 -0700143 if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
Irfan Sheriff302b06d2013-02-22 12:35:31 -0800144 // We track the clients by the Messenger
145 // since it is expected to be always available
Irfan Sheriffc808a192013-03-05 09:46:36 -0800146 mTrafficPoller.addClient(msg.replyTo);
Wink Saville4b7ba092010-10-20 15:37:41 -0700147 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800148 Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
149 }
150 break;
151 }
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800152 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
153 if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
Irfan Sheriff6bfc8882012-08-29 15:35:57 -0700154 if (DBG) Slog.d(TAG, "Send failed, client connection lost");
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800155 } else {
Irfan Sheriff6bfc8882012-08-29 15:35:57 -0700156 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800157 }
Irfan Sheriffc808a192013-03-05 09:46:36 -0800158 mTrafficPoller.removeClient(msg.replyTo);
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800159 break;
160 }
Irfan Sheriff227bec42011-02-15 19:30:27 -0800161 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
162 AsyncChannel ac = new AsyncChannel();
163 ac.connect(mContext, this, msg.replyTo);
164 break;
165 }
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800166 /* Client commands are forwarded to state machine */
167 case WifiManager.CONNECT_NETWORK:
168 case WifiManager.SAVE_NETWORK:
169 case WifiManager.FORGET_NETWORK:
170 case WifiManager.START_WPS:
171 case WifiManager.CANCEL_WPS:
172 case WifiManager.DISABLE_NETWORK:
Yuhao Zhengf6307822012-08-14 14:21:25 -0700173 case WifiManager.RSSI_PKTCNT_FETCH: {
174 mWifiStateMachine.sendMessage(Message.obtain(msg));
175 break;
176 }
Wink Saville4b7ba092010-10-20 15:37:41 -0700177 default: {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800178 Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg);
Wink Saville4b7ba092010-10-20 15:37:41 -0700179 break;
180 }
181 }
182 }
183 }
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800184 private ClientHandler mClientHandler;
Irfan Sheriff227bec42011-02-15 19:30:27 -0800185
186 /**
187 * Handles interaction with WifiStateMachine
188 */
189 private class WifiStateMachineHandler extends Handler {
190 private AsyncChannel mWsmChannel;
191
192 WifiStateMachineHandler(android.os.Looper looper) {
193 super(looper);
194 mWsmChannel = new AsyncChannel();
195 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
196 }
197
198 @Override
199 public void handleMessage(Message msg) {
200 switch (msg.what) {
201 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
202 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
203 mWifiStateMachineChannel = mWsmChannel;
204 } else {
205 Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1);
206 mWifiStateMachineChannel = null;
207 }
208 break;
209 }
Irfan Sheriff6da83d52011-06-06 12:54:06 -0700210 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
211 Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1);
212 mWifiStateMachineChannel = null;
213 //Re-establish connection to state machine
214 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
215 break;
216 }
Irfan Sheriff227bec42011-02-15 19:30:27 -0800217 default: {
218 Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg);
219 break;
220 }
221 }
222 }
223 }
224 WifiStateMachineHandler mWifiStateMachineHandler;
Wink Saville4b7ba092010-10-20 15:37:41 -0700225
Isaac Levy654f5092011-07-13 17:41:45 -0700226 private WifiWatchdogStateMachine mWifiWatchdogStateMachine;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700227
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800228 public WifiService(Context context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 mContext = context;
Irfan Sheriff227bec42011-02-15 19:30:27 -0800230
231 mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
232
233 mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700234 mWifiStateMachine.enableRssiPolling(true);
The Android Open Source Project10592532009-03-18 17:39:46 -0700235 mBatteryStats = BatteryStatsService.getService();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800236 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800237
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800238 mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
Irfan Sheriffc808a192013-03-05 09:46:36 -0800239 mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800240 mSettingsStore = new WifiSettingsStore(mContext);
241
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800242 HandlerThread wifiThread = new HandlerThread("WifiService");
243 wifiThread.start();
244 mClientHandler = new ClientHandler(wifiThread.getLooper());
245 mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
246 mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
247 mWifiController.start();
248
249 registerForScanModeChange();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 mContext.registerReceiver(
251 new BroadcastReceiver() {
252 @Override
253 public void onReceive(Context context, Intent intent) {
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800254 if (mSettingsStore.handleAirplaneModeToggled()) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800255 mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800256 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 }
258 },
259 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
260
Irfan Sheriffe68d8582013-04-23 13:43:43 -0700261 // Adding optimizations of only receiving broadcasts when wifi is enabled
262 // can result in race conditions when apps toggle wifi in the background
263 // without active user involvement. Always receive broadcasts.
264 registerForBroadcasts();
Irfan Sheriff7b009782010-03-11 16:37:45 -0800265 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800266
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800267 private WifiController mWifiController;
268
Irfan Sheriff7b009782010-03-11 16:37:45 -0800269 /**
270 * Check if Wi-Fi needs to be enabled and start
271 * if needed
Irfan Sheriff60e3ba02010-04-02 12:18:45 -0700272 *
273 * This function is used only at boot time
Irfan Sheriff7b009782010-03-11 16:37:45 -0800274 */
Irfan Sheriff0d255342010-07-28 09:35:20 -0700275 public void checkAndStartWifi() {
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800276 /* Check if wi-fi needs to be enabled */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800277 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
Irfan Sheriff7b009782010-03-11 16:37:45 -0800278 Slog.i(TAG, "WifiService starting up with Wi-Fi " +
279 (wifiEnabled ? "enabled" : "disabled"));
Irfan Sherifff03d6202012-05-17 12:33:46 -0700280
281 // If we are already disabled (could be due to airplane mode), avoid changing persist
282 // state here
283 if (wifiEnabled) setWifiEnabled(wifiEnabled);
Isaac Levybc7dfb52011-06-06 15:34:01 -0700284
Isaac Levy654f5092011-07-13 17:41:45 -0700285 mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
286 makeWifiWatchdogStateMachine(mContext);
287
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800288 }
289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 /**
291 * see {@link android.net.wifi.WifiManager#pingSupplicant()}
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700292 * @return {@code true} if the operation succeeds, {@code false} otherwise
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 */
294 public boolean pingSupplicant() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700295 enforceAccessPermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800296 if (mWifiStateMachineChannel != null) {
297 return mWifiStateMachine.syncPingSupplicant(mWifiStateMachineChannel);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700298 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800299 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700300 return false;
301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 }
303
304 /**
305 * see {@link android.net.wifi.WifiManager#startScan()}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 */
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -0800307 public void startScan() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 enforceChangePermission();
Robert Greenwalt89710842013-06-25 11:41:53 -0700309 mWifiStateMachine.startScan(Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 }
311
312 private void enforceAccessPermission() {
313 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
314 "WifiService");
315 }
316
317 private void enforceChangePermission() {
318 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
319 "WifiService");
320
321 }
322
Robert Greenwaltfc1b15c2009-05-22 15:09:51 -0700323 private void enforceMulticastChangePermission() {
324 mContext.enforceCallingOrSelfPermission(
325 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
326 "WifiService");
327 }
328
Irfan Sheriffda6da092012-08-16 12:49:23 -0700329 private void enforceConnectivityInternalPermission() {
330 mContext.enforceCallingOrSelfPermission(
331 android.Manifest.permission.CONNECTIVITY_INTERNAL,
332 "ConnectivityService");
333 }
334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 /**
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700336 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
337 * @param enable {@code true} to enable, {@code false} to disable.
338 * @return {@code true} if the enable/disable operation was
339 * started or is already in the queue.
340 */
341 public synchronized boolean setWifiEnabled(boolean enable) {
342 enforceChangePermission();
Irfan Sheriffbd21b782012-05-16 13:13:54 -0700343 Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
344 + ", uid=" + Binder.getCallingUid());
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700345 if (DBG) {
Irfan Sheriff0d255342010-07-28 09:35:20 -0700346 Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700347 }
348
Irfan Sheriff61180692010-08-18 16:07:39 -0700349 /*
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800350 * Caller might not have WRITE_SECURE_SETTINGS,
351 * only CHANGE_WIFI_STATE is enforced
352 */
Irfan Sheriff5401f0b2011-12-07 16:27:49 -0800353
Irfan Sherifff03d6202012-05-17 12:33:46 -0700354 long ident = Binder.clearCallingIdentity();
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700355 try {
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800356 if (! mSettingsStore.handleWifiToggled(enable)) {
357 // Nothing to do if wifi cannot be toggled
358 return true;
359 }
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700360 } finally {
361 Binder.restoreCallingIdentity(ident);
362 }
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700363
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800364 mWifiController.sendMessage(CMD_WIFI_TOGGLED);
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700365 return true;
366 }
367
368 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 * see {@link WifiManager#getWifiState()}
370 * @return One of {@link WifiManager#WIFI_STATE_DISABLED},
371 * {@link WifiManager#WIFI_STATE_DISABLING},
372 * {@link WifiManager#WIFI_STATE_ENABLED},
373 * {@link WifiManager#WIFI_STATE_ENABLING},
374 * {@link WifiManager#WIFI_STATE_UNKNOWN}
375 */
376 public int getWifiEnabledState() {
377 enforceAccessPermission();
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700378 return mWifiStateMachine.syncGetWifiState();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 }
380
381 /**
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700382 * see {@link android.net.wifi.WifiManager#setWifiApEnabled(WifiConfiguration, boolean)}
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800383 * @param wifiConfig SSID, security and channel details as
384 * part of WifiConfiguration
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700385 * @param enabled true to enable and false to disable
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800386 */
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700387 public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800388 enforceChangePermission();
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800389 mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig).sendToTarget();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800390 }
391
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700392 /**
393 * see {@link WifiManager#getWifiApState()}
394 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED},
395 * {@link WifiManager#WIFI_AP_STATE_DISABLING},
396 * {@link WifiManager#WIFI_AP_STATE_ENABLED},
397 * {@link WifiManager#WIFI_AP_STATE_ENABLING},
398 * {@link WifiManager#WIFI_AP_STATE_FAILED}
399 */
400 public int getWifiApEnabledState() {
Irfan Sheriff17b232b2010-06-24 11:32:26 -0700401 enforceAccessPermission();
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700402 return mWifiStateMachine.syncGetWifiApState();
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700403 }
404
405 /**
406 * see {@link WifiManager#getWifiApConfiguration()}
407 * @return soft access point configuration
408 */
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700409 public WifiConfiguration getWifiApConfiguration() {
410 enforceAccessPermission();
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800411 return mWifiStateMachine.syncGetWifiApConfiguration();
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800412 }
413
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700414 /**
415 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)}
416 * @param wifiConfig WifiConfiguration details for soft access point
417 */
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700418 public void setWifiApConfiguration(WifiConfiguration wifiConfig) {
Irfan Sheriff17b232b2010-06-24 11:32:26 -0700419 enforceChangePermission();
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800420 if (wifiConfig == null)
421 return;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700422 mWifiStateMachine.setWifiApConfiguration(wifiConfig);
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800423 }
424
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800425 /**
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800426 * @param enable {@code true} to enable, {@code false} to disable.
427 * @return {@code true} if the enable/disable operation was
428 * started or is already in the queue.
429 */
Irfan Sheriff7ea33ea2013-04-19 08:39:53 -0700430 public boolean isScanAlwaysAvailable() {
Irfan Sheriff1ef840c2013-03-12 17:09:27 -0700431 enforceAccessPermission();
432 return mSettingsStore.isScanAlwaysAvailable();
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800433 }
434
435 /**
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700436 * see {@link android.net.wifi.WifiManager#disconnect()}
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800437 */
Irfan Sheriffe4984752010-08-19 11:29:22 -0700438 public void disconnect() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700439 enforceChangePermission();
Irfan Sheriffe4984752010-08-19 11:29:22 -0700440 mWifiStateMachine.disconnectCommand();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800441 }
442
443 /**
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700444 * see {@link android.net.wifi.WifiManager#reconnect()}
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800445 */
Irfan Sheriffe4984752010-08-19 11:29:22 -0700446 public void reconnect() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700447 enforceChangePermission();
Irfan Sheriffe4984752010-08-19 11:29:22 -0700448 mWifiStateMachine.reconnectCommand();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800449 }
450
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700451 /**
452 * see {@link android.net.wifi.WifiManager#reassociate()}
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700453 */
Irfan Sheriffe4984752010-08-19 11:29:22 -0700454 public void reassociate() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700455 enforceChangePermission();
Irfan Sheriffe4984752010-08-19 11:29:22 -0700456 mWifiStateMachine.reassociateCommand();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800457 }
458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 /**
460 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()}
461 * @return the list of configured networks
462 */
463 public List<WifiConfiguration> getConfiguredNetworks() {
464 enforceAccessPermission();
Irfan Sheriffe744cff2011-12-11 09:17:50 -0800465 if (mWifiStateMachineChannel != null) {
466 return mWifiStateMachine.syncGetConfiguredNetworks(mWifiStateMachineChannel);
467 } else {
468 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
469 return null;
470 }
Chung-yih Wanga8d15942009-10-09 11:01:49 +0800471 }
472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 /**
474 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)}
475 * @return the supplicant-assigned identifier for the new or updated
476 * network if the operation succeeds, or {@code -1} if it fails
477 */
Irfan Sheriff7aac5542009-12-22 21:42:17 -0800478 public int addOrUpdateNetwork(WifiConfiguration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800480 if (mWifiStateMachineChannel != null) {
481 return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700482 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800483 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700484 return -1;
485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 }
487
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700488 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 * See {@link android.net.wifi.WifiManager#removeNetwork(int)}
490 * @param netId the integer that identifies the network configuration
491 * to the supplicant
492 * @return {@code true} if the operation succeeded
493 */
494 public boolean removeNetwork(int netId) {
495 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800496 if (mWifiStateMachineChannel != null) {
497 return mWifiStateMachine.syncRemoveNetwork(mWifiStateMachineChannel, netId);
Wink Saville4b7ba092010-10-20 15:37:41 -0700498 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800499 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Wink Saville4b7ba092010-10-20 15:37:41 -0700500 return false;
501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 }
503
504 /**
505 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)}
506 * @param netId the integer that identifies the network configuration
507 * to the supplicant
508 * @param disableOthers if true, disable all other networks.
509 * @return {@code true} if the operation succeeded
510 */
511 public boolean enableNetwork(int netId, boolean disableOthers) {
512 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800513 if (mWifiStateMachineChannel != null) {
514 return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId,
515 disableOthers);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700516 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800517 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700518 return false;
519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 }
521
522 /**
523 * See {@link android.net.wifi.WifiManager#disableNetwork(int)}
524 * @param netId the integer that identifies the network configuration
525 * to the supplicant
526 * @return {@code true} if the operation succeeded
527 */
528 public boolean disableNetwork(int netId) {
529 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800530 if (mWifiStateMachineChannel != null) {
531 return mWifiStateMachine.syncDisableNetwork(mWifiStateMachineChannel, netId);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700532 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800533 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700534 return false;
535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 }
537
538 /**
539 * See {@link android.net.wifi.WifiManager#getConnectionInfo()}
540 * @return the Wi-Fi information, contained in {@link WifiInfo}.
541 */
542 public WifiInfo getConnectionInfo() {
543 enforceAccessPermission();
544 /*
545 * Make sure we have the latest information, by sending
546 * a status request to the supplicant.
547 */
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700548 return mWifiStateMachine.syncRequestConnectionInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 }
550
551 /**
552 * Return the results of the most recent access point scan, in the form of
553 * a list of {@link ScanResult} objects.
554 * @return the list of results
555 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800556 public List<ScanResult> getScanResults(String callingPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 enforceAccessPermission();
Irfan Sheriffdb831da2012-09-16 17:39:26 -0700558 int userId = UserHandle.getCallingUserId();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800559 int uid = Binder.getCallingUid();
Irfan Sheriffdb831da2012-09-16 17:39:26 -0700560 long ident = Binder.clearCallingIdentity();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800561 if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
562 != AppOpsManager.MODE_ALLOWED) {
563 return new ArrayList<ScanResult>();
564 }
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700565 try {
566 int currentUser = ActivityManager.getCurrentUser();
567 if (userId != currentUser) {
568 return new ArrayList<ScanResult>();
569 } else {
570 return mWifiStateMachine.syncGetScanResultsList();
571 }
572 } finally {
573 Binder.restoreCallingIdentity(ident);
Irfan Sheriff330b1872012-09-16 12:27:57 -0700574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 }
576
577 /**
578 * Tell the supplicant to persist the current list of configured networks.
579 * @return {@code true} if the operation succeeded
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700580 *
581 * TODO: deprecate this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 */
583 public boolean saveConfiguration() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700584 boolean result = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800586 if (mWifiStateMachineChannel != null) {
587 return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700588 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800589 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700590 return false;
591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592 }
593
594 /**
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700595 * Set the country code
596 * @param countryCode ISO 3166 country code.
Robert Greenwaltb5010cc2009-05-21 15:11:40 -0700597 * @param persist {@code true} if the setting should be remembered.
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700598 *
599 * The persist behavior exists so that wifi can fall back to the last
600 * persisted country code on a restart, when the locale information is
601 * not available from telephony.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 */
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700603 public void setCountryCode(String countryCode, boolean persist) {
604 Slog.i(TAG, "WifiService trying to set country code to " + countryCode +
605 " with persist set to " + persist);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 enforceChangePermission();
Robert Greenwalt304aad42013-05-31 17:57:10 -0700607 final long token = Binder.clearCallingIdentity();
608 try {
609 mWifiStateMachine.setCountryCode(countryCode, persist);
610 } finally {
611 Binder.restoreCallingIdentity(token);
612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 }
614
615 /**
Irfan Sheriff36f74132010-11-04 16:57:37 -0700616 * Set the operational frequency band
617 * @param band One of
618 * {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO},
619 * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ},
620 * {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ},
621 * @param persist {@code true} if the setting should be remembered.
622 *
623 */
624 public void setFrequencyBand(int band, boolean persist) {
625 enforceChangePermission();
626 if (!isDualBandSupported()) return;
627 Slog.i(TAG, "WifiService trying to set frequency band to " + band +
628 " with persist set to " + persist);
Robert Greenwalt304aad42013-05-31 17:57:10 -0700629 final long token = Binder.clearCallingIdentity();
630 try {
631 mWifiStateMachine.setFrequencyBand(band, persist);
632 } finally {
633 Binder.restoreCallingIdentity(token);
634 }
Irfan Sheriff36f74132010-11-04 16:57:37 -0700635 }
636
637
638 /**
639 * Get the operational frequency band
640 */
641 public int getFrequencyBand() {
642 enforceAccessPermission();
643 return mWifiStateMachine.getFrequencyBand();
644 }
645
646 public boolean isDualBandSupported() {
647 //TODO: Should move towards adding a driver API that checks at runtime
648 return mContext.getResources().getBoolean(
649 com.android.internal.R.bool.config_wifi_dual_band_support);
650 }
651
652 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 * Return the DHCP-assigned addresses from the last successful DHCP request,
654 * if any.
655 * @return the DHCP information
Robert Greenwalt4717c262012-10-31 14:32:53 -0700656 * @deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657 */
658 public DhcpInfo getDhcpInfo() {
659 enforceAccessPermission();
Robert Greenwalt4717c262012-10-31 14:32:53 -0700660 DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults();
661 if (dhcpResults.linkProperties == null) return null;
662
663 DhcpInfo info = new DhcpInfo();
664 for (LinkAddress la : dhcpResults.linkProperties.getLinkAddresses()) {
665 InetAddress addr = la.getAddress();
666 if (addr instanceof Inet4Address) {
667 info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address)addr);
668 break;
669 }
670 }
671 for (RouteInfo r : dhcpResults.linkProperties.getRoutes()) {
672 if (r.isDefaultRoute()) {
673 InetAddress gateway = r.getGateway();
674 if (gateway instanceof Inet4Address) {
675 info.gateway = NetworkUtils.inetAddressToInt((Inet4Address)gateway);
676 }
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700677 } else if (r.hasGateway() == false) {
Robert Greenwalt4717c262012-10-31 14:32:53 -0700678 LinkAddress dest = r.getDestination();
679 if (dest.getAddress() instanceof Inet4Address) {
680 info.netmask = NetworkUtils.prefixLengthToNetmaskInt(
681 dest.getNetworkPrefixLength());
682 }
683 }
684 }
685 int dnsFound = 0;
686 for (InetAddress dns : dhcpResults.linkProperties.getDnses()) {
687 if (dns instanceof Inet4Address) {
688 if (dnsFound == 0) {
689 info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns);
690 } else {
691 info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns);
692 }
693 if (++dnsFound > 1) break;
694 }
695 }
696 InetAddress serverAddress = dhcpResults.serverAddress;
697 if (serverAddress instanceof Inet4Address) {
698 info.serverAddress = NetworkUtils.inetAddressToInt((Inet4Address)serverAddress);
699 }
700 info.leaseDuration = dhcpResults.leaseDuration;
701
702 return info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 }
704
Irfan Sheriff0d255342010-07-28 09:35:20 -0700705 /**
706 * see {@link android.net.wifi.WifiManager#startWifi}
707 *
708 */
709 public void startWifi() {
Irfan Sheriffda6da092012-08-16 12:49:23 -0700710 enforceConnectivityInternalPermission();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700711 /* TODO: may be add permissions for access only to connectivity service
712 * TODO: if a start issued, keep wifi alive until a stop issued irrespective
713 * of WifiLock & device idle status unless wifi enabled status is toggled
714 */
715
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800716 mWifiStateMachine.setDriverStart(true);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700717 mWifiStateMachine.reconnectCommand();
718 }
719
Irfan Sheriffda6da092012-08-16 12:49:23 -0700720 public void captivePortalCheckComplete() {
721 enforceConnectivityInternalPermission();
722 mWifiStateMachine.captivePortalCheckComplete();
723 }
724
Irfan Sheriff0d255342010-07-28 09:35:20 -0700725 /**
726 * see {@link android.net.wifi.WifiManager#stopWifi}
727 *
728 */
729 public void stopWifi() {
Irfan Sheriffda6da092012-08-16 12:49:23 -0700730 enforceConnectivityInternalPermission();
731 /*
Irfan Sheriff0d255342010-07-28 09:35:20 -0700732 * TODO: if a stop is issued, wifi is brought up only by startWifi
733 * unless wifi enabled status is toggled
734 */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800735 mWifiStateMachine.setDriverStart(false);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700736 }
737
Irfan Sheriff0d255342010-07-28 09:35:20 -0700738 /**
739 * see {@link android.net.wifi.WifiManager#addToBlacklist}
740 *
741 */
742 public void addToBlacklist(String bssid) {
743 enforceChangePermission();
744
745 mWifiStateMachine.addToBlacklist(bssid);
746 }
747
748 /**
749 * see {@link android.net.wifi.WifiManager#clearBlacklist}
750 *
751 */
752 public void clearBlacklist() {
753 enforceChangePermission();
754
755 mWifiStateMachine.clearBlacklist();
756 }
757
Irfan Sheriff227bec42011-02-15 19:30:27 -0800758 /**
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -0700759 * enable TDLS for the local NIC to remote NIC
760 * The APPs don't know the remote MAC address to identify NIC though,
761 * so we need to do additional work to find it from remote IP address
762 */
763
764 class TdlsTaskParams {
765 public String remoteIpAddress;
766 public boolean enable;
767 }
768
769 class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> {
770 @Override
771 protected Integer doInBackground(TdlsTaskParams... params) {
772
773 // Retrieve parameters for the call
774 TdlsTaskParams param = params[0];
775 String remoteIpAddress = param.remoteIpAddress.trim();
776 boolean enable = param.enable;
777
778 // Get MAC address of Remote IP
779 String macAddress = null;
780
781 BufferedReader reader = null;
782
783 try {
784 reader = new BufferedReader(new FileReader("/proc/net/arp"));
785
786 // Skip over the line bearing colum titles
787 String line = reader.readLine();
788
789 while ((line = reader.readLine()) != null) {
790 String[] tokens = line.split("[ ]+");
791 if (tokens.length < 6) {
792 continue;
793 }
794
795 // ARP column format is
796 // Address HWType HWAddress Flags Mask IFace
797 String ip = tokens[0];
798 String mac = tokens[3];
799
800 if (remoteIpAddress.equals(ip)) {
801 macAddress = mac;
802 break;
803 }
804 }
805
806 if (macAddress == null) {
807 Slog.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " +
808 "/proc/net/arp");
809 } else {
810 enableTdlsWithMacAddress(macAddress, enable);
811 }
812
813 } catch (FileNotFoundException e) {
814 Slog.e(TAG, "Could not open /proc/net/arp to lookup mac address");
815 } catch (IOException e) {
816 Slog.e(TAG, "Could not read /proc/net/arp to lookup mac address");
817 } finally {
818 try {
819 if (reader != null) {
820 reader.close();
821 }
822 }
823 catch (IOException e) {
824 // Do nothing
825 }
826 }
827
828 return 0;
829 }
830 }
831
832 public void enableTdls(String remoteAddress, boolean enable) {
833 TdlsTaskParams params = new TdlsTaskParams();
834 params.remoteIpAddress = remoteAddress;
835 params.enable = enable;
836 new TdlsTask().execute(params);
837 }
838
839
840 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) {
841 mWifiStateMachine.enableTdls(remoteMacAddress, enable);
842 }
843
844 /**
Irfan Sheriff227bec42011-02-15 19:30:27 -0800845 * Get a reference to handler. This is used by a client to establish
846 * an AsyncChannel communication with WifiService
847 */
Irfan Sheriff07573b32012-01-27 21:00:19 -0800848 public Messenger getWifiServiceMessenger() {
Irfan Sheriff35bbe272012-08-23 16:57:43 -0700849 enforceAccessPermission();
850 enforceChangePermission();
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800851 return new Messenger(mClientHandler);
Irfan Sheriff227bec42011-02-15 19:30:27 -0800852 }
853
Irfan Sheriff07573b32012-01-27 21:00:19 -0800854 /** Get a reference to WifiStateMachine handler for AsyncChannel communication */
855 public Messenger getWifiStateMachineMessenger() {
856 enforceAccessPermission();
857 enforceChangePermission();
858 return mWifiStateMachine.getMessenger();
859 }
860
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800861 /**
862 * Get the IP and proxy configuration file
863 */
864 public String getConfigFile() {
865 enforceAccessPermission();
866 return mWifiStateMachine.getConfigFile();
867 }
868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
870 @Override
871 public void onReceive(Context context, Intent intent) {
872 String action = intent.getAction();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 if (action.equals(Intent.ACTION_SCREEN_ON)) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800874 mWifiController.sendMessage(CMD_SCREEN_ON);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800876 mWifiController.sendMessage(CMD_SCREEN_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 int pluggedType = intent.getIntExtra("plugged", 0);
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800879 mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null);
Irfan Sheriff65eaec82011-01-05 22:00:16 -0800880 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
881 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
882 BluetoothAdapter.STATE_DISCONNECTED);
883 mWifiStateMachine.sendBluetoothAdapterStateChange(state);
Irfan Sheriff616f3172011-09-11 19:59:01 -0700884 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800885 boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);
886 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 };
890
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800891 /**
892 * Observes settings changes to scan always mode.
893 */
894 private void registerForScanModeChange() {
895 ContentObserver contentObserver = new ContentObserver(null) {
896 @Override
897 public void onChange(boolean selfChange) {
898 mSettingsStore.handleWifiScanAlwaysAvailableToggled();
899 mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED);
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700900 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800901 };
Jaikumar Ganesh7440fc22010-09-27 17:04:14 -0700902
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800903 mContext.getContentResolver().registerContentObserver(
904 Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE),
905 false, contentObserver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 }
907
908 private void registerForBroadcasts() {
909 IntentFilter intentFilter = new IntentFilter();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
911 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
912 intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800913 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
Irfan Sheriff65eaec82011-01-05 22:00:16 -0800914 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
Irfan Sheriff616f3172011-09-11 19:59:01 -0700915 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 mContext.registerReceiver(mReceiver, intentFilter);
917 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 @Override
920 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
921 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
922 != PackageManager.PERMISSION_GRANTED) {
923 pw.println("Permission Denial: can't dump WifiService from from pid="
924 + Binder.getCallingPid()
925 + ", uid=" + Binder.getCallingUid());
926 return;
927 }
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700928 pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 pw.println("Stay-awake conditions: " +
Christopher Tatec09cdce2012-09-10 16:50:14 -0700930 Settings.Global.getInt(mContext.getContentResolver(),
931 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0));
Irfan Sherifff0afe412012-11-30 14:07:44 -0800932 pw.println("mMulticastEnabled " + mMulticastEnabled);
933 pw.println("mMulticastDisabled " + mMulticastDisabled);
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800934 mWifiController.dump(fd, pw, args);
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800935 mSettingsStore.dump(fd, pw, args);
936 mNotificationController.dump(fd, pw, args);
937 mTrafficPoller.dump(fd, pw, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 pw.println("Latest scan results:");
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700940 List<ScanResult> scanResults = mWifiStateMachine.syncGetScanResultsList();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 if (scanResults != null && scanResults.size() != 0) {
942 pw.println(" BSSID Frequency RSSI Flags SSID");
943 for (ScanResult r : scanResults) {
944 pw.printf(" %17s %9d %5d %-16s %s%n",
945 r.BSSID,
946 r.frequency,
947 r.level,
948 r.capabilities,
949 r.SSID == null ? "" : r.SSID);
950 }
951 }
952 pw.println();
Eric Shienbrood5711fad2009-03-27 20:25:31 -0700953 pw.println("Locks acquired: " + mFullLocksAcquired + " full, " +
Irfan Sheriff5876a422010-08-12 20:26:23 -0700954 mFullHighPerfLocksAcquired + " full high perf, " +
Eric Shienbrood5711fad2009-03-27 20:25:31 -0700955 mScanLocksAcquired + " scan");
956 pw.println("Locks released: " + mFullLocksReleased + " full, " +
Irfan Sheriff5876a422010-08-12 20:26:23 -0700957 mFullHighPerfLocksReleased + " full high perf, " +
Eric Shienbrood5711fad2009-03-27 20:25:31 -0700958 mScanLocksReleased + " scan");
959 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 pw.println("Locks held:");
961 mLocks.dump(pw);
Isaac Levybc7dfb52011-06-06 15:34:01 -0700962
Irfan Sherifff0afe412012-11-30 14:07:44 -0800963 mWifiWatchdogStateMachine.dump(fd, pw, args);
Isaac Levybc7dfb52011-06-06 15:34:01 -0700964 pw.println();
Irfan Sheriff60792372012-04-16 16:47:10 -0700965 mWifiStateMachine.dump(fd, pw, args);
Irfan Sherifff0afe412012-11-30 14:07:44 -0800966 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 }
968
Robert Greenwalt58ff0212009-05-19 15:53:54 -0700969 private class WifiLock extends DeathRecipient {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700970 WifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) {
971 super(lockMode, tag, binder, ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 }
973
974 public void binderDied() {
975 synchronized (mLocks) {
976 releaseWifiLockLocked(mBinder);
977 }
978 }
979
980 public String toString() {
Robert Greenwalt5347bd42009-05-13 15:10:16 -0700981 return "WifiLock{" + mTag + " type=" + mMode + " binder=" + mBinder + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 }
983 }
984
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800985 class LockList {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 private List<WifiLock> mList;
987
988 private LockList() {
989 mList = new ArrayList<WifiLock>();
990 }
991
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800992 synchronized boolean hasLocks() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 return !mList.isEmpty();
994 }
995
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800996 synchronized int getStrongestLockMode() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 if (mList.isEmpty()) {
998 return WifiManager.WIFI_MODE_FULL;
999 }
Irfan Sheriff5876a422010-08-12 20:26:23 -07001000
1001 if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) {
1002 return WifiManager.WIFI_MODE_FULL_HIGH_PERF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 }
Irfan Sheriff5876a422010-08-12 20:26:23 -07001004
1005 if (mFullLocksAcquired > mFullLocksReleased) {
1006 return WifiManager.WIFI_MODE_FULL;
1007 }
1008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 return WifiManager.WIFI_MODE_SCAN_ONLY;
1010 }
1011
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001012 synchronized void updateWorkSource(WorkSource ws) {
1013 for (int i = 0; i < mLocks.mList.size(); i++) {
1014 ws.add(mLocks.mList.get(i).mWorkSource);
1015 }
1016 }
1017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 private void addLock(WifiLock lock) {
1019 if (findLockByBinder(lock.mBinder) < 0) {
1020 mList.add(lock);
1021 }
1022 }
1023
1024 private WifiLock removeLock(IBinder binder) {
1025 int index = findLockByBinder(binder);
1026 if (index >= 0) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001027 WifiLock ret = mList.remove(index);
1028 ret.unlinkDeathRecipient();
1029 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 } else {
1031 return null;
1032 }
1033 }
1034
1035 private int findLockByBinder(IBinder binder) {
1036 int size = mList.size();
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001037 for (int i = size - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 if (mList.get(i).mBinder == binder)
1039 return i;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 return -1;
1042 }
1043
1044 private void dump(PrintWriter pw) {
1045 for (WifiLock l : mList) {
1046 pw.print(" ");
1047 pw.println(l);
1048 }
1049 }
1050 }
1051
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001052 void enforceWakeSourcePermission(int uid, int pid) {
Dianne Hackborne746f032010-09-13 16:02:57 -07001053 if (uid == android.os.Process.myUid()) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001054 return;
1055 }
1056 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
1057 pid, uid, null);
1058 }
1059
1060 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
Irfan Sheriff5876a422010-08-12 20:26:23 -07001062 if (lockMode != WifiManager.WIFI_MODE_FULL &&
1063 lockMode != WifiManager.WIFI_MODE_SCAN_ONLY &&
1064 lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF) {
1065 Slog.e(TAG, "Illegal argument, lockMode= " + lockMode);
1066 if (DBG) throw new IllegalArgumentException("lockMode=" + lockMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 return false;
1068 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001069 if (ws != null && ws.size() == 0) {
1070 ws = null;
1071 }
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001072 if (ws != null) {
1073 enforceWakeSourcePermission(Binder.getCallingUid(), Binder.getCallingPid());
1074 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001075 if (ws == null) {
1076 ws = new WorkSource(Binder.getCallingUid());
1077 }
1078 WifiLock wifiLock = new WifiLock(lockMode, tag, binder, ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 synchronized (mLocks) {
1080 return acquireWifiLockLocked(wifiLock);
1081 }
1082 }
1083
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001084 private void noteAcquireWifiLock(WifiLock wifiLock) throws RemoteException {
1085 switch(wifiLock.mMode) {
1086 case WifiManager.WIFI_MODE_FULL:
Irfan Sheriff5876a422010-08-12 20:26:23 -07001087 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001088 case WifiManager.WIFI_MODE_SCAN_ONLY:
Nick Pelly6ccaa542012-06-15 15:22:47 -07001089 mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001090 break;
1091 }
1092 }
1093
1094 private void noteReleaseWifiLock(WifiLock wifiLock) throws RemoteException {
1095 switch(wifiLock.mMode) {
1096 case WifiManager.WIFI_MODE_FULL:
Irfan Sheriff5876a422010-08-12 20:26:23 -07001097 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001098 case WifiManager.WIFI_MODE_SCAN_ONLY:
Nick Pelly6ccaa542012-06-15 15:22:47 -07001099 mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001100 break;
1101 }
1102 }
1103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 private boolean acquireWifiLockLocked(WifiLock wifiLock) {
Irfan Sheriffc89dd542010-09-28 08:40:54 -07001105 if (DBG) Slog.d(TAG, "acquireWifiLockLocked: " + wifiLock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 mLocks.addLock(wifiLock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001108
The Android Open Source Project10592532009-03-18 17:39:46 -07001109 long ident = Binder.clearCallingIdentity();
1110 try {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001111 noteAcquireWifiLock(wifiLock);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001112 switch(wifiLock.mMode) {
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001113 case WifiManager.WIFI_MODE_FULL:
1114 ++mFullLocksAcquired;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001115 break;
Irfan Sheriff5876a422010-08-12 20:26:23 -07001116 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
1117 ++mFullHighPerfLocksAcquired;
1118 break;
1119
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001120 case WifiManager.WIFI_MODE_SCAN_ONLY:
1121 ++mScanLocksAcquired;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001122 break;
The Android Open Source Project10592532009-03-18 17:39:46 -07001123 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001124 mWifiController.sendMessage(CMD_LOCKS_CHANGED);
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001125 return true;
The Android Open Source Project10592532009-03-18 17:39:46 -07001126 } catch (RemoteException e) {
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001127 return false;
The Android Open Source Project10592532009-03-18 17:39:46 -07001128 } finally {
1129 Binder.restoreCallingIdentity(ident);
1130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 }
1132
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001133 public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) {
1134 int uid = Binder.getCallingUid();
1135 int pid = Binder.getCallingPid();
1136 if (ws != null && ws.size() == 0) {
1137 ws = null;
1138 }
1139 if (ws != null) {
1140 enforceWakeSourcePermission(uid, pid);
1141 }
1142 long ident = Binder.clearCallingIdentity();
1143 try {
1144 synchronized (mLocks) {
1145 int index = mLocks.findLockByBinder(lock);
1146 if (index < 0) {
1147 throw new IllegalArgumentException("Wifi lock not active");
1148 }
1149 WifiLock wl = mLocks.mList.get(index);
1150 noteReleaseWifiLock(wl);
1151 wl.mWorkSource = ws != null ? new WorkSource(ws) : new WorkSource(uid);
1152 noteAcquireWifiLock(wl);
1153 }
1154 } catch (RemoteException e) {
1155 } finally {
1156 Binder.restoreCallingIdentity(ident);
1157 }
1158 }
1159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 public boolean releaseWifiLock(IBinder lock) {
1161 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
1162 synchronized (mLocks) {
1163 return releaseWifiLockLocked(lock);
1164 }
1165 }
1166
1167 private boolean releaseWifiLockLocked(IBinder lock) {
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001168 boolean hadLock;
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001169
The Android Open Source Project10592532009-03-18 17:39:46 -07001170 WifiLock wifiLock = mLocks.removeLock(lock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001171
Irfan Sheriffc89dd542010-09-28 08:40:54 -07001172 if (DBG) Slog.d(TAG, "releaseWifiLockLocked: " + wifiLock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001173
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001174 hadLock = (wifiLock != null);
1175
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001176 long ident = Binder.clearCallingIdentity();
1177 try {
1178 if (hadLock) {
Wink Savillece0ea1f2011-10-13 16:55:20 -07001179 noteReleaseWifiLock(wifiLock);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001180 switch(wifiLock.mMode) {
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001181 case WifiManager.WIFI_MODE_FULL:
1182 ++mFullLocksReleased;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001183 break;
Irfan Sheriff5876a422010-08-12 20:26:23 -07001184 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
1185 ++mFullHighPerfLocksReleased;
1186 break;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001187 case WifiManager.WIFI_MODE_SCAN_ONLY:
1188 ++mScanLocksReleased;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001189 break;
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001190 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001191 mWifiController.sendMessage(CMD_LOCKS_CHANGED);
The Android Open Source Project10592532009-03-18 17:39:46 -07001192 }
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001193 } catch (RemoteException e) {
1194 } finally {
1195 Binder.restoreCallingIdentity(ident);
The Android Open Source Project10592532009-03-18 17:39:46 -07001196 }
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001197
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001198 return hadLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 }
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001200
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001201 private abstract class DeathRecipient
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001202 implements IBinder.DeathRecipient {
1203 String mTag;
1204 int mMode;
1205 IBinder mBinder;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001206 WorkSource mWorkSource;
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001207
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001208 DeathRecipient(int mode, String tag, IBinder binder, WorkSource ws) {
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001209 super();
1210 mTag = tag;
1211 mMode = mode;
1212 mBinder = binder;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001213 mWorkSource = ws;
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001214 try {
1215 mBinder.linkToDeath(this, 0);
1216 } catch (RemoteException e) {
1217 binderDied();
1218 }
1219 }
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001220
1221 void unlinkDeathRecipient() {
1222 mBinder.unlinkToDeath(this, 0);
1223 }
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001224 }
1225
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001226 private class Multicaster extends DeathRecipient {
1227 Multicaster(String tag, IBinder binder) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001228 super(Binder.getCallingUid(), tag, binder, null);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001229 }
1230
1231 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001232 Slog.e(TAG, "Multicaster binderDied");
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001233 synchronized (mMulticasters) {
1234 int i = mMulticasters.indexOf(this);
1235 if (i != -1) {
1236 removeMulticasterLocked(i, mMode);
1237 }
1238 }
1239 }
1240
1241 public String toString() {
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001242 return "Multicaster{" + mTag + " binder=" + mBinder + "}";
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001243 }
1244
1245 public int getUid() {
1246 return mMode;
1247 }
1248 }
1249
Robert Greenwalte2d155a2009-10-21 14:58:34 -07001250 public void initializeMulticastFiltering() {
1251 enforceMulticastChangePermission();
Irfan Sheriffa8fbe1f2010-03-09 09:13:58 -08001252
Robert Greenwalte2d155a2009-10-21 14:58:34 -07001253 synchronized (mMulticasters) {
1254 // if anybody had requested filters be off, leave off
1255 if (mMulticasters.size() != 0) {
1256 return;
1257 } else {
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001258 mWifiStateMachine.startFilteringMulticastV4Packets();
Robert Greenwalte2d155a2009-10-21 14:58:34 -07001259 }
1260 }
1261 }
1262
Robert Greenwaltfc1b15c2009-05-22 15:09:51 -07001263 public void acquireMulticastLock(IBinder binder, String tag) {
1264 enforceMulticastChangePermission();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001265
1266 synchronized (mMulticasters) {
1267 mMulticastEnabled++;
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001268 mMulticasters.add(new Multicaster(tag, binder));
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001269 // Note that we could call stopFilteringMulticastV4Packets only when
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001270 // our new size == 1 (first call), but this function won't
1271 // be called often and by making the stopPacket call each
1272 // time we're less fragile and self-healing.
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001273 mWifiStateMachine.stopFilteringMulticastV4Packets();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001274 }
1275
1276 int uid = Binder.getCallingUid();
You Kim2bea5852012-10-23 22:56:51 +09001277 final long ident = Binder.clearCallingIdentity();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001278 try {
1279 mBatteryStats.noteWifiMulticastEnabled(uid);
1280 } catch (RemoteException e) {
1281 } finally {
1282 Binder.restoreCallingIdentity(ident);
1283 }
1284 }
1285
Robert Greenwaltfc1b15c2009-05-22 15:09:51 -07001286 public void releaseMulticastLock() {
1287 enforceMulticastChangePermission();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001288
1289 int uid = Binder.getCallingUid();
1290 synchronized (mMulticasters) {
1291 mMulticastDisabled++;
1292 int size = mMulticasters.size();
1293 for (int i = size - 1; i >= 0; i--) {
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001294 Multicaster m = mMulticasters.get(i);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001295 if ((m != null) && (m.getUid() == uid)) {
1296 removeMulticasterLocked(i, uid);
1297 }
1298 }
1299 }
1300 }
1301
1302 private void removeMulticasterLocked(int i, int uid)
1303 {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001304 Multicaster removed = mMulticasters.remove(i);
Irfan Sheriffa8fbe1f2010-03-09 09:13:58 -08001305
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001306 if (removed != null) {
1307 removed.unlinkDeathRecipient();
1308 }
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001309 if (mMulticasters.size() == 0) {
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001310 mWifiStateMachine.startFilteringMulticastV4Packets();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001311 }
1312
You Kim2bea5852012-10-23 22:56:51 +09001313 final long ident = Binder.clearCallingIdentity();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001314 try {
1315 mBatteryStats.noteWifiMulticastDisabled(uid);
1316 } catch (RemoteException e) {
1317 } finally {
1318 Binder.restoreCallingIdentity(ident);
1319 }
1320 }
1321
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001322 public boolean isMulticastEnabled() {
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001323 enforceAccessPermission();
1324
1325 synchronized (mMulticasters) {
1326 return (mMulticasters.size() > 0);
1327 }
1328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329}