WifiServiceImpl.java revision 3b26801d62a06475b722bbf29cba7f48f376654e
1d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor/* 2d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * Copyright (C) 2010 The Android Open Source Project 3d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * 4d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * Licensed under the Apache License, Version 2.0 (the "License"); 5d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * you may not use this file except in compliance with the License. 6d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * You may obtain a copy of the License at 7d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * 8d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * http://www.apache.org/licenses/LICENSE-2.0 9d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * 10d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * Unless required by applicable law or agreed to in writing, software 11d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * distributed under the License is distributed on an "AS IS" BASIS, 12d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * See the License for the specific language governing permissions and 14d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * limitations under the License. 15d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor */ 16d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor 1730a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruthpackage com.android.server.wifi; 18d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor 19d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.app.ActivityManager; 20d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregorimport android.app.AppOpsManager; 21d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.bluetooth.BluetoothAdapter; 22d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.content.BroadcastReceiver; 23d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.content.Context; 24d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.content.Intent; 25d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.content.IntentFilter; 26d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.content.pm.PackageManager; 27d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.content.pm.UserInfo; 28d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.database.ContentObserver; 29d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.net.DhcpInfo; 30d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.net.DhcpResults; 31d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.net.IpConfiguration.ProxySettings; 32d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.net.LinkAddress; 33d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.net.NetworkUtils; 34d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.net.RouteInfo; 35d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.net.wifi.*; 36d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.net.wifi.IWifiManager; 37d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.os.AsyncTask; 38d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.os.Binder; 39d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.os.Handler; 40d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.os.HandlerThread; 41d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.os.IBinder; 4224bae92f08ae098cc50a602d8cf1273b423e14daDouglas Gregorimport android.os.Message; 43c95d413660756c474bc8f97e5b32edc7ddff3850Richard Smithimport android.os.Messenger; 44c95d413660756c474bc8f97e5b32edc7ddff3850Richard Smithimport android.os.RemoteException; 45c95d413660756c474bc8f97e5b32edc7ddff3850Richard Smithimport android.os.SystemProperties; 46d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.os.UserHandle; 47357bbd022c1d340c8e255aea7a684ddb34bc76e5Douglas Gregorimport android.os.UserManager; 48686775deca8b8685eb90801495880e3abdd844c2Chris Lattnerimport android.os.WorkSource; 49d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.provider.Settings; 50d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.util.Log; 51d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport android.util.Slog; 52d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor 53d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport java.io.FileNotFoundException; 54d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport java.io.BufferedReader; 55357bbd022c1d340c8e255aea7a684ddb34bc76e5Douglas Gregorimport java.io.FileDescriptor; 56d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport java.io.FileReader; 5724bae92f08ae098cc50a602d8cf1273b423e14daDouglas Gregorimport java.io.IOException; 58d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport java.io.PrintWriter; 59d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport java.lang.Override; 60d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport java.net.InetAddress; 61d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport java.net.Inet4Address; 62d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport java.util.ArrayList; 63d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport java.util.List; 64d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor 65d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport com.android.internal.R; 66d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregorimport com.android.internal.app.IBatteryStats; 67c95d413660756c474bc8f97e5b32edc7ddff3850Richard Smithimport com.android.internal.telephony.TelephonyIntents; 68c95d413660756c474bc8f97e5b32edc7ddff3850Richard Smithimport com.android.internal.util.AsyncChannel; 69d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport com.android.server.am.BatteryStatsService; 70d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregor 71d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED; 72d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED; 73d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED; 74d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED; 75d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED; 76d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport static com.android.server.wifi.WifiController.CMD_SCREEN_OFF; 77d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport static com.android.server.wifi.WifiController.CMD_SCREEN_ON; 78c95d413660756c474bc8f97e5b32edc7ddff3850Richard Smithimport static com.android.server.wifi.WifiController.CMD_SET_AP; 79d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport static com.android.server.wifi.WifiController.CMD_USER_PRESENT; 80d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregorimport static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED; 81d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregor/** 82d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * WifiService handles remote WiFi operation requests by implementing 83d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor * the IWifiManager interface. 84d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor * 85d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor * @hide 86d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor */ 87d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorpublic final class WifiServiceImpl extends IWifiManager.Stub { 88c95d413660756c474bc8f97e5b32edc7ddff3850Richard Smith private static final String TAG = "WifiService"; 89d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor private static final boolean DBG = true; 90c95d413660756c474bc8f97e5b32edc7ddff3850Richard Smith 91d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor final WifiStateMachine mWifiStateMachine; 92d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor 93d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor private final Context mContext; 94d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor 95d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor final LockList mLocks = new LockList(); 96d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor // some wifi lock statistics 97b5eb3f5bf383807103dc1377a124fd96ee21d02aRichard Smith private int mFullHighPerfLocksAcquired; 98b5eb3f5bf383807103dc1377a124fd96ee21d02aRichard Smith private int mFullHighPerfLocksReleased; 9924bae92f08ae098cc50a602d8cf1273b423e14daDouglas Gregor private int mFullLocksAcquired; 100b5eb3f5bf383807103dc1377a124fd96ee21d02aRichard Smith private int mFullLocksReleased; 101b5eb3f5bf383807103dc1377a124fd96ee21d02aRichard Smith private int mScanLocksAcquired; 102b5eb3f5bf383807103dc1377a124fd96ee21d02aRichard Smith private int mScanLocksReleased; 103b5eb3f5bf383807103dc1377a124fd96ee21d02aRichard Smith 104b5eb3f5bf383807103dc1377a124fd96ee21d02aRichard Smith private final List<Multicaster> mMulticasters = 105b5eb3f5bf383807103dc1377a124fd96ee21d02aRichard Smith new ArrayList<Multicaster>(); 106b5eb3f5bf383807103dc1377a124fd96ee21d02aRichard Smith private int mMulticastEnabled; 107d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregor private int mMulticastDisabled; 10824bae92f08ae098cc50a602d8cf1273b423e14daDouglas Gregor 10924bae92f08ae098cc50a602d8cf1273b423e14daDouglas Gregor private final IBatteryStats mBatteryStats; 110d6350aefb1396b299e199c7f1fe51bb40c12e75eDouglas Gregor private final AppOpsManager mAppOps; 111d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor 1128a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor private String mInterfaceName; 1138a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor 1147cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall /* Tracks the open wi-fi network notification */ 1158a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor private WifiNotificationController mNotificationController; 1168a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor /* Polls traffic stats and notifies clients */ 1178a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor private WifiTrafficPoller mTrafficPoller; 1188a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor /* Tracks the persisted states for wi-fi & airplane mode */ 1198a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor final WifiSettingsStore mSettingsStore; 1208a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor 1218a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor final boolean mBatchedScanSupported; 1228a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor 1238a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor /** 1248a51491d936d8c50480f3c3ca6647be12a7ad51fDouglas Gregor * Asynchronous channel to WifiStateMachine 12502024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor */ 1267cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall private AsyncChannel mWifiStateMachineChannel; 1277cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall 1287cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall /** 1297cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall * Handles client connections 1307cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall */ 1317cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall private class ClientHandler extends Handler { 1327cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall 1337cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall ClientHandler(android.os.Looper looper) { 1347cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall super(looper); 1357cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall } 1367cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall 13702024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor @Override 13802024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor public void handleMessage(Message msg) { 13902024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor switch (msg.what) { 14002024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 14102024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 14202024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); 14302024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor // We track the clients by the Messenger 14402024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor // since it is expected to be always available 14502024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor mTrafficPoller.addClient(msg.replyTo); 14602024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor } else { 14702024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor Slog.e(TAG, "Client connection failure, error=" + msg.arg1); 14802024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor } 14902024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor break; 15002024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor } 15102024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 15202024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { 153d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor if (DBG) Slog.d(TAG, "Send failed, client connection lost"); 154855243789cb44799c03f4c7216d3d6308805f549Benjamin Kramer } else { 155855243789cb44799c03f4c7216d3d6308805f549Benjamin Kramer if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); 15602024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor } 15702024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor mTrafficPoller.removeClient(msg.replyTo); 158855243789cb44799c03f4c7216d3d6308805f549Benjamin Kramer break; 15902024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor } 16002024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { 16102024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor AsyncChannel ac = new AsyncChannel(); 16202024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor ac.connect(mContext, this, msg.replyTo); 16302024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor break; 16402024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor } 16502024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor /* Client commands are forwarded to state machine */ 16602024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor case WifiManager.CONNECT_NETWORK: 16702024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor case WifiManager.SAVE_NETWORK: { 16802024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor WifiConfiguration config = (WifiConfiguration) msg.obj; 16902024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor int networkId = msg.arg1; 17002024a9f0d8e6c898de276193af604c42ee41269Douglas Gregor if (msg.what == WifiManager.SAVE_NETWORK) { 1712a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall if (config != null) { 1722a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall if (config.networkId == WifiConfiguration.INVALID_NETWORK_ID) { 1732a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall config.creatorUid = Binder.getCallingUid(); 1742a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } else { 1752a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall config.lastUpdateUid = Binder.getCallingUid(); 1762a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 1772a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 1782a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall Slog.e("WiFiServiceImpl ", "SAVE" 17912c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor + " nid=" + Integer.toString(networkId) 18012c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor + " uid=" + Integer.toString(config.creatorUid) 18187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar + "/" + Integer.toString(config.lastUpdateUid)); 18287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 18312c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor if (msg.what == WifiManager.CONNECT_NETWORK) { 1842a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall if (config != null) { 1852a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall if (config.networkId == WifiConfiguration.INVALID_NETWORK_ID) { 1862a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall config.creatorUid = Binder.getCallingUid(); 1872a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } else { 1883bbffd549c76dfeb3c8d7c73860736a6523cde92Benjamin Kramer config.lastUpdateUid = Binder.getCallingUid(); 1893bbffd549c76dfeb3c8d7c73860736a6523cde92Benjamin Kramer } 1903bbffd549c76dfeb3c8d7c73860736a6523cde92Benjamin Kramer } 1913bbffd549c76dfeb3c8d7c73860736a6523cde92Benjamin Kramer Slog.e("WiFiServiceImpl ", "CONNECT " 1922a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall + " nid=" + Integer.toString(networkId) 1932a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall + " uid=" + Binder.getCallingUid()); 1942a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 1952a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall if (config != null && config.isValid()) { 1962a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall if (DBG) Slog.d(TAG, "Connect with config" + config); 1972a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall mWifiStateMachine.sendMessage(Message.obtain(msg)); 1982a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } else if (config == null 1992a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall && networkId != WifiConfiguration.INVALID_NETWORK_ID) { 2002a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall if (DBG) Slog.d(TAG, "Connect with networkId" + networkId); 2012a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall mWifiStateMachine.sendMessage(Message.obtain(msg)); 2022a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } else { 2032a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg); 2042a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall if (msg.what == WifiManager.CONNECT_NETWORK) { 2052a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED, 20612c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor WifiManager.INVALID_ARGS); 20712c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor } else { 20812c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED, 20912c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor WifiManager.INVALID_ARGS); 21012c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor } 2112a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 21212c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor break; 213686775deca8b8685eb90801495880e3abdd844c2Chris Lattner } 21412c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor case WifiManager.FORGET_NETWORK: 2152a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall if (isOwner(msg.sendingUid)) { 2162a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall mWifiStateMachine.sendMessage(Message.obtain(msg)); 2172a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } else { 2182a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall Slog.e(TAG, "Forget is not authorized for user"); 2192a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall replyFailed(msg, WifiManager.FORGET_NETWORK_FAILED, 2202a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall WifiManager.NOT_AUTHORIZED); 2212a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 2222a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall break; 2232a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall case WifiManager.START_WPS: 2242a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall case WifiManager.CANCEL_WPS: 2252a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall case WifiManager.DISABLE_NETWORK: 2262a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall case WifiManager.RSSI_PKTCNT_FETCH: { 227d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor mWifiStateMachine.sendMessage(Message.obtain(msg)); 228d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor break; 229d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor } 230d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor default: { 231d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg); 232d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor break; 233d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor } 234d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor } 235d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor } 236d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor 237d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor private void replyFailed(Message msg, int what, int why) { 238d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor Message reply = msg.obtain(); 239d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor reply.what = what; 2402a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall reply.arg1 = why; 241be2fa7ebf01259b63dc52fe46c8d101c18e72269Craig Topper try { 2420e2c34f92f00628d48968dfea096d36381f494cbStephen Hines msg.replyTo.send(reply); 2430e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } catch (RemoteException e) { 2442a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall // There's not much we can do if reply can't be sent! 2452a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 2462a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 2472a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 248d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor private ClientHandler mClientHandler; 2496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2502a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall /** 2512a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall * Handles interaction with WifiStateMachine 2522a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall */ 2532a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall private class WifiStateMachineHandler extends Handler { 2542a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall private AsyncChannel mWsmChannel; 2552a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall 2562a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall WifiStateMachineHandler(android.os.Looper looper) { 257d8e54990ade0dd5566f8e3aa2e62def08753d1e9Chris Lattner super(looper); 258d8e54990ade0dd5566f8e3aa2e62def08753d1e9Chris Lattner mWsmChannel = new AsyncChannel(); 2592a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 2602a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 2612a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall 2622a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall @Override 2632a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall public void handleMessage(Message msg) { 2642a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall switch (msg.what) { 26512c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 26612c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 26712c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor mWifiStateMachineChannel = mWsmChannel; 2682a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } else { 2692a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1); 2702a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall mWifiStateMachineChannel = null; 2712a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall } 27223323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins break; 27323323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins } 27423323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 27523323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1); 2763ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mWifiStateMachineChannel = null; 2773ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar //Re-establish connection to state machine 2783ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 2793ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar break; 2803ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 28123323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins default: { 28223323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg); 28323323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins break; 2846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 28523323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins } 28623323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins } 28723323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins } 28823323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 28923323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins WifiStateMachineHandler mWifiStateMachineHandler; 29023323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 29123323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins private WifiWatchdogStateMachine mWifiWatchdogStateMachine; 29223323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 29323323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins private WifiController mWifiController; 29423323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 29523323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins public WifiServiceImpl(Context context) { 29623323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mContext = context; 29723323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 29823323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mInterfaceName = SystemProperties.get("wifi.interface", "wlan0"); 29923323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 30023323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName); 30123323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName, mTrafficPoller); 30223323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mWifiStateMachine.enableRssiPolling(true); 30323323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mBatteryStats = BatteryStatsService.getService(); 30423323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 30523323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 30623323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine); 3073ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mSettingsStore = new WifiSettingsStore(mContext); 3083ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 30923323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins HandlerThread wifiThread = new HandlerThread("WifiService"); 31023323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins wifiThread.start(); 31123323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mClientHandler = new ClientHandler(wifiThread.getLooper()); 31223323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper()); 31323323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mWifiController = new WifiController(mContext, this, wifiThread.getLooper()); 31423323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 31523323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins mBatchedScanSupported = mContext.getResources().getBoolean( 31623323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins R.bool.config_wifi_batched_scan_supported); 31723323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins } 31823323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 31923323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 32023323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins /** 32123323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins * Check if Wi-Fi needs to be enabled and start 32223323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins * if needed 32312c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor * 32412c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor * This function is used only at boot time 32512c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor */ 32612c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor public void checkAndStartWifi() { 32712c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor /* Check if wi-fi needs to be enabled */ 32812c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled(); 329c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines Slog.i(TAG, "WifiService starting up with Wi-Fi " + 33012c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor (wifiEnabled ? "enabled" : "disabled")); 33112c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor 33212c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor registerForScanModeChange(); 3332a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall mContext.registerReceiver( 3342a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall new BroadcastReceiver() { 33587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar @Override 33612c9c00024a01819e3a70ef6d951d32efaeb9312Douglas Gregor public void onReceive(Context context, Intent intent) { 337d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor if (mSettingsStore.handleAirplaneModeToggled()) { 338d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED); 339d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor } 340d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor } 341d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor }, 342d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); 343d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor 344d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor // Adding optimizations of only receiving broadcasts when wifi is enabled 345d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor // can result in race conditions when apps toggle wifi in the background 346d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor // without active user involvement. Always receive broadcasts. 347d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor registerForBroadcasts(); 348d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor 349d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor mWifiController.start(); 350d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor 351d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor // If we are already disabled (could be due to airplane mode), avoid changing persist 352d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor // state here 35322eaced5cac3cf0522c953f593419fc6cf184aafDouglas Gregor if (wifiEnabled) setWifiEnabled(wifiEnabled); 35422eaced5cac3cf0522c953f593419fc6cf184aafDouglas Gregor 35522eaced5cac3cf0522c953f593419fc6cf184aafDouglas Gregor mWifiWatchdogStateMachine = WifiWatchdogStateMachine. 35622eaced5cac3cf0522c953f593419fc6cf184aafDouglas Gregor makeWifiWatchdogStateMachine(mContext, mWifiStateMachine.getMessenger()); 35722eaced5cac3cf0522c953f593419fc6cf184aafDouglas Gregor } 3586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 3596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /** 36022eaced5cac3cf0522c953f593419fc6cf184aafDouglas Gregor * see {@link android.net.wifi.WifiManager#pingSupplicant()} 36122eaced5cac3cf0522c953f593419fc6cf184aafDouglas Gregor * @return {@code true} if the operation succeeds, {@code false} otherwise 36222eaced5cac3cf0522c953f593419fc6cf184aafDouglas Gregor */ 363d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor public boolean pingSupplicant() { 364d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor enforceAccessPermission(); 365d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor if (mWifiStateMachineChannel != null) { 3666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return mWifiStateMachine.syncPingSupplicant(mWifiStateMachineChannel); 3676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } else { 3686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 3692a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall return false; 370d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 371d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 3728491ffe86c50241b47c6d7ef8cd9ee00f5e675daDouglas Gregor 3738491ffe86c50241b47c6d7ef8cd9ee00f5e675daDouglas Gregor /** 374d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor * see {@link android.net.wifi.WifiManager#getChannelList} 3758491ffe86c50241b47c6d7ef8cd9ee00f5e675daDouglas Gregor */ 376d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor public List<WifiChannel> getChannelList() { 377d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor enforceAccessPermission(); 37823323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins if (mWifiStateMachineChannel != null) { 37923323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins return mWifiStateMachine.syncGetChannelList(mWifiStateMachineChannel); 380d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } else { 381d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 382d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor return null; 383d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 384686775deca8b8685eb90801495880e3abdd844c2Chris Lattner } 385d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor 386d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor /** 387d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor * see {@link android.net.wifi.WifiManager#startScan} 388ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo * and {@link android.net.wifi.WifiManager#startCustomizedScan} 389ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo * 390ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo * @param settings If null, use default parameter, i.e. full scan. 391ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo * @param workSource If null, all blame is given to the calling uid. 392ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo */ 393ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo public void startScan(ScanSettings settings, WorkSource workSource) { 394ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo enforceChangePermission(); 395ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo if (settings != null) { 396d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor // TODO: should be removed once the startCustomizedScan API is opened up 397d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor mContext.enforceCallingOrSelfPermission(android.Manifest.permission.LOCATION_HARDWARE, 398d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor "LocationHardware"); 399612409ece080e814f79e06772c690d603f45fbd6Richard Smith settings = new ScanSettings(settings); 400612409ece080e814f79e06772c690d603f45fbd6Richard Smith if (!settings.isValid()) { 4016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Slog.e(TAG, "invalid scan setting"); 4026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return; 403d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 404ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman } 405ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman if (workSource != null) { 406ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman enforceWorkSourcePermission(); 407ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman // WifiManager currently doesn't use names, so need to clear names out of the 408ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman // supplied WorkSource to allow future WorkSource combining. 409ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman workSource.clearNames(); 410ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman } 411ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman mWifiStateMachine.startScan(Binder.getCallingUid(), settings, workSource); 412ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman } 413ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman 414ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman private class BatchedScanRequest extends DeathRecipient { 415ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman final BatchedScanSettings settings; 41687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar final int uid; 417ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman final int pid; 418ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman final WorkSource workSource; 419ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman 420ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman BatchedScanRequest(BatchedScanSettings settings, IBinder binder, WorkSource ws) { 421ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman super(0, null, binder, null); 422ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman this.settings = settings; 423ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman this.uid = getCallingUid(); 424ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman this.pid = getCallingPid(); 425ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman workSource = ws; 426ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman } 427ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman public void binderDied() { 428ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman stopBatchedScan(settings, uid, pid); 429ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman } 430d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor public String toString() { 431ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman return "BatchedScanRequest{settings=" + settings + ", binder=" + mBinder + "}"; 432af0f4d0b2e38c810effc8b024ad2fb6604eec5d3Francois Pichet } 433ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman 434ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman public boolean isSameApp(int uid, int pid) { 435ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman return (this.uid == uid && this.pid == pid); 436567f917df048d42732997a479b2b257403fc88efLarisse Voufo } 437ded9979a2997336cee8797deb6bb3194fccc2068Eli Friedman } 43823323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 43923323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins private final List<BatchedScanRequest> mBatchedScanners = new ArrayList<BatchedScanRequest>(); 44023323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 44123323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins public boolean isBatchedScanSupported() { 44223323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins return mBatchedScanSupported; 44323323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins } 44423323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 44523323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins public void pollBatchedScan() { 44623323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins enforceChangePermission(); 4476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (mBatchedScanSupported == false) return; 4486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines mWifiStateMachine.requestBatchedScanPoll(); 44923323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins } 45023323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 45123323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins public String getWpsNfcConfigurationToken(int netId) { 45223323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins enforceConnectivityInternalPermission(); 453d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor return mWifiStateMachine.syncGetWpsNfcConfigurationToken(netId); 454686775deca8b8685eb90801495880e3abdd844c2Chris Lattner } 455d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor 456d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor /** 457d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor * see {@link android.net.wifi.WifiManager#requestBatchedScan()} 458d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor */ 459ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo public boolean requestBatchedScan(BatchedScanSettings requested, IBinder binder, 460ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo WorkSource workSource) { 461ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo enforceChangePermission(); 462ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo if (workSource != null) { 463d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor enforceWorkSourcePermission(); 464d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor // WifiManager currently doesn't use names, so need to clear names out of the 465d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor // supplied WorkSource to allow future WorkSource combining. 466d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor workSource.clearNames(); 467d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 468d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor if (mBatchedScanSupported == false) return false; 469d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor requested = new BatchedScanSettings(requested); 470d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor if (requested.isInvalid()) return false; 471ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo BatchedScanRequest r = new BatchedScanRequest(requested, binder, workSource); 472ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo synchronized(mBatchedScanners) { 473ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo mBatchedScanners.add(r); 474ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo resolveBatchedScannersLocked(); 475d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 476d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor return true; 477d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 478d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor 479d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor public List<BatchedScanResult> getBatchedScanResults(String callingPackage) { 480d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor enforceAccessPermission(); 481d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor if (mBatchedScanSupported == false) return new ArrayList<BatchedScanResult>(); 482d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor int uid = Binder.getCallingUid(); 483ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo int userId = UserHandle.getCallingUserId(); 484ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo long ident = Binder.clearCallingIdentity(); 485ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo try { 486ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage) 487d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor != AppOpsManager.MODE_ALLOWED) { 488d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor return new ArrayList<BatchedScanResult>(); 489686775deca8b8685eb90801495880e3abdd844c2Chris Lattner } 490d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor if (!isCurrentProfile(userId)) { 491d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor return new ArrayList<BatchedScanResult>(); 492d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 493d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor return mWifiStateMachine.syncGetBatchedScanResultsList(); 494d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } finally { 495d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor Binder.restoreCallingIdentity(ident); 496d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 497d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor } 498d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor 499d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor public void stopBatchedScan(BatchedScanSettings settings) { 500ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo enforceChangePermission(); 501ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo if (mBatchedScanSupported == false) return; 502ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo stopBatchedScan(settings, getCallingUid(), getCallingPid()); 503ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo } 504c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 505ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo private void stopBatchedScan(BatchedScanSettings settings, int uid, int pid) { 5063e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith ArrayList<BatchedScanRequest> found = new ArrayList<BatchedScanRequest>(); 507d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor synchronized(mBatchedScanners) { 508d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor for (BatchedScanRequest r : mBatchedScanners) { 509d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor if (r.isSameApp(uid, pid) && (settings == null || settings.equals(r.settings))) { 510d65587f7a6d38965fa37158d3f57990a7faf3836Douglas Gregor found.add(r); 511ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo if (settings != null) break; 512ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo } 513ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo } 514ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo for (BatchedScanRequest r : found) { 515f1c66b40213784a1c4612f04c14cafa2b0e89988Richard Smith mBatchedScanners.remove(r); 5168491ffe86c50241b47c6d7ef8cd9ee00f5e675daDouglas Gregor } 517d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor if (found.size() != 0) { 518d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor resolveBatchedScannersLocked(); 519d1102433214bd33b5bef5b493944292a1e82c2fbDouglas Gregor } 520 } 521 } 522 523 private void resolveBatchedScannersLocked() { 524 BatchedScanSettings setting = new BatchedScanSettings(); 525 WorkSource responsibleWorkSource = null; 526 int responsibleUid = 0; 527 double responsibleCsph = 0; // Channel Scans Per Hour 528 529 if (mBatchedScanners.size() == 0) { 530 mWifiStateMachine.setBatchedScanSettings(null, 0, 0, null); 531 return; 532 } 533 for (BatchedScanRequest r : mBatchedScanners) { 534 BatchedScanSettings s = r.settings; 535 536 // evaluate responsibility 537 int currentChannelCount; 538 int currentScanInterval; 539 double currentCsph; 540 541 if (s.channelSet == null || s.channelSet.isEmpty()) { 542 // all channels - 11 B and 9 A channels roughly. 543 currentChannelCount = 9 + 11; 544 } else { 545 currentChannelCount = s.channelSet.size(); 546 // these are rough est - no real need to correct for reg-domain; 547 if (s.channelSet.contains("A")) currentChannelCount += (9 - 1); 548 if (s.channelSet.contains("B")) currentChannelCount += (11 - 1); 549 550 } 551 if (s.scanIntervalSec == BatchedScanSettings.UNSPECIFIED) { 552 currentScanInterval = BatchedScanSettings.DEFAULT_INTERVAL_SEC; 553 } else { 554 currentScanInterval = s.scanIntervalSec; 555 } 556 currentCsph = 60 * 60 * currentChannelCount / currentScanInterval; 557 558 if (currentCsph > responsibleCsph) { 559 responsibleUid = r.uid; 560 responsibleWorkSource = r.workSource; 561 responsibleCsph = currentCsph; 562 } 563 564 if (s.maxScansPerBatch != BatchedScanSettings.UNSPECIFIED && 565 s.maxScansPerBatch < setting.maxScansPerBatch) { 566 setting.maxScansPerBatch = s.maxScansPerBatch; 567 } 568 if (s.maxApPerScan != BatchedScanSettings.UNSPECIFIED && 569 (setting.maxApPerScan == BatchedScanSettings.UNSPECIFIED || 570 s.maxApPerScan > setting.maxApPerScan)) { 571 setting.maxApPerScan = s.maxApPerScan; 572 } 573 if (s.scanIntervalSec != BatchedScanSettings.UNSPECIFIED && 574 s.scanIntervalSec < setting.scanIntervalSec) { 575 setting.scanIntervalSec = s.scanIntervalSec; 576 } 577 if (s.maxApForDistance != BatchedScanSettings.UNSPECIFIED && 578 (setting.maxApForDistance == BatchedScanSettings.UNSPECIFIED || 579 s.maxApForDistance > setting.maxApForDistance)) { 580 setting.maxApForDistance = s.maxApForDistance; 581 } 582 if (s.channelSet != null && s.channelSet.size() != 0) { 583 if (setting.channelSet == null || setting.channelSet.size() != 0) { 584 if (setting.channelSet == null) setting.channelSet = new ArrayList<String>(); 585 for (String i : s.channelSet) { 586 if (setting.channelSet.contains(i) == false) setting.channelSet.add(i); 587 } 588 } // else, ignore the constraint - we already use all channels 589 } else { 590 if (setting.channelSet == null || setting.channelSet.size() != 0) { 591 setting.channelSet = new ArrayList<String>(); 592 } 593 } 594 } 595 596 setting.constrain(); 597 mWifiStateMachine.setBatchedScanSettings(setting, responsibleUid, (int)responsibleCsph, 598 responsibleWorkSource); 599 } 600 601 private void enforceAccessPermission() { 602 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, 603 "WifiService"); 604 } 605 606 private void enforceChangePermission() { 607 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 608 "WifiService"); 609 610 } 611 612 private void enforceReadCredentialPermission() { 613 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL, 614 "WifiService"); 615 } 616 617 private void enforceWorkSourcePermission() { 618 mContext.enforceCallingPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 619 "WifiService"); 620 621 } 622 623 private void enforceMulticastChangePermission() { 624 mContext.enforceCallingOrSelfPermission( 625 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, 626 "WifiService"); 627 } 628 629 private void enforceConnectivityInternalPermission() { 630 mContext.enforceCallingOrSelfPermission( 631 android.Manifest.permission.CONNECTIVITY_INTERNAL, 632 "ConnectivityService"); 633 } 634 635 /** 636 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} 637 * @param enable {@code true} to enable, {@code false} to disable. 638 * @return {@code true} if the enable/disable operation was 639 * started or is already in the queue. 640 */ 641 public synchronized boolean setWifiEnabled(boolean enable) { 642 enforceChangePermission(); 643 Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid() 644 + ", uid=" + Binder.getCallingUid()); 645 if (DBG) { 646 Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n"); 647 } 648 649 /* 650 * Caller might not have WRITE_SECURE_SETTINGS, 651 * only CHANGE_WIFI_STATE is enforced 652 */ 653 654 long ident = Binder.clearCallingIdentity(); 655 try { 656 if (! mSettingsStore.handleWifiToggled(enable)) { 657 // Nothing to do if wifi cannot be toggled 658 return true; 659 } 660 } finally { 661 Binder.restoreCallingIdentity(ident); 662 } 663 664 mWifiController.sendMessage(CMD_WIFI_TOGGLED); 665 return true; 666 } 667 668 /** 669 * see {@link WifiManager#getWifiState()} 670 * @return One of {@link WifiManager#WIFI_STATE_DISABLED}, 671 * {@link WifiManager#WIFI_STATE_DISABLING}, 672 * {@link WifiManager#WIFI_STATE_ENABLED}, 673 * {@link WifiManager#WIFI_STATE_ENABLING}, 674 * {@link WifiManager#WIFI_STATE_UNKNOWN} 675 */ 676 public int getWifiEnabledState() { 677 enforceAccessPermission(); 678 return mWifiStateMachine.syncGetWifiState(); 679 } 680 681 /** 682 * see {@link android.net.wifi.WifiManager#setWifiApEnabled(WifiConfiguration, boolean)} 683 * @param wifiConfig SSID, security and channel details as 684 * part of WifiConfiguration 685 * @param enabled true to enable and false to disable 686 */ 687 public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { 688 enforceChangePermission(); 689 UserManager um = UserManager.get(mContext); 690 if (um.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 691 throw new SecurityException("DISALLOW_CONFIG_TETHERING is enabled for this user."); 692 } 693 // null wifiConfig is a meaningful input for CMD_SET_AP 694 if (wifiConfig == null || wifiConfig.isValid()) { 695 mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig).sendToTarget(); 696 } else { 697 Slog.e(TAG, "Invalid WifiConfiguration"); 698 } 699 } 700 701 /** 702 * see {@link WifiManager#getWifiApState()} 703 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 704 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 705 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 706 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 707 * {@link WifiManager#WIFI_AP_STATE_FAILED} 708 */ 709 public int getWifiApEnabledState() { 710 enforceAccessPermission(); 711 return mWifiStateMachine.syncGetWifiApState(); 712 } 713 714 /** 715 * see {@link WifiManager#getWifiApConfiguration()} 716 * @return soft access point configuration 717 */ 718 public WifiConfiguration getWifiApConfiguration() { 719 enforceAccessPermission(); 720 return mWifiStateMachine.syncGetWifiApConfiguration(); 721 } 722 723 /** 724 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)} 725 * @param wifiConfig WifiConfiguration details for soft access point 726 */ 727 public void setWifiApConfiguration(WifiConfiguration wifiConfig) { 728 enforceChangePermission(); 729 if (wifiConfig == null) 730 return; 731 if (wifiConfig.isValid()) { 732 mWifiStateMachine.setWifiApConfiguration(wifiConfig); 733 } else { 734 Slog.e(TAG, "Invalid WifiConfiguration"); 735 } 736 } 737 738 /** 739 * @param enable {@code true} to enable, {@code false} to disable. 740 * @return {@code true} if the enable/disable operation was 741 * started or is already in the queue. 742 */ 743 public boolean isScanAlwaysAvailable() { 744 enforceAccessPermission(); 745 return mSettingsStore.isScanAlwaysAvailable(); 746 } 747 748 /** 749 * see {@link android.net.wifi.WifiManager#disconnect()} 750 */ 751 public void disconnect() { 752 enforceChangePermission(); 753 mWifiStateMachine.disconnectCommand(); 754 } 755 756 /** 757 * see {@link android.net.wifi.WifiManager#reconnect()} 758 */ 759 public void reconnect() { 760 enforceChangePermission(); 761 mWifiStateMachine.reconnectCommand(); 762 } 763 764 /** 765 * see {@link android.net.wifi.WifiManager#reassociate()} 766 */ 767 public void reassociate() { 768 enforceChangePermission(); 769 mWifiStateMachine.reassociateCommand(); 770 } 771 772 /** 773 * see {@link android.net.wifi.WifiManager#getAdaptors} 774 */ 775 public List<WifiAdapter> getAdaptors() { 776 enforceAccessPermission(); 777 if (mWifiStateMachineChannel != null) { 778 return mWifiStateMachine.syncGetAdaptors(mWifiStateMachineChannel); 779 } else { 780 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 781 return null; 782 } 783 } 784 785 /** 786 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()} 787 * @return the list of configured networks 788 */ 789 public List<WifiConfiguration> getConfiguredNetworks() { 790 enforceAccessPermission(); 791 if (mWifiStateMachineChannel != null) { 792 return mWifiStateMachine.syncGetConfiguredNetworks(mWifiStateMachineChannel); 793 } else { 794 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 795 return null; 796 } 797 } 798 799 /** 800 * see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()} 801 * @return the list of configured networks with real preSharedKey 802 */ 803 public List<WifiConfiguration> getPrivilegedConfiguredNetworks() { 804 enforceReadCredentialPermission(); 805 enforceAccessPermission(); 806 if (mWifiStateMachineChannel != null) { 807 return mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 808 } else { 809 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 810 return null; 811 } 812 } 813 814 /** 815 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)} 816 * @return the supplicant-assigned identifier for the new or updated 817 * network if the operation succeeds, or {@code -1} if it fails 818 */ 819 public int addOrUpdateNetwork(WifiConfiguration config) { 820 enforceChangePermission(); 821 if (config.isValid()) { 822 //TODO: pass the Uid the WifiStateMachine as a message parameter 823 Slog.e("addOrUpdateNetwork", " uid = " + Integer.toString(Binder.getCallingUid()) 824 + " SSID " + config.SSID 825 + " nid=" + Integer.toString(config.networkId)); 826 if (config.networkId == WifiConfiguration.INVALID_NETWORK_ID) { 827 config.creatorUid = Binder.getCallingUid(); 828 } else { 829 config.lastUpdateUid = Binder.getCallingUid(); 830 } 831 if (mWifiStateMachineChannel != null) { 832 return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config); 833 } else { 834 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 835 return -1; 836 } 837 } else { 838 Slog.e(TAG, "bad network configuration"); 839 return -1; 840 } 841 } 842 843 /** 844 * See {@link android.net.wifi.WifiManager#removeNetwork(int)} 845 * @param netId the integer that identifies the network configuration 846 * to the supplicant 847 * @return {@code true} if the operation succeeded 848 */ 849 public boolean removeNetwork(int netId) { 850 enforceChangePermission(); 851 852 if (!isOwner(Binder.getCallingUid())) { 853 Slog.e(TAG, "Remove is not authorized for user"); 854 return false; 855 } 856 857 if (mWifiStateMachineChannel != null) { 858 return mWifiStateMachine.syncRemoveNetwork(mWifiStateMachineChannel, netId); 859 } else { 860 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 861 return false; 862 } 863 } 864 865 /** 866 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)} 867 * @param netId the integer that identifies the network configuration 868 * to the supplicant 869 * @param disableOthers if true, disable all other networks. 870 * @return {@code true} if the operation succeeded 871 */ 872 public boolean enableNetwork(int netId, boolean disableOthers) { 873 enforceChangePermission(); 874 if (mWifiStateMachineChannel != null) { 875 return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId, 876 disableOthers); 877 } else { 878 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 879 return false; 880 } 881 } 882 883 /** 884 * See {@link android.net.wifi.WifiManager#disableNetwork(int)} 885 * @param netId the integer that identifies the network configuration 886 * to the supplicant 887 * @return {@code true} if the operation succeeded 888 */ 889 public boolean disableNetwork(int netId) { 890 enforceChangePermission(); 891 if (mWifiStateMachineChannel != null) { 892 return mWifiStateMachine.syncDisableNetwork(mWifiStateMachineChannel, netId); 893 } else { 894 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 895 return false; 896 } 897 } 898 899 /** 900 * See {@link android.net.wifi.WifiManager#getConnectionInfo()} 901 * @return the Wi-Fi information, contained in {@link WifiInfo}. 902 */ 903 public WifiInfo getConnectionInfo() { 904 enforceAccessPermission(); 905 /* 906 * Make sure we have the latest information, by sending 907 * a status request to the supplicant. 908 */ 909 return mWifiStateMachine.syncRequestConnectionInfo(); 910 } 911 912 /** 913 * Return the results of the most recent access point scan, in the form of 914 * a list of {@link ScanResult} objects. 915 * @return the list of results 916 */ 917 public List<ScanResult> getScanResults(String callingPackage) { 918 enforceAccessPermission(); 919 int userId = UserHandle.getCallingUserId(); 920 int uid = Binder.getCallingUid(); 921 long ident = Binder.clearCallingIdentity(); 922 try { 923 if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage) 924 != AppOpsManager.MODE_ALLOWED) { 925 return new ArrayList<ScanResult>(); 926 } 927 if (!isCurrentProfile(userId)) { 928 return new ArrayList<ScanResult>(); 929 } 930 return mWifiStateMachine.syncGetScanResultsList(); 931 } finally { 932 Binder.restoreCallingIdentity(ident); 933 } 934 } 935 936 /** 937 * Returns true if the calling user is the current one or a profile of the 938 * current user.. 939 */ 940 private boolean isCurrentProfile(int userId) { 941 int currentUser = ActivityManager.getCurrentUser(); 942 if (userId == currentUser) { 943 return true; 944 } 945 List<UserInfo> profiles = UserManager.get(mContext).getProfiles(currentUser); 946 for (UserInfo user : profiles) { 947 if (userId == user.id) { 948 return true; 949 } 950 } 951 return false; 952 } 953 954 /** 955 * Returns true if uid is an application running under the owner or a profile of the owner. 956 * 957 * Note: Should not be called if identity is cleared. 958 */ 959 private boolean isOwner(int uid) { 960 long ident = Binder.clearCallingIdentity(); 961 int userId = UserHandle.getUserId(uid); 962 try { 963 int ownerUser = UserHandle.USER_OWNER; 964 if (userId == ownerUser) { 965 return true; 966 } 967 List<UserInfo> profiles = UserManager.get(mContext).getProfiles(ownerUser); 968 for (UserInfo profile : profiles) { 969 if (userId == profile.id) { 970 return true; 971 } 972 } 973 return false; 974 } 975 finally { 976 Binder.restoreCallingIdentity(ident); 977 } 978 } 979 980 981 /** 982 * Tell the supplicant to persist the current list of configured networks. 983 * @return {@code true} if the operation succeeded 984 * 985 * TODO: deprecate this 986 */ 987 public boolean saveConfiguration() { 988 boolean result = true; 989 enforceChangePermission(); 990 if (mWifiStateMachineChannel != null) { 991 return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel); 992 } else { 993 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 994 return false; 995 } 996 } 997 998 /** 999 * Set the country code 1000 * @param countryCode ISO 3166 country code. 1001 * @param persist {@code true} if the setting should be remembered. 1002 * 1003 * The persist behavior exists so that wifi can fall back to the last 1004 * persisted country code on a restart, when the locale information is 1005 * not available from telephony. 1006 */ 1007 public void setCountryCode(String countryCode, boolean persist) { 1008 Slog.i(TAG, "WifiService trying to set country code to " + countryCode + 1009 " with persist set to " + persist); 1010 enforceConnectivityInternalPermission(); 1011 final long token = Binder.clearCallingIdentity(); 1012 try { 1013 mWifiStateMachine.setCountryCode(countryCode, persist); 1014 } finally { 1015 Binder.restoreCallingIdentity(token); 1016 } 1017 } 1018 1019 /** 1020 * Set the operational frequency band 1021 * @param band One of 1022 * {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO}, 1023 * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ}, 1024 * {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ}, 1025 * @param persist {@code true} if the setting should be remembered. 1026 * 1027 */ 1028 public void setFrequencyBand(int band, boolean persist) { 1029 enforceChangePermission(); 1030 if (!isDualBandSupported()) return; 1031 Slog.i(TAG, "WifiService trying to set frequency band to " + band + 1032 " with persist set to " + persist); 1033 final long token = Binder.clearCallingIdentity(); 1034 try { 1035 mWifiStateMachine.setFrequencyBand(band, persist); 1036 } finally { 1037 Binder.restoreCallingIdentity(token); 1038 } 1039 } 1040 1041 1042 /** 1043 * Get the operational frequency band 1044 */ 1045 public int getFrequencyBand() { 1046 enforceAccessPermission(); 1047 return mWifiStateMachine.getFrequencyBand(); 1048 } 1049 1050 public boolean isDualBandSupported() { 1051 //TODO: Should move towards adding a driver API that checks at runtime 1052 return mContext.getResources().getBoolean( 1053 com.android.internal.R.bool.config_wifi_dual_band_support); 1054 } 1055 1056 /** 1057 * Return the DHCP-assigned addresses from the last successful DHCP request, 1058 * if any. 1059 * @return the DHCP information 1060 * @deprecated 1061 */ 1062 public DhcpInfo getDhcpInfo() { 1063 enforceAccessPermission(); 1064 DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults(); 1065 1066 DhcpInfo info = new DhcpInfo(); 1067 1068 if (dhcpResults.ipAddress != null && 1069 dhcpResults.ipAddress.getAddress() instanceof Inet4Address) { 1070 info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.ipAddress.getAddress()); 1071 } 1072 1073 if (dhcpResults.gateway != null) { 1074 info.gateway = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.gateway); 1075 } 1076 1077 int dnsFound = 0; 1078 for (InetAddress dns : dhcpResults.dnsServers) { 1079 if (dns instanceof Inet4Address) { 1080 if (dnsFound == 0) { 1081 info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1082 } else { 1083 info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1084 } 1085 if (++dnsFound > 1) break; 1086 } 1087 } 1088 InetAddress serverAddress = dhcpResults.serverAddress; 1089 if (serverAddress instanceof Inet4Address) { 1090 info.serverAddress = NetworkUtils.inetAddressToInt((Inet4Address)serverAddress); 1091 } 1092 info.leaseDuration = dhcpResults.leaseDuration; 1093 1094 return info; 1095 } 1096 1097 /** 1098 * see {@link android.net.wifi.WifiManager#startWifi} 1099 * 1100 */ 1101 public void startWifi() { 1102 enforceConnectivityInternalPermission(); 1103 /* TODO: may be add permissions for access only to connectivity service 1104 * TODO: if a start issued, keep wifi alive until a stop issued irrespective 1105 * of WifiLock & device idle status unless wifi enabled status is toggled 1106 */ 1107 1108 mWifiStateMachine.setDriverStart(true); 1109 mWifiStateMachine.reconnectCommand(); 1110 } 1111 1112 /** 1113 * see {@link android.net.wifi.WifiManager#stopWifi} 1114 * 1115 */ 1116 public void stopWifi() { 1117 enforceConnectivityInternalPermission(); 1118 /* 1119 * TODO: if a stop is issued, wifi is brought up only by startWifi 1120 * unless wifi enabled status is toggled 1121 */ 1122 mWifiStateMachine.setDriverStart(false); 1123 } 1124 1125 /** 1126 * see {@link android.net.wifi.WifiManager#addToBlacklist} 1127 * 1128 */ 1129 public void addToBlacklist(String bssid) { 1130 enforceChangePermission(); 1131 1132 mWifiStateMachine.addToBlacklist(bssid); 1133 } 1134 1135 /** 1136 * see {@link android.net.wifi.WifiManager#clearBlacklist} 1137 * 1138 */ 1139 public void clearBlacklist() { 1140 enforceChangePermission(); 1141 1142 mWifiStateMachine.clearBlacklist(); 1143 } 1144 1145 /** 1146 * enable TDLS for the local NIC to remote NIC 1147 * The APPs don't know the remote MAC address to identify NIC though, 1148 * so we need to do additional work to find it from remote IP address 1149 */ 1150 1151 class TdlsTaskParams { 1152 public String remoteIpAddress; 1153 public boolean enable; 1154 } 1155 1156 class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> { 1157 @Override 1158 protected Integer doInBackground(TdlsTaskParams... params) { 1159 1160 // Retrieve parameters for the call 1161 TdlsTaskParams param = params[0]; 1162 String remoteIpAddress = param.remoteIpAddress.trim(); 1163 boolean enable = param.enable; 1164 1165 // Get MAC address of Remote IP 1166 String macAddress = null; 1167 1168 BufferedReader reader = null; 1169 1170 try { 1171 reader = new BufferedReader(new FileReader("/proc/net/arp")); 1172 1173 // Skip over the line bearing colum titles 1174 String line = reader.readLine(); 1175 1176 while ((line = reader.readLine()) != null) { 1177 String[] tokens = line.split("[ ]+"); 1178 if (tokens.length < 6) { 1179 continue; 1180 } 1181 1182 // ARP column format is 1183 // Address HWType HWAddress Flags Mask IFace 1184 String ip = tokens[0]; 1185 String mac = tokens[3]; 1186 1187 if (remoteIpAddress.equals(ip)) { 1188 macAddress = mac; 1189 break; 1190 } 1191 } 1192 1193 if (macAddress == null) { 1194 Slog.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " + 1195 "/proc/net/arp"); 1196 } else { 1197 enableTdlsWithMacAddress(macAddress, enable); 1198 } 1199 1200 } catch (FileNotFoundException e) { 1201 Slog.e(TAG, "Could not open /proc/net/arp to lookup mac address"); 1202 } catch (IOException e) { 1203 Slog.e(TAG, "Could not read /proc/net/arp to lookup mac address"); 1204 } finally { 1205 try { 1206 if (reader != null) { 1207 reader.close(); 1208 } 1209 } 1210 catch (IOException e) { 1211 // Do nothing 1212 } 1213 } 1214 1215 return 0; 1216 } 1217 } 1218 1219 public void enableTdls(String remoteAddress, boolean enable) { 1220 if (remoteAddress == null) { 1221 throw new IllegalArgumentException("remoteAddress cannot be null"); 1222 } 1223 1224 TdlsTaskParams params = new TdlsTaskParams(); 1225 params.remoteIpAddress = remoteAddress; 1226 params.enable = enable; 1227 new TdlsTask().execute(params); 1228 } 1229 1230 1231 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { 1232 if (remoteMacAddress == null) { 1233 throw new IllegalArgumentException("remoteMacAddress cannot be null"); 1234 } 1235 1236 mWifiStateMachine.enableTdls(remoteMacAddress, enable); 1237 } 1238 1239 /** 1240 * Get a reference to handler. This is used by a client to establish 1241 * an AsyncChannel communication with WifiService 1242 */ 1243 public Messenger getWifiServiceMessenger() { 1244 enforceAccessPermission(); 1245 enforceChangePermission(); 1246 return new Messenger(mClientHandler); 1247 } 1248 1249 1250 /** 1251 * Get the IP and proxy configuration file 1252 */ 1253 public String getConfigFile() { 1254 enforceAccessPermission(); 1255 return mWifiStateMachine.getConfigFile(); 1256 } 1257 1258 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1259 @Override 1260 public void onReceive(Context context, Intent intent) { 1261 String action = intent.getAction(); 1262 if (action.equals(Intent.ACTION_SCREEN_ON)) { 1263 mWifiController.sendMessage(CMD_SCREEN_ON); 1264 } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1265 mWifiController.sendMessage(CMD_USER_PRESENT); 1266 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1267 mWifiController.sendMessage(CMD_SCREEN_OFF); 1268 } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 1269 int pluggedType = intent.getIntExtra("plugged", 0); 1270 mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null); 1271 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { 1272 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 1273 BluetoothAdapter.STATE_DISCONNECTED); 1274 mWifiStateMachine.sendBluetoothAdapterStateChange(state); 1275 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 1276 boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false); 1277 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0); 1278 } 1279 } 1280 }; 1281 1282 /** 1283 * Observes settings changes to scan always mode. 1284 */ 1285 private void registerForScanModeChange() { 1286 ContentObserver contentObserver = new ContentObserver(null) { 1287 @Override 1288 public void onChange(boolean selfChange) { 1289 mSettingsStore.handleWifiScanAlwaysAvailableToggled(); 1290 mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED); 1291 } 1292 }; 1293 1294 mContext.getContentResolver().registerContentObserver( 1295 Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE), 1296 false, contentObserver); 1297 } 1298 1299 private void registerForBroadcasts() { 1300 IntentFilter intentFilter = new IntentFilter(); 1301 intentFilter.addAction(Intent.ACTION_SCREEN_ON); 1302 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 1303 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 1304 intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); 1305 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 1306 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 1307 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 1308 mContext.registerReceiver(mReceiver, intentFilter); 1309 } 1310 1311 @Override 1312 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1313 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1314 != PackageManager.PERMISSION_GRANTED) { 1315 pw.println("Permission Denial: can't dump WifiService from from pid=" 1316 + Binder.getCallingPid() 1317 + ", uid=" + Binder.getCallingUid()); 1318 return; 1319 } 1320 pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName()); 1321 pw.println("Stay-awake conditions: " + 1322 Settings.Global.getInt(mContext.getContentResolver(), 1323 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); 1324 pw.println("mMulticastEnabled " + mMulticastEnabled); 1325 pw.println("mMulticastDisabled " + mMulticastDisabled); 1326 mWifiController.dump(fd, pw, args); 1327 mSettingsStore.dump(fd, pw, args); 1328 mNotificationController.dump(fd, pw, args); 1329 mTrafficPoller.dump(fd, pw, args); 1330 1331 pw.println("Latest scan results:"); 1332 List<ScanResult> scanResults = mWifiStateMachine.syncGetScanResultsList(); 1333 if (scanResults != null && scanResults.size() != 0) { 1334 pw.println(" BSSID Frequency RSSI Flags SSID"); 1335 for (ScanResult r : scanResults) { 1336 pw.printf(" %17s %9d %5d %-16s %s%n", 1337 r.BSSID, 1338 r.frequency, 1339 r.level, 1340 r.capabilities, 1341 r.SSID == null ? "" : r.SSID); 1342 } 1343 } 1344 pw.println(); 1345 pw.println("Locks acquired: " + mFullLocksAcquired + " full, " + 1346 mFullHighPerfLocksAcquired + " full high perf, " + 1347 mScanLocksAcquired + " scan"); 1348 pw.println("Locks released: " + mFullLocksReleased + " full, " + 1349 mFullHighPerfLocksReleased + " full high perf, " + 1350 mScanLocksReleased + " scan"); 1351 pw.println(); 1352 pw.println("Locks held:"); 1353 mLocks.dump(pw); 1354 1355 mWifiWatchdogStateMachine.dump(fd, pw, args); 1356 pw.println(); 1357 mWifiStateMachine.dump(fd, pw, args); 1358 pw.println(); 1359 } 1360 1361 private class WifiLock extends DeathRecipient { 1362 WifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) { 1363 super(lockMode, tag, binder, ws); 1364 } 1365 1366 public void binderDied() { 1367 synchronized (mLocks) { 1368 releaseWifiLockLocked(mBinder); 1369 } 1370 } 1371 1372 public String toString() { 1373 return "WifiLock{" + mTag + " type=" + mMode + " binder=" + mBinder + "}"; 1374 } 1375 } 1376 1377 class LockList { 1378 private List<WifiLock> mList; 1379 1380 private LockList() { 1381 mList = new ArrayList<WifiLock>(); 1382 } 1383 1384 synchronized boolean hasLocks() { 1385 return !mList.isEmpty(); 1386 } 1387 1388 synchronized int getStrongestLockMode() { 1389 if (mList.isEmpty()) { 1390 return WifiManager.WIFI_MODE_FULL; 1391 } 1392 1393 if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) { 1394 return WifiManager.WIFI_MODE_FULL_HIGH_PERF; 1395 } 1396 1397 if (mFullLocksAcquired > mFullLocksReleased) { 1398 return WifiManager.WIFI_MODE_FULL; 1399 } 1400 1401 return WifiManager.WIFI_MODE_SCAN_ONLY; 1402 } 1403 1404 synchronized void updateWorkSource(WorkSource ws) { 1405 for (int i = 0; i < mLocks.mList.size(); i++) { 1406 ws.add(mLocks.mList.get(i).mWorkSource); 1407 } 1408 } 1409 1410 private void addLock(WifiLock lock) { 1411 if (findLockByBinder(lock.mBinder) < 0) { 1412 mList.add(lock); 1413 } 1414 } 1415 1416 private WifiLock removeLock(IBinder binder) { 1417 int index = findLockByBinder(binder); 1418 if (index >= 0) { 1419 WifiLock ret = mList.remove(index); 1420 ret.unlinkDeathRecipient(); 1421 return ret; 1422 } else { 1423 return null; 1424 } 1425 } 1426 1427 private int findLockByBinder(IBinder binder) { 1428 int size = mList.size(); 1429 for (int i = size - 1; i >= 0; i--) { 1430 if (mList.get(i).mBinder == binder) 1431 return i; 1432 } 1433 return -1; 1434 } 1435 1436 private void dump(PrintWriter pw) { 1437 for (WifiLock l : mList) { 1438 pw.print(" "); 1439 pw.println(l); 1440 } 1441 } 1442 } 1443 1444 void enforceWakeSourcePermission(int uid, int pid) { 1445 if (uid == android.os.Process.myUid()) { 1446 return; 1447 } 1448 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 1449 pid, uid, null); 1450 } 1451 1452 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) { 1453 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 1454 if (lockMode != WifiManager.WIFI_MODE_FULL && 1455 lockMode != WifiManager.WIFI_MODE_SCAN_ONLY && 1456 lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF) { 1457 Slog.e(TAG, "Illegal argument, lockMode= " + lockMode); 1458 if (DBG) throw new IllegalArgumentException("lockMode=" + lockMode); 1459 return false; 1460 } 1461 if (ws != null && ws.size() == 0) { 1462 ws = null; 1463 } 1464 if (ws != null) { 1465 enforceWakeSourcePermission(Binder.getCallingUid(), Binder.getCallingPid()); 1466 } 1467 if (ws == null) { 1468 ws = new WorkSource(Binder.getCallingUid()); 1469 } 1470 WifiLock wifiLock = new WifiLock(lockMode, tag, binder, ws); 1471 synchronized (mLocks) { 1472 return acquireWifiLockLocked(wifiLock); 1473 } 1474 } 1475 1476 private void noteAcquireWifiLock(WifiLock wifiLock) throws RemoteException { 1477 switch(wifiLock.mMode) { 1478 case WifiManager.WIFI_MODE_FULL: 1479 case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 1480 case WifiManager.WIFI_MODE_SCAN_ONLY: 1481 mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource); 1482 break; 1483 } 1484 } 1485 1486 private void noteReleaseWifiLock(WifiLock wifiLock) throws RemoteException { 1487 switch(wifiLock.mMode) { 1488 case WifiManager.WIFI_MODE_FULL: 1489 case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 1490 case WifiManager.WIFI_MODE_SCAN_ONLY: 1491 mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource); 1492 break; 1493 } 1494 } 1495 1496 private boolean acquireWifiLockLocked(WifiLock wifiLock) { 1497 if (DBG) Slog.d(TAG, "acquireWifiLockLocked: " + wifiLock); 1498 1499 mLocks.addLock(wifiLock); 1500 1501 long ident = Binder.clearCallingIdentity(); 1502 try { 1503 noteAcquireWifiLock(wifiLock); 1504 switch(wifiLock.mMode) { 1505 case WifiManager.WIFI_MODE_FULL: 1506 ++mFullLocksAcquired; 1507 break; 1508 case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 1509 ++mFullHighPerfLocksAcquired; 1510 break; 1511 1512 case WifiManager.WIFI_MODE_SCAN_ONLY: 1513 ++mScanLocksAcquired; 1514 break; 1515 } 1516 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1517 return true; 1518 } catch (RemoteException e) { 1519 return false; 1520 } finally { 1521 Binder.restoreCallingIdentity(ident); 1522 } 1523 } 1524 1525 public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) { 1526 int uid = Binder.getCallingUid(); 1527 int pid = Binder.getCallingPid(); 1528 if (ws != null && ws.size() == 0) { 1529 ws = null; 1530 } 1531 if (ws != null) { 1532 enforceWakeSourcePermission(uid, pid); 1533 } 1534 long ident = Binder.clearCallingIdentity(); 1535 try { 1536 synchronized (mLocks) { 1537 int index = mLocks.findLockByBinder(lock); 1538 if (index < 0) { 1539 throw new IllegalArgumentException("Wifi lock not active"); 1540 } 1541 WifiLock wl = mLocks.mList.get(index); 1542 noteReleaseWifiLock(wl); 1543 wl.mWorkSource = ws != null ? new WorkSource(ws) : new WorkSource(uid); 1544 noteAcquireWifiLock(wl); 1545 } 1546 } catch (RemoteException e) { 1547 } finally { 1548 Binder.restoreCallingIdentity(ident); 1549 } 1550 } 1551 1552 public boolean releaseWifiLock(IBinder lock) { 1553 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 1554 synchronized (mLocks) { 1555 return releaseWifiLockLocked(lock); 1556 } 1557 } 1558 1559 private boolean releaseWifiLockLocked(IBinder lock) { 1560 boolean hadLock; 1561 1562 WifiLock wifiLock = mLocks.removeLock(lock); 1563 1564 if (DBG) Slog.d(TAG, "releaseWifiLockLocked: " + wifiLock); 1565 1566 hadLock = (wifiLock != null); 1567 1568 long ident = Binder.clearCallingIdentity(); 1569 try { 1570 if (hadLock) { 1571 noteReleaseWifiLock(wifiLock); 1572 switch(wifiLock.mMode) { 1573 case WifiManager.WIFI_MODE_FULL: 1574 ++mFullLocksReleased; 1575 break; 1576 case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 1577 ++mFullHighPerfLocksReleased; 1578 break; 1579 case WifiManager.WIFI_MODE_SCAN_ONLY: 1580 ++mScanLocksReleased; 1581 break; 1582 } 1583 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1584 } 1585 } catch (RemoteException e) { 1586 } finally { 1587 Binder.restoreCallingIdentity(ident); 1588 } 1589 1590 return hadLock; 1591 } 1592 1593 private abstract class DeathRecipient 1594 implements IBinder.DeathRecipient { 1595 String mTag; 1596 int mMode; 1597 IBinder mBinder; 1598 WorkSource mWorkSource; 1599 1600 DeathRecipient(int mode, String tag, IBinder binder, WorkSource ws) { 1601 super(); 1602 mTag = tag; 1603 mMode = mode; 1604 mBinder = binder; 1605 mWorkSource = ws; 1606 try { 1607 mBinder.linkToDeath(this, 0); 1608 } catch (RemoteException e) { 1609 binderDied(); 1610 } 1611 } 1612 1613 void unlinkDeathRecipient() { 1614 mBinder.unlinkToDeath(this, 0); 1615 } 1616 } 1617 1618 private class Multicaster extends DeathRecipient { 1619 Multicaster(String tag, IBinder binder) { 1620 super(Binder.getCallingUid(), tag, binder, null); 1621 } 1622 1623 public void binderDied() { 1624 Slog.e(TAG, "Multicaster binderDied"); 1625 synchronized (mMulticasters) { 1626 int i = mMulticasters.indexOf(this); 1627 if (i != -1) { 1628 removeMulticasterLocked(i, mMode); 1629 } 1630 } 1631 } 1632 1633 public String toString() { 1634 return "Multicaster{" + mTag + " binder=" + mBinder + "}"; 1635 } 1636 1637 public int getUid() { 1638 return mMode; 1639 } 1640 } 1641 1642 public void initializeMulticastFiltering() { 1643 enforceMulticastChangePermission(); 1644 1645 synchronized (mMulticasters) { 1646 // if anybody had requested filters be off, leave off 1647 if (mMulticasters.size() != 0) { 1648 return; 1649 } else { 1650 mWifiStateMachine.startFilteringMulticastV4Packets(); 1651 } 1652 } 1653 } 1654 1655 public void acquireMulticastLock(IBinder binder, String tag) { 1656 enforceMulticastChangePermission(); 1657 1658 synchronized (mMulticasters) { 1659 mMulticastEnabled++; 1660 mMulticasters.add(new Multicaster(tag, binder)); 1661 // Note that we could call stopFilteringMulticastV4Packets only when 1662 // our new size == 1 (first call), but this function won't 1663 // be called often and by making the stopPacket call each 1664 // time we're less fragile and self-healing. 1665 mWifiStateMachine.stopFilteringMulticastV4Packets(); 1666 } 1667 1668 int uid = Binder.getCallingUid(); 1669 final long ident = Binder.clearCallingIdentity(); 1670 try { 1671 mBatteryStats.noteWifiMulticastEnabled(uid); 1672 } catch (RemoteException e) { 1673 } finally { 1674 Binder.restoreCallingIdentity(ident); 1675 } 1676 } 1677 1678 public void releaseMulticastLock() { 1679 enforceMulticastChangePermission(); 1680 1681 int uid = Binder.getCallingUid(); 1682 synchronized (mMulticasters) { 1683 mMulticastDisabled++; 1684 int size = mMulticasters.size(); 1685 for (int i = size - 1; i >= 0; i--) { 1686 Multicaster m = mMulticasters.get(i); 1687 if ((m != null) && (m.getUid() == uid)) { 1688 removeMulticasterLocked(i, uid); 1689 } 1690 } 1691 } 1692 } 1693 1694 private void removeMulticasterLocked(int i, int uid) 1695 { 1696 Multicaster removed = mMulticasters.remove(i); 1697 1698 if (removed != null) { 1699 removed.unlinkDeathRecipient(); 1700 } 1701 if (mMulticasters.size() == 0) { 1702 mWifiStateMachine.startFilteringMulticastV4Packets(); 1703 } 1704 1705 final long ident = Binder.clearCallingIdentity(); 1706 try { 1707 mBatteryStats.noteWifiMulticastDisabled(uid); 1708 } catch (RemoteException e) { 1709 } finally { 1710 Binder.restoreCallingIdentity(ident); 1711 } 1712 } 1713 1714 public boolean isMulticastEnabled() { 1715 enforceAccessPermission(); 1716 1717 synchronized (mMulticasters) { 1718 return (mMulticasters.size() > 0); 1719 } 1720 } 1721 1722 public WifiMonitor getWifiMonitor() { 1723 return mWifiStateMachine.getWifiMonitor(); 1724 } 1725 1726 1727 public void enableVerboseLogging(int verbose) { 1728 enforceAccessPermission(); 1729 mWifiStateMachine.enableVerboseLogging(verbose); 1730 } 1731 1732 public int getVerboseLoggingLevel() { 1733 enforceAccessPermission(); 1734 return mWifiStateMachine.getVerboseLoggingLevel(); 1735 } 1736 1737 public void enableAggressiveHandover(int enabled) { 1738 enforceAccessPermission(); 1739 mWifiStateMachine.enableAggressiveHandover(enabled); 1740 } 1741 1742 public int getAggressiveHandover() { 1743 enforceAccessPermission(); 1744 return mWifiStateMachine.getAggressiveHandover(); 1745 } 1746 1747 public void setAllowScansWithTraffic(int enabled) { 1748 enforceAccessPermission(); 1749 mWifiStateMachine.setAllowScansWithTraffic(enabled); 1750 } 1751 1752 public int getAllowScansWithTraffic() { 1753 enforceAccessPermission(); 1754 return mWifiStateMachine.getAllowScansWithTraffic(); 1755 } 1756 1757 /* Return the Wifi Connection statistics object */ 1758 public WifiConnectionStatistics getConnectionStatistics() { 1759 enforceAccessPermission(); 1760 enforceReadCredentialPermission(); 1761 if (mWifiStateMachineChannel != null) { 1762 return mWifiStateMachine.syncGetConnectionStatistics(mWifiStateMachineChannel); 1763 } else { 1764 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1765 return null; 1766 } 1767 } 1768} 1769