blob: a70978ee6c4b585eb201a6409ee1a0593b6e4e15 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.provider.Settings;
Nick Pelly6ccaa542012-06-15 15:22:47 -070052import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080053import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
Irfan Sherifff0afe412012-11-30 14:07:44 -080055import java.io.FileDescriptor;
56import java.io.PrintWriter;
Robert Greenwalt4717c262012-10-31 14:32:53 -070057import java.net.InetAddress;
58import java.net.Inet4Address;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import java.util.ArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import java.util.List;
Irfan Sheriff07a22952013-03-27 13:27:39 -070061import java.util.concurrent.atomic.AtomicBoolean;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062
Irfan Sheriff11aefad2013-03-06 07:57:41 -080063import com.android.internal.R;
The Android Open Source Project10592532009-03-18 17:39:46 -070064import com.android.internal.app.IBatteryStats;
Irfan Sheriff616f3172011-09-11 19:59:01 -070065import com.android.internal.telephony.TelephonyIntents;
Wink Saville4b7ba092010-10-20 15:37:41 -070066import com.android.internal.util.AsyncChannel;
The Android Open Source Project10592532009-03-18 17:39:46 -070067import com.android.server.am.BatteryStatsService;
Irfan Sheriff11aefad2013-03-06 07:57:41 -080068import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED;
69import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED;
70import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED;
71import static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED;
72import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED;
73import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF;
74import static com.android.server.wifi.WifiController.CMD_SCREEN_ON;
75import static com.android.server.wifi.WifiController.CMD_SET_AP;
76import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077/**
78 * WifiService handles remote WiFi operation requests by implementing
Irfan Sheriffa2a1b912010-06-07 09:03:04 -070079 * the IWifiManager interface.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 *
81 * @hide
82 */
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080083public final class WifiService extends IWifiManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 private static final String TAG = "WifiService";
Dianne Hackborn5fd21692011-06-07 14:09:47 -070085 private static final boolean DBG = false;
Irfan Sheriffa2a1b912010-06-07 09:03:04 -070086
Irfan Sheriff11aefad2013-03-06 07:57:41 -080087 final WifiStateMachine mWifiStateMachine;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080089 private final Context mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090
Irfan Sheriff11aefad2013-03-06 07:57:41 -080091 final LockList mLocks = new LockList();
Eric Shienbrood5711fad2009-03-27 20:25:31 -070092 // some wifi lock statistics
Irfan Sheriff5876a422010-08-12 20:26:23 -070093 private int mFullHighPerfLocksAcquired;
94 private int mFullHighPerfLocksReleased;
Eric Shienbrood5711fad2009-03-27 20:25:31 -070095 private int mFullLocksAcquired;
96 private int mFullLocksReleased;
97 private int mScanLocksAcquired;
98 private int mScanLocksReleased;
The Android Open Source Project10592532009-03-18 17:39:46 -070099
Robert Greenwalt58ff0212009-05-19 15:53:54 -0700100 private final List<Multicaster> mMulticasters =
101 new ArrayList<Multicaster>();
Robert Greenwalt5347bd42009-05-13 15:10:16 -0700102 private int mMulticastEnabled;
103 private int mMulticastDisabled;
104
The Android Open Source Project10592532009-03-18 17:39:46 -0700105 private final IBatteryStats mBatteryStats;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800106 private final AppOpsManager mAppOps;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800107
Irfan Sheriff227bec42011-02-15 19:30:27 -0800108 private String mInterfaceName;
109
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800110 /* Tracks the open wi-fi network notification */
111 private WifiNotificationController mNotificationController;
112 /* Polls traffic stats and notifies clients */
113 private WifiTrafficPoller mTrafficPoller;
114 /* Tracks the persisted states for wi-fi & airplane mode */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800115 final WifiSettingsStore mSettingsStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116
Dianne Hackborn03f3cb02010-09-17 23:12:26 -0700117 /**
Wink Saville4b7ba092010-10-20 15:37:41 -0700118 * Asynchronous channel to WifiStateMachine
119 */
Irfan Sheriff227bec42011-02-15 19:30:27 -0800120 private AsyncChannel mWifiStateMachineChannel;
Wink Saville4b7ba092010-10-20 15:37:41 -0700121
122 /**
Irfan Sheriff227bec42011-02-15 19:30:27 -0800123 * Handles client connections
124 */
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800125 private class ClientHandler extends Handler {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800126
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800127 ClientHandler(android.os.Looper looper) {
Wink Saville4b7ba092010-10-20 15:37:41 -0700128 super(looper);
Wink Saville4b7ba092010-10-20 15:37:41 -0700129 }
130
131 @Override
132 public void handleMessage(Message msg) {
133 switch (msg.what) {
134 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
135 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
Irfan Sheriff6bfc8882012-08-29 15:35:57 -0700136 if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
Irfan Sheriff302b06d2013-02-22 12:35:31 -0800137 // We track the clients by the Messenger
138 // since it is expected to be always available
Irfan Sheriffc808a192013-03-05 09:46:36 -0800139 mTrafficPoller.addClient(msg.replyTo);
Wink Saville4b7ba092010-10-20 15:37:41 -0700140 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800141 Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
142 }
143 break;
144 }
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800145 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
146 if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
Irfan Sheriff6bfc8882012-08-29 15:35:57 -0700147 if (DBG) Slog.d(TAG, "Send failed, client connection lost");
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800148 } else {
Irfan Sheriff6bfc8882012-08-29 15:35:57 -0700149 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800150 }
Irfan Sheriffc808a192013-03-05 09:46:36 -0800151 mTrafficPoller.removeClient(msg.replyTo);
Irfan Sheriffc23971b2011-03-04 17:06:31 -0800152 break;
153 }
Irfan Sheriff227bec42011-02-15 19:30:27 -0800154 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
155 AsyncChannel ac = new AsyncChannel();
156 ac.connect(mContext, this, msg.replyTo);
157 break;
158 }
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800159 /* Client commands are forwarded to state machine */
160 case WifiManager.CONNECT_NETWORK:
161 case WifiManager.SAVE_NETWORK:
162 case WifiManager.FORGET_NETWORK:
163 case WifiManager.START_WPS:
164 case WifiManager.CANCEL_WPS:
165 case WifiManager.DISABLE_NETWORK:
Yuhao Zhengf6307822012-08-14 14:21:25 -0700166 case WifiManager.RSSI_PKTCNT_FETCH: {
167 mWifiStateMachine.sendMessage(Message.obtain(msg));
168 break;
169 }
Wink Saville4b7ba092010-10-20 15:37:41 -0700170 default: {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800171 Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg);
Wink Saville4b7ba092010-10-20 15:37:41 -0700172 break;
173 }
174 }
175 }
176 }
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800177 private ClientHandler mClientHandler;
Irfan Sheriff227bec42011-02-15 19:30:27 -0800178
179 /**
180 * Handles interaction with WifiStateMachine
181 */
182 private class WifiStateMachineHandler extends Handler {
183 private AsyncChannel mWsmChannel;
184
185 WifiStateMachineHandler(android.os.Looper looper) {
186 super(looper);
187 mWsmChannel = new AsyncChannel();
188 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
189 }
190
191 @Override
192 public void handleMessage(Message msg) {
193 switch (msg.what) {
194 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
195 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
196 mWifiStateMachineChannel = mWsmChannel;
197 } else {
198 Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1);
199 mWifiStateMachineChannel = null;
200 }
201 break;
202 }
Irfan Sheriff6da83d52011-06-06 12:54:06 -0700203 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
204 Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1);
205 mWifiStateMachineChannel = null;
206 //Re-establish connection to state machine
207 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
208 break;
209 }
Irfan Sheriff227bec42011-02-15 19:30:27 -0800210 default: {
211 Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg);
212 break;
213 }
214 }
215 }
216 }
217 WifiStateMachineHandler mWifiStateMachineHandler;
Wink Saville4b7ba092010-10-20 15:37:41 -0700218
Isaac Levy654f5092011-07-13 17:41:45 -0700219 private WifiWatchdogStateMachine mWifiWatchdogStateMachine;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700220
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800221 public WifiService(Context context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 mContext = context;
Irfan Sheriff227bec42011-02-15 19:30:27 -0800223
224 mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
225
226 mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700227 mWifiStateMachine.enableRssiPolling(true);
The Android Open Source Project10592532009-03-18 17:39:46 -0700228 mBatteryStats = BatteryStatsService.getService();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800229 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800230
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800231 mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
Irfan Sheriffc808a192013-03-05 09:46:36 -0800232 mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800233 mSettingsStore = new WifiSettingsStore(mContext);
234
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800235 HandlerThread wifiThread = new HandlerThread("WifiService");
236 wifiThread.start();
237 mClientHandler = new ClientHandler(wifiThread.getLooper());
238 mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
239 mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
240 mWifiController.start();
241
242 registerForScanModeChange();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 mContext.registerReceiver(
244 new BroadcastReceiver() {
245 @Override
246 public void onReceive(Context context, Intent intent) {
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800247 if (mSettingsStore.handleAirplaneModeToggled()) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800248 mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 }
251 },
252 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
253
Irfan Sheriffe68d8582013-04-23 13:43:43 -0700254 // Adding optimizations of only receiving broadcasts when wifi is enabled
255 // can result in race conditions when apps toggle wifi in the background
256 // without active user involvement. Always receive broadcasts.
257 registerForBroadcasts();
Irfan Sheriff7b009782010-03-11 16:37:45 -0800258 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800259
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800260 private WifiController mWifiController;
261
Irfan Sheriff7b009782010-03-11 16:37:45 -0800262 /**
263 * Check if Wi-Fi needs to be enabled and start
264 * if needed
Irfan Sheriff60e3ba02010-04-02 12:18:45 -0700265 *
266 * This function is used only at boot time
Irfan Sheriff7b009782010-03-11 16:37:45 -0800267 */
Irfan Sheriff0d255342010-07-28 09:35:20 -0700268 public void checkAndStartWifi() {
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800269 /* Check if wi-fi needs to be enabled */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800270 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
Irfan Sheriff7b009782010-03-11 16:37:45 -0800271 Slog.i(TAG, "WifiService starting up with Wi-Fi " +
272 (wifiEnabled ? "enabled" : "disabled"));
Irfan Sherifff03d6202012-05-17 12:33:46 -0700273
274 // If we are already disabled (could be due to airplane mode), avoid changing persist
275 // state here
276 if (wifiEnabled) setWifiEnabled(wifiEnabled);
Isaac Levybc7dfb52011-06-06 15:34:01 -0700277
Isaac Levy654f5092011-07-13 17:41:45 -0700278 mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
279 makeWifiWatchdogStateMachine(mContext);
280
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800281 }
282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 /**
284 * see {@link android.net.wifi.WifiManager#pingSupplicant()}
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700285 * @return {@code true} if the operation succeeds, {@code false} otherwise
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 */
287 public boolean pingSupplicant() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700288 enforceAccessPermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800289 if (mWifiStateMachineChannel != null) {
290 return mWifiStateMachine.syncPingSupplicant(mWifiStateMachineChannel);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700291 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800292 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700293 return false;
294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 }
296
297 /**
298 * see {@link android.net.wifi.WifiManager#startScan()}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 */
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -0800300 public void startScan() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 enforceChangePermission();
Robert Greenwalt89710842013-06-25 11:41:53 -0700302 mWifiStateMachine.startScan(Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 }
304
305 private void enforceAccessPermission() {
306 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
307 "WifiService");
308 }
309
310 private void enforceChangePermission() {
311 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
312 "WifiService");
313
314 }
315
Robert Greenwaltfc1b15c2009-05-22 15:09:51 -0700316 private void enforceMulticastChangePermission() {
317 mContext.enforceCallingOrSelfPermission(
318 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
319 "WifiService");
320 }
321
Irfan Sheriffda6da092012-08-16 12:49:23 -0700322 private void enforceConnectivityInternalPermission() {
323 mContext.enforceCallingOrSelfPermission(
324 android.Manifest.permission.CONNECTIVITY_INTERNAL,
325 "ConnectivityService");
326 }
327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 /**
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700329 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
330 * @param enable {@code true} to enable, {@code false} to disable.
331 * @return {@code true} if the enable/disable operation was
332 * started or is already in the queue.
333 */
334 public synchronized boolean setWifiEnabled(boolean enable) {
335 enforceChangePermission();
Irfan Sheriffbd21b782012-05-16 13:13:54 -0700336 Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
337 + ", uid=" + Binder.getCallingUid());
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700338 if (DBG) {
Irfan Sheriff0d255342010-07-28 09:35:20 -0700339 Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700340 }
341
Irfan Sheriff61180692010-08-18 16:07:39 -0700342 /*
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800343 * Caller might not have WRITE_SECURE_SETTINGS,
344 * only CHANGE_WIFI_STATE is enforced
345 */
Irfan Sheriff5401f0b2011-12-07 16:27:49 -0800346
Irfan Sherifff03d6202012-05-17 12:33:46 -0700347 long ident = Binder.clearCallingIdentity();
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700348 try {
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800349 if (! mSettingsStore.handleWifiToggled(enable)) {
350 // Nothing to do if wifi cannot be toggled
351 return true;
352 }
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700353 } finally {
354 Binder.restoreCallingIdentity(ident);
355 }
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700356
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800357 mWifiController.sendMessage(CMD_WIFI_TOGGLED);
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700358 return true;
359 }
360
361 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 * see {@link WifiManager#getWifiState()}
363 * @return One of {@link WifiManager#WIFI_STATE_DISABLED},
364 * {@link WifiManager#WIFI_STATE_DISABLING},
365 * {@link WifiManager#WIFI_STATE_ENABLED},
366 * {@link WifiManager#WIFI_STATE_ENABLING},
367 * {@link WifiManager#WIFI_STATE_UNKNOWN}
368 */
369 public int getWifiEnabledState() {
370 enforceAccessPermission();
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700371 return mWifiStateMachine.syncGetWifiState();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 }
373
374 /**
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700375 * see {@link android.net.wifi.WifiManager#setWifiApEnabled(WifiConfiguration, boolean)}
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800376 * @param wifiConfig SSID, security and channel details as
377 * part of WifiConfiguration
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700378 * @param enabled true to enable and false to disable
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800379 */
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700380 public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800381 enforceChangePermission();
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800382 mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig).sendToTarget();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800383 }
384
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700385 /**
386 * see {@link WifiManager#getWifiApState()}
387 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED},
388 * {@link WifiManager#WIFI_AP_STATE_DISABLING},
389 * {@link WifiManager#WIFI_AP_STATE_ENABLED},
390 * {@link WifiManager#WIFI_AP_STATE_ENABLING},
391 * {@link WifiManager#WIFI_AP_STATE_FAILED}
392 */
393 public int getWifiApEnabledState() {
Irfan Sheriff17b232b2010-06-24 11:32:26 -0700394 enforceAccessPermission();
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700395 return mWifiStateMachine.syncGetWifiApState();
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700396 }
397
398 /**
399 * see {@link WifiManager#getWifiApConfiguration()}
400 * @return soft access point configuration
401 */
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700402 public WifiConfiguration getWifiApConfiguration() {
403 enforceAccessPermission();
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800404 return mWifiStateMachine.syncGetWifiApConfiguration();
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800405 }
406
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700407 /**
408 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)}
409 * @param wifiConfig WifiConfiguration details for soft access point
410 */
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700411 public void setWifiApConfiguration(WifiConfiguration wifiConfig) {
Irfan Sheriff17b232b2010-06-24 11:32:26 -0700412 enforceChangePermission();
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800413 if (wifiConfig == null)
414 return;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700415 mWifiStateMachine.setWifiApConfiguration(wifiConfig);
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800416 }
417
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800418 /**
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800419 * @param enable {@code true} to enable, {@code false} to disable.
420 * @return {@code true} if the enable/disable operation was
421 * started or is already in the queue.
422 */
Irfan Sheriff7ea33ea2013-04-19 08:39:53 -0700423 public boolean isScanAlwaysAvailable() {
Irfan Sheriff1ef840c2013-03-12 17:09:27 -0700424 enforceAccessPermission();
425 return mSettingsStore.isScanAlwaysAvailable();
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800426 }
427
428 /**
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700429 * see {@link android.net.wifi.WifiManager#disconnect()}
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800430 */
Irfan Sheriffe4984752010-08-19 11:29:22 -0700431 public void disconnect() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700432 enforceChangePermission();
Irfan Sheriffe4984752010-08-19 11:29:22 -0700433 mWifiStateMachine.disconnectCommand();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800434 }
435
436 /**
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700437 * see {@link android.net.wifi.WifiManager#reconnect()}
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800438 */
Irfan Sheriffe4984752010-08-19 11:29:22 -0700439 public void reconnect() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700440 enforceChangePermission();
Irfan Sheriffe4984752010-08-19 11:29:22 -0700441 mWifiStateMachine.reconnectCommand();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800442 }
443
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700444 /**
445 * see {@link android.net.wifi.WifiManager#reassociate()}
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700446 */
Irfan Sheriffe4984752010-08-19 11:29:22 -0700447 public void reassociate() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700448 enforceChangePermission();
Irfan Sheriffe4984752010-08-19 11:29:22 -0700449 mWifiStateMachine.reassociateCommand();
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800450 }
451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 /**
453 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()}
454 * @return the list of configured networks
455 */
456 public List<WifiConfiguration> getConfiguredNetworks() {
457 enforceAccessPermission();
Irfan Sheriffe744cff2011-12-11 09:17:50 -0800458 if (mWifiStateMachineChannel != null) {
459 return mWifiStateMachine.syncGetConfiguredNetworks(mWifiStateMachineChannel);
460 } else {
461 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
462 return null;
463 }
Chung-yih Wanga8d15942009-10-09 11:01:49 +0800464 }
465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 /**
467 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)}
468 * @return the supplicant-assigned identifier for the new or updated
469 * network if the operation succeeds, or {@code -1} if it fails
470 */
Irfan Sheriff7aac5542009-12-22 21:42:17 -0800471 public int addOrUpdateNetwork(WifiConfiguration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800473 if (mWifiStateMachineChannel != null) {
474 return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700475 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800476 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700477 return -1;
478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 }
480
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700481 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 * See {@link android.net.wifi.WifiManager#removeNetwork(int)}
483 * @param netId the integer that identifies the network configuration
484 * to the supplicant
485 * @return {@code true} if the operation succeeded
486 */
487 public boolean removeNetwork(int netId) {
488 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800489 if (mWifiStateMachineChannel != null) {
490 return mWifiStateMachine.syncRemoveNetwork(mWifiStateMachineChannel, netId);
Wink Saville4b7ba092010-10-20 15:37:41 -0700491 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800492 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Wink Saville4b7ba092010-10-20 15:37:41 -0700493 return false;
494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 }
496
497 /**
498 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)}
499 * @param netId the integer that identifies the network configuration
500 * to the supplicant
501 * @param disableOthers if true, disable all other networks.
502 * @return {@code true} if the operation succeeded
503 */
504 public boolean enableNetwork(int netId, boolean disableOthers) {
505 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800506 if (mWifiStateMachineChannel != null) {
507 return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId,
508 disableOthers);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700509 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800510 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700511 return false;
512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 }
514
515 /**
516 * See {@link android.net.wifi.WifiManager#disableNetwork(int)}
517 * @param netId the integer that identifies the network configuration
518 * to the supplicant
519 * @return {@code true} if the operation succeeded
520 */
521 public boolean disableNetwork(int netId) {
522 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800523 if (mWifiStateMachineChannel != null) {
524 return mWifiStateMachine.syncDisableNetwork(mWifiStateMachineChannel, netId);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700525 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800526 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700527 return false;
528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 }
530
531 /**
532 * See {@link android.net.wifi.WifiManager#getConnectionInfo()}
533 * @return the Wi-Fi information, contained in {@link WifiInfo}.
534 */
535 public WifiInfo getConnectionInfo() {
536 enforceAccessPermission();
537 /*
538 * Make sure we have the latest information, by sending
539 * a status request to the supplicant.
540 */
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700541 return mWifiStateMachine.syncRequestConnectionInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 }
543
544 /**
545 * Return the results of the most recent access point scan, in the form of
546 * a list of {@link ScanResult} objects.
547 * @return the list of results
548 */
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800549 public List<ScanResult> getScanResults(String callingPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 enforceAccessPermission();
Irfan Sheriffdb831da2012-09-16 17:39:26 -0700551 int userId = UserHandle.getCallingUserId();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800552 int uid = Binder.getCallingUid();
Irfan Sheriffdb831da2012-09-16 17:39:26 -0700553 long ident = Binder.clearCallingIdentity();
Dianne Hackborn5e45ee62013-01-24 19:13:44 -0800554 if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
555 != AppOpsManager.MODE_ALLOWED) {
556 return new ArrayList<ScanResult>();
557 }
Irfan Sheriff3d33a632012-09-16 17:59:13 -0700558 try {
559 int currentUser = ActivityManager.getCurrentUser();
560 if (userId != currentUser) {
561 return new ArrayList<ScanResult>();
562 } else {
563 return mWifiStateMachine.syncGetScanResultsList();
564 }
565 } finally {
566 Binder.restoreCallingIdentity(ident);
Irfan Sheriff330b1872012-09-16 12:27:57 -0700567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800568 }
569
570 /**
571 * Tell the supplicant to persist the current list of configured networks.
572 * @return {@code true} if the operation succeeded
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700573 *
574 * TODO: deprecate this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 */
576 public boolean saveConfiguration() {
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700577 boolean result = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 enforceChangePermission();
Irfan Sheriff227bec42011-02-15 19:30:27 -0800579 if (mWifiStateMachineChannel != null) {
580 return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700581 } else {
Irfan Sheriff227bec42011-02-15 19:30:27 -0800582 Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700583 return false;
584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 }
586
587 /**
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700588 * Set the country code
589 * @param countryCode ISO 3166 country code.
Robert Greenwaltb5010cc2009-05-21 15:11:40 -0700590 * @param persist {@code true} if the setting should be remembered.
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700591 *
592 * The persist behavior exists so that wifi can fall back to the last
593 * persisted country code on a restart, when the locale information is
594 * not available from telephony.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 */
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700596 public void setCountryCode(String countryCode, boolean persist) {
597 Slog.i(TAG, "WifiService trying to set country code to " + countryCode +
598 " with persist set to " + persist);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 enforceChangePermission();
Robert Greenwalt304aad42013-05-31 17:57:10 -0700600 final long token = Binder.clearCallingIdentity();
601 try {
602 mWifiStateMachine.setCountryCode(countryCode, persist);
603 } finally {
604 Binder.restoreCallingIdentity(token);
605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 }
607
608 /**
Irfan Sheriff36f74132010-11-04 16:57:37 -0700609 * Set the operational frequency band
610 * @param band One of
611 * {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO},
612 * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ},
613 * {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ},
614 * @param persist {@code true} if the setting should be remembered.
615 *
616 */
617 public void setFrequencyBand(int band, boolean persist) {
618 enforceChangePermission();
619 if (!isDualBandSupported()) return;
620 Slog.i(TAG, "WifiService trying to set frequency band to " + band +
621 " with persist set to " + persist);
Robert Greenwalt304aad42013-05-31 17:57:10 -0700622 final long token = Binder.clearCallingIdentity();
623 try {
624 mWifiStateMachine.setFrequencyBand(band, persist);
625 } finally {
626 Binder.restoreCallingIdentity(token);
627 }
Irfan Sheriff36f74132010-11-04 16:57:37 -0700628 }
629
630
631 /**
632 * Get the operational frequency band
633 */
634 public int getFrequencyBand() {
635 enforceAccessPermission();
636 return mWifiStateMachine.getFrequencyBand();
637 }
638
639 public boolean isDualBandSupported() {
640 //TODO: Should move towards adding a driver API that checks at runtime
641 return mContext.getResources().getBoolean(
642 com.android.internal.R.bool.config_wifi_dual_band_support);
643 }
644
645 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 * Return the DHCP-assigned addresses from the last successful DHCP request,
647 * if any.
648 * @return the DHCP information
Robert Greenwalt4717c262012-10-31 14:32:53 -0700649 * @deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 */
651 public DhcpInfo getDhcpInfo() {
652 enforceAccessPermission();
Robert Greenwalt4717c262012-10-31 14:32:53 -0700653 DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults();
654 if (dhcpResults.linkProperties == null) return null;
655
656 DhcpInfo info = new DhcpInfo();
657 for (LinkAddress la : dhcpResults.linkProperties.getLinkAddresses()) {
658 InetAddress addr = la.getAddress();
659 if (addr instanceof Inet4Address) {
660 info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address)addr);
661 break;
662 }
663 }
664 for (RouteInfo r : dhcpResults.linkProperties.getRoutes()) {
665 if (r.isDefaultRoute()) {
666 InetAddress gateway = r.getGateway();
667 if (gateway instanceof Inet4Address) {
668 info.gateway = NetworkUtils.inetAddressToInt((Inet4Address)gateway);
669 }
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700670 } else if (r.hasGateway() == false) {
Robert Greenwalt4717c262012-10-31 14:32:53 -0700671 LinkAddress dest = r.getDestination();
672 if (dest.getAddress() instanceof Inet4Address) {
673 info.netmask = NetworkUtils.prefixLengthToNetmaskInt(
674 dest.getNetworkPrefixLength());
675 }
676 }
677 }
678 int dnsFound = 0;
679 for (InetAddress dns : dhcpResults.linkProperties.getDnses()) {
680 if (dns instanceof Inet4Address) {
681 if (dnsFound == 0) {
682 info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns);
683 } else {
684 info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns);
685 }
686 if (++dnsFound > 1) break;
687 }
688 }
689 InetAddress serverAddress = dhcpResults.serverAddress;
690 if (serverAddress instanceof Inet4Address) {
691 info.serverAddress = NetworkUtils.inetAddressToInt((Inet4Address)serverAddress);
692 }
693 info.leaseDuration = dhcpResults.leaseDuration;
694
695 return info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 }
697
Irfan Sheriff0d255342010-07-28 09:35:20 -0700698 /**
699 * see {@link android.net.wifi.WifiManager#startWifi}
700 *
701 */
702 public void startWifi() {
Irfan Sheriffda6da092012-08-16 12:49:23 -0700703 enforceConnectivityInternalPermission();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700704 /* TODO: may be add permissions for access only to connectivity service
705 * TODO: if a start issued, keep wifi alive until a stop issued irrespective
706 * of WifiLock & device idle status unless wifi enabled status is toggled
707 */
708
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800709 mWifiStateMachine.setDriverStart(true);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700710 mWifiStateMachine.reconnectCommand();
711 }
712
Irfan Sheriffda6da092012-08-16 12:49:23 -0700713 public void captivePortalCheckComplete() {
714 enforceConnectivityInternalPermission();
715 mWifiStateMachine.captivePortalCheckComplete();
716 }
717
Irfan Sheriff0d255342010-07-28 09:35:20 -0700718 /**
719 * see {@link android.net.wifi.WifiManager#stopWifi}
720 *
721 */
722 public void stopWifi() {
Irfan Sheriffda6da092012-08-16 12:49:23 -0700723 enforceConnectivityInternalPermission();
724 /*
Irfan Sheriff0d255342010-07-28 09:35:20 -0700725 * TODO: if a stop is issued, wifi is brought up only by startWifi
726 * unless wifi enabled status is toggled
727 */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800728 mWifiStateMachine.setDriverStart(false);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700729 }
730
Irfan Sheriff0d255342010-07-28 09:35:20 -0700731 /**
732 * see {@link android.net.wifi.WifiManager#addToBlacklist}
733 *
734 */
735 public void addToBlacklist(String bssid) {
736 enforceChangePermission();
737
738 mWifiStateMachine.addToBlacklist(bssid);
739 }
740
741 /**
742 * see {@link android.net.wifi.WifiManager#clearBlacklist}
743 *
744 */
745 public void clearBlacklist() {
746 enforceChangePermission();
747
748 mWifiStateMachine.clearBlacklist();
749 }
750
Irfan Sheriff227bec42011-02-15 19:30:27 -0800751 /**
752 * Get a reference to handler. This is used by a client to establish
753 * an AsyncChannel communication with WifiService
754 */
Irfan Sheriff07573b32012-01-27 21:00:19 -0800755 public Messenger getWifiServiceMessenger() {
Irfan Sheriff35bbe272012-08-23 16:57:43 -0700756 enforceAccessPermission();
757 enforceChangePermission();
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800758 return new Messenger(mClientHandler);
Irfan Sheriff227bec42011-02-15 19:30:27 -0800759 }
760
Irfan Sheriff07573b32012-01-27 21:00:19 -0800761 /** Get a reference to WifiStateMachine handler for AsyncChannel communication */
762 public Messenger getWifiStateMachineMessenger() {
763 enforceAccessPermission();
764 enforceChangePermission();
765 return mWifiStateMachine.getMessenger();
766 }
767
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800768 /**
769 * Get the IP and proxy configuration file
770 */
771 public String getConfigFile() {
772 enforceAccessPermission();
773 return mWifiStateMachine.getConfigFile();
774 }
775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
777 @Override
778 public void onReceive(Context context, Intent intent) {
779 String action = intent.getAction();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 if (action.equals(Intent.ACTION_SCREEN_ON)) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800781 mWifiController.sendMessage(CMD_SCREEN_ON);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800783 mWifiController.sendMessage(CMD_SCREEN_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 int pluggedType = intent.getIntExtra("plugged", 0);
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800786 mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null);
Irfan Sheriff65eaec82011-01-05 22:00:16 -0800787 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
788 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
789 BluetoothAdapter.STATE_DISCONNECTED);
790 mWifiStateMachine.sendBluetoothAdapterStateChange(state);
Irfan Sheriff616f3172011-09-11 19:59:01 -0700791 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800792 boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);
793 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 };
797
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800798 /**
799 * Observes settings changes to scan always mode.
800 */
801 private void registerForScanModeChange() {
802 ContentObserver contentObserver = new ContentObserver(null) {
803 @Override
804 public void onChange(boolean selfChange) {
805 mSettingsStore.handleWifiScanAlwaysAvailableToggled();
806 mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED);
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700807 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800808 };
Jaikumar Ganesh7440fc22010-09-27 17:04:14 -0700809
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800810 mContext.getContentResolver().registerContentObserver(
811 Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE),
812 false, contentObserver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813 }
814
815 private void registerForBroadcasts() {
816 IntentFilter intentFilter = new IntentFilter();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
818 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
819 intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800820 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
Irfan Sheriff65eaec82011-01-05 22:00:16 -0800821 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
Irfan Sheriff616f3172011-09-11 19:59:01 -0700822 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823 mContext.registerReceiver(mReceiver, intentFilter);
824 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 @Override
827 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
828 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
829 != PackageManager.PERMISSION_GRANTED) {
830 pw.println("Permission Denial: can't dump WifiService from from pid="
831 + Binder.getCallingPid()
832 + ", uid=" + Binder.getCallingUid());
833 return;
834 }
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700835 pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 pw.println("Stay-awake conditions: " +
Christopher Tatec09cdce2012-09-10 16:50:14 -0700837 Settings.Global.getInt(mContext.getContentResolver(),
838 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0));
Irfan Sherifff0afe412012-11-30 14:07:44 -0800839 pw.println("mMulticastEnabled " + mMulticastEnabled);
840 pw.println("mMulticastDisabled " + mMulticastDisabled);
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800841 mWifiController.dump(fd, pw, args);
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800842 mSettingsStore.dump(fd, pw, args);
843 mNotificationController.dump(fd, pw, args);
844 mTrafficPoller.dump(fd, pw, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 pw.println("Latest scan results:");
Irfan Sheriffd8134ff2010-08-22 17:06:34 -0700847 List<ScanResult> scanResults = mWifiStateMachine.syncGetScanResultsList();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 if (scanResults != null && scanResults.size() != 0) {
849 pw.println(" BSSID Frequency RSSI Flags SSID");
850 for (ScanResult r : scanResults) {
851 pw.printf(" %17s %9d %5d %-16s %s%n",
852 r.BSSID,
853 r.frequency,
854 r.level,
855 r.capabilities,
856 r.SSID == null ? "" : r.SSID);
857 }
858 }
859 pw.println();
Eric Shienbrood5711fad2009-03-27 20:25:31 -0700860 pw.println("Locks acquired: " + mFullLocksAcquired + " full, " +
Irfan Sheriff5876a422010-08-12 20:26:23 -0700861 mFullHighPerfLocksAcquired + " full high perf, " +
Eric Shienbrood5711fad2009-03-27 20:25:31 -0700862 mScanLocksAcquired + " scan");
863 pw.println("Locks released: " + mFullLocksReleased + " full, " +
Irfan Sheriff5876a422010-08-12 20:26:23 -0700864 mFullHighPerfLocksReleased + " full high perf, " +
Eric Shienbrood5711fad2009-03-27 20:25:31 -0700865 mScanLocksReleased + " scan");
866 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 pw.println("Locks held:");
868 mLocks.dump(pw);
Isaac Levybc7dfb52011-06-06 15:34:01 -0700869
Irfan Sherifff0afe412012-11-30 14:07:44 -0800870 mWifiWatchdogStateMachine.dump(fd, pw, args);
Isaac Levybc7dfb52011-06-06 15:34:01 -0700871 pw.println();
Irfan Sheriff60792372012-04-16 16:47:10 -0700872 mWifiStateMachine.dump(fd, pw, args);
Irfan Sherifff0afe412012-11-30 14:07:44 -0800873 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 }
875
Robert Greenwalt58ff0212009-05-19 15:53:54 -0700876 private class WifiLock extends DeathRecipient {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700877 WifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) {
878 super(lockMode, tag, binder, ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 }
880
881 public void binderDied() {
882 synchronized (mLocks) {
883 releaseWifiLockLocked(mBinder);
884 }
885 }
886
887 public String toString() {
Robert Greenwalt5347bd42009-05-13 15:10:16 -0700888 return "WifiLock{" + mTag + " type=" + mMode + " binder=" + mBinder + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 }
890 }
891
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800892 class LockList {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 private List<WifiLock> mList;
894
895 private LockList() {
896 mList = new ArrayList<WifiLock>();
897 }
898
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800899 synchronized boolean hasLocks() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 return !mList.isEmpty();
901 }
902
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800903 synchronized int getStrongestLockMode() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 if (mList.isEmpty()) {
905 return WifiManager.WIFI_MODE_FULL;
906 }
Irfan Sheriff5876a422010-08-12 20:26:23 -0700907
908 if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) {
909 return WifiManager.WIFI_MODE_FULL_HIGH_PERF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 }
Irfan Sheriff5876a422010-08-12 20:26:23 -0700911
912 if (mFullLocksAcquired > mFullLocksReleased) {
913 return WifiManager.WIFI_MODE_FULL;
914 }
915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 return WifiManager.WIFI_MODE_SCAN_ONLY;
917 }
918
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800919 synchronized void updateWorkSource(WorkSource ws) {
920 for (int i = 0; i < mLocks.mList.size(); i++) {
921 ws.add(mLocks.mList.get(i).mWorkSource);
922 }
923 }
924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 private void addLock(WifiLock lock) {
926 if (findLockByBinder(lock.mBinder) < 0) {
927 mList.add(lock);
928 }
929 }
930
931 private WifiLock removeLock(IBinder binder) {
932 int index = findLockByBinder(binder);
933 if (index >= 0) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -0700934 WifiLock ret = mList.remove(index);
935 ret.unlinkDeathRecipient();
936 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 } else {
938 return null;
939 }
940 }
941
942 private int findLockByBinder(IBinder binder) {
943 int size = mList.size();
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800944 for (int i = size - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 if (mList.get(i).mBinder == binder)
946 return i;
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 return -1;
949 }
950
951 private void dump(PrintWriter pw) {
952 for (WifiLock l : mList) {
953 pw.print(" ");
954 pw.println(l);
955 }
956 }
957 }
958
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700959 void enforceWakeSourcePermission(int uid, int pid) {
Dianne Hackborne746f032010-09-13 16:02:57 -0700960 if (uid == android.os.Process.myUid()) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700961 return;
962 }
963 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
964 pid, uid, null);
965 }
966
967 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
Irfan Sheriff5876a422010-08-12 20:26:23 -0700969 if (lockMode != WifiManager.WIFI_MODE_FULL &&
970 lockMode != WifiManager.WIFI_MODE_SCAN_ONLY &&
971 lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF) {
972 Slog.e(TAG, "Illegal argument, lockMode= " + lockMode);
973 if (DBG) throw new IllegalArgumentException("lockMode=" + lockMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 return false;
975 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700976 if (ws != null && ws.size() == 0) {
977 ws = null;
978 }
Dianne Hackbornecfd7f72010-10-08 14:23:40 -0700979 if (ws != null) {
980 enforceWakeSourcePermission(Binder.getCallingUid(), Binder.getCallingPid());
981 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700982 if (ws == null) {
983 ws = new WorkSource(Binder.getCallingUid());
984 }
985 WifiLock wifiLock = new WifiLock(lockMode, tag, binder, ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 synchronized (mLocks) {
987 return acquireWifiLockLocked(wifiLock);
988 }
989 }
990
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700991 private void noteAcquireWifiLock(WifiLock wifiLock) throws RemoteException {
992 switch(wifiLock.mMode) {
993 case WifiManager.WIFI_MODE_FULL:
Irfan Sheriff5876a422010-08-12 20:26:23 -0700994 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700995 case WifiManager.WIFI_MODE_SCAN_ONLY:
Nick Pelly6ccaa542012-06-15 15:22:47 -0700996 mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700997 break;
998 }
999 }
1000
1001 private void noteReleaseWifiLock(WifiLock wifiLock) throws RemoteException {
1002 switch(wifiLock.mMode) {
1003 case WifiManager.WIFI_MODE_FULL:
Irfan Sheriff5876a422010-08-12 20:26:23 -07001004 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001005 case WifiManager.WIFI_MODE_SCAN_ONLY:
Nick Pelly6ccaa542012-06-15 15:22:47 -07001006 mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001007 break;
1008 }
1009 }
1010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 private boolean acquireWifiLockLocked(WifiLock wifiLock) {
Irfan Sheriffc89dd542010-09-28 08:40:54 -07001012 if (DBG) Slog.d(TAG, "acquireWifiLockLocked: " + wifiLock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 mLocks.addLock(wifiLock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001015
The Android Open Source Project10592532009-03-18 17:39:46 -07001016 long ident = Binder.clearCallingIdentity();
1017 try {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001018 noteAcquireWifiLock(wifiLock);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001019 switch(wifiLock.mMode) {
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001020 case WifiManager.WIFI_MODE_FULL:
1021 ++mFullLocksAcquired;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001022 break;
Irfan Sheriff5876a422010-08-12 20:26:23 -07001023 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
1024 ++mFullHighPerfLocksAcquired;
1025 break;
1026
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001027 case WifiManager.WIFI_MODE_SCAN_ONLY:
1028 ++mScanLocksAcquired;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001029 break;
The Android Open Source Project10592532009-03-18 17:39:46 -07001030 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001031 mWifiController.sendMessage(CMD_LOCKS_CHANGED);
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001032 return true;
The Android Open Source Project10592532009-03-18 17:39:46 -07001033 } catch (RemoteException e) {
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001034 return false;
The Android Open Source Project10592532009-03-18 17:39:46 -07001035 } finally {
1036 Binder.restoreCallingIdentity(ident);
1037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 }
1039
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001040 public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) {
1041 int uid = Binder.getCallingUid();
1042 int pid = Binder.getCallingPid();
1043 if (ws != null && ws.size() == 0) {
1044 ws = null;
1045 }
1046 if (ws != null) {
1047 enforceWakeSourcePermission(uid, pid);
1048 }
1049 long ident = Binder.clearCallingIdentity();
1050 try {
1051 synchronized (mLocks) {
1052 int index = mLocks.findLockByBinder(lock);
1053 if (index < 0) {
1054 throw new IllegalArgumentException("Wifi lock not active");
1055 }
1056 WifiLock wl = mLocks.mList.get(index);
1057 noteReleaseWifiLock(wl);
1058 wl.mWorkSource = ws != null ? new WorkSource(ws) : new WorkSource(uid);
1059 noteAcquireWifiLock(wl);
1060 }
1061 } catch (RemoteException e) {
1062 } finally {
1063 Binder.restoreCallingIdentity(ident);
1064 }
1065 }
1066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 public boolean releaseWifiLock(IBinder lock) {
1068 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
1069 synchronized (mLocks) {
1070 return releaseWifiLockLocked(lock);
1071 }
1072 }
1073
1074 private boolean releaseWifiLockLocked(IBinder lock) {
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001075 boolean hadLock;
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001076
The Android Open Source Project10592532009-03-18 17:39:46 -07001077 WifiLock wifiLock = mLocks.removeLock(lock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001078
Irfan Sheriffc89dd542010-09-28 08:40:54 -07001079 if (DBG) Slog.d(TAG, "releaseWifiLockLocked: " + wifiLock);
Robert Greenwaltf1acb2d2009-10-13 08:20:55 -07001080
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001081 hadLock = (wifiLock != null);
1082
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001083 long ident = Binder.clearCallingIdentity();
1084 try {
1085 if (hadLock) {
Wink Savillece0ea1f2011-10-13 16:55:20 -07001086 noteReleaseWifiLock(wifiLock);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001087 switch(wifiLock.mMode) {
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001088 case WifiManager.WIFI_MODE_FULL:
1089 ++mFullLocksReleased;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001090 break;
Irfan Sheriff5876a422010-08-12 20:26:23 -07001091 case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
1092 ++mFullHighPerfLocksReleased;
1093 break;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001094 case WifiManager.WIFI_MODE_SCAN_ONLY:
1095 ++mScanLocksReleased;
Eric Shienbrood5711fad2009-03-27 20:25:31 -07001096 break;
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001097 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001098 mWifiController.sendMessage(CMD_LOCKS_CHANGED);
The Android Open Source Project10592532009-03-18 17:39:46 -07001099 }
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001100 } catch (RemoteException e) {
1101 } finally {
1102 Binder.restoreCallingIdentity(ident);
The Android Open Source Project10592532009-03-18 17:39:46 -07001103 }
Dianne Hackbornecfd7f72010-10-08 14:23:40 -07001104
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001105 return hadLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 }
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001107
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001108 private abstract class DeathRecipient
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001109 implements IBinder.DeathRecipient {
1110 String mTag;
1111 int mMode;
1112 IBinder mBinder;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001113 WorkSource mWorkSource;
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001114
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001115 DeathRecipient(int mode, String tag, IBinder binder, WorkSource ws) {
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001116 super();
1117 mTag = tag;
1118 mMode = mode;
1119 mBinder = binder;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001120 mWorkSource = ws;
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001121 try {
1122 mBinder.linkToDeath(this, 0);
1123 } catch (RemoteException e) {
1124 binderDied();
1125 }
1126 }
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001127
1128 void unlinkDeathRecipient() {
1129 mBinder.unlinkToDeath(this, 0);
1130 }
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001131 }
1132
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001133 private class Multicaster extends DeathRecipient {
1134 Multicaster(String tag, IBinder binder) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001135 super(Binder.getCallingUid(), tag, binder, null);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001136 }
1137
1138 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001139 Slog.e(TAG, "Multicaster binderDied");
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001140 synchronized (mMulticasters) {
1141 int i = mMulticasters.indexOf(this);
1142 if (i != -1) {
1143 removeMulticasterLocked(i, mMode);
1144 }
1145 }
1146 }
1147
1148 public String toString() {
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001149 return "Multicaster{" + mTag + " binder=" + mBinder + "}";
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001150 }
1151
1152 public int getUid() {
1153 return mMode;
1154 }
1155 }
1156
Robert Greenwalte2d155a2009-10-21 14:58:34 -07001157 public void initializeMulticastFiltering() {
1158 enforceMulticastChangePermission();
Irfan Sheriffa8fbe1f2010-03-09 09:13:58 -08001159
Robert Greenwalte2d155a2009-10-21 14:58:34 -07001160 synchronized (mMulticasters) {
1161 // if anybody had requested filters be off, leave off
1162 if (mMulticasters.size() != 0) {
1163 return;
1164 } else {
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001165 mWifiStateMachine.startFilteringMulticastV4Packets();
Robert Greenwalte2d155a2009-10-21 14:58:34 -07001166 }
1167 }
1168 }
1169
Robert Greenwaltfc1b15c2009-05-22 15:09:51 -07001170 public void acquireMulticastLock(IBinder binder, String tag) {
1171 enforceMulticastChangePermission();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001172
1173 synchronized (mMulticasters) {
1174 mMulticastEnabled++;
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001175 mMulticasters.add(new Multicaster(tag, binder));
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001176 // Note that we could call stopFilteringMulticastV4Packets only when
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001177 // our new size == 1 (first call), but this function won't
1178 // be called often and by making the stopPacket call each
1179 // time we're less fragile and self-healing.
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001180 mWifiStateMachine.stopFilteringMulticastV4Packets();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001181 }
1182
1183 int uid = Binder.getCallingUid();
You Kim2bea5852012-10-23 22:56:51 +09001184 final long ident = Binder.clearCallingIdentity();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001185 try {
1186 mBatteryStats.noteWifiMulticastEnabled(uid);
1187 } catch (RemoteException e) {
1188 } finally {
1189 Binder.restoreCallingIdentity(ident);
1190 }
1191 }
1192
Robert Greenwaltfc1b15c2009-05-22 15:09:51 -07001193 public void releaseMulticastLock() {
1194 enforceMulticastChangePermission();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001195
1196 int uid = Binder.getCallingUid();
1197 synchronized (mMulticasters) {
1198 mMulticastDisabled++;
1199 int size = mMulticasters.size();
1200 for (int i = size - 1; i >= 0; i--) {
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001201 Multicaster m = mMulticasters.get(i);
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001202 if ((m != null) && (m.getUid() == uid)) {
1203 removeMulticasterLocked(i, uid);
1204 }
1205 }
1206 }
1207 }
1208
1209 private void removeMulticasterLocked(int i, int uid)
1210 {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001211 Multicaster removed = mMulticasters.remove(i);
Irfan Sheriffa8fbe1f2010-03-09 09:13:58 -08001212
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07001213 if (removed != null) {
1214 removed.unlinkDeathRecipient();
1215 }
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001216 if (mMulticasters.size() == 0) {
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001217 mWifiStateMachine.startFilteringMulticastV4Packets();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001218 }
1219
You Kim2bea5852012-10-23 22:56:51 +09001220 final long ident = Binder.clearCallingIdentity();
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001221 try {
1222 mBatteryStats.noteWifiMulticastDisabled(uid);
1223 } catch (RemoteException e) {
1224 } finally {
1225 Binder.restoreCallingIdentity(ident);
1226 }
1227 }
1228
Robert Greenwalt58ff0212009-05-19 15:53:54 -07001229 public boolean isMulticastEnabled() {
Robert Greenwalt5347bd42009-05-13 15:10:16 -07001230 enforceAccessPermission();
1231
1232 synchronized (mMulticasters) {
1233 return (mMulticasters.size() > 0);
1234 }
1235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236}