12a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein/* 22a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * Copyright (C) 2016 The Android Open Source Project 32a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * 42a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * Licensed under the Apache License, Version 2.0 (the "License"); 52a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * you may not use this file except in compliance with the License. 62a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * You may obtain a copy of the License at 72a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * 82a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * http://www.apache.org/licenses/LICENSE-2.0 92a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * 102a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * Unless required by applicable law or agreed to in writing, software 112a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * distributed under the License is distributed on an "AS IS" BASIS, 122a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * See the License for the specific language governing permissions and 142a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * limitations under the License. 152a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein */ 162a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 172a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinpackage com.android.server.wifi; 182a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 192a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport android.content.Context; 202a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport android.net.wifi.WifiManager; 212a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport android.os.Binder; 222a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport android.os.IBinder; 232a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport android.os.RemoteException; 242a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport android.os.WorkSource; 252a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport android.util.Slog; 262a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 272a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport com.android.internal.app.IBatteryStats; 282a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 292a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport java.io.PrintWriter; 302a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport java.util.ArrayList; 312a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinimport java.util.List; 322a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 332a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein/** 342a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * WifiLockManager maintains the list of wake locks held by different applications. 352a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein */ 362a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silbersteinpublic class WifiLockManager { 372a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private static final String TAG = "WifiLockManager"; 382a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private boolean mVerboseLoggingEnabled = false; 392a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 402a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private final Context mContext; 412a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private final IBatteryStats mBatteryStats; 422a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 432a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private final List<WifiLock> mWifiLocks = new ArrayList<>(); 442a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein // some wifi lock statistics 452a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private int mFullHighPerfLocksAcquired; 462a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private int mFullHighPerfLocksReleased; 472a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private int mFullLocksAcquired; 482a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private int mFullLocksReleased; 492a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private int mScanLocksAcquired; 502a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private int mScanLocksReleased; 512a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 522a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein WifiLockManager(Context context, IBatteryStats batteryStats) { 532a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mContext = context; 542a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mBatteryStats = batteryStats; 552a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 562a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 572a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein /** 582a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * Method allowing a calling app to acquire a Wifi WakeLock in the supplied mode. 592a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * 602a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * This method verifies that the caller has permission to make the call and that the lock mode 612a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * is a valid WifiLock mode. 622a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @param lockMode int representation of the Wifi WakeLock type. 632a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @param tag String passed to WifiManager.WifiLock 642a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @param binder IBinder for the calling app 652a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @param ws WorkSource of the calling app 662a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * 672a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @return true if the lock was successfully acquired, false if the lockMode was invalid. 682a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein */ 692a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein public boolean acquireWifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) { 702a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 712a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (!isValidLockMode(lockMode)) { 722a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein throw new IllegalArgumentException("lockMode =" + lockMode); 732a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 74fd828776e37a5a8405a9ce0d4175d7971efbedcdNarayan Kamath if (ws == null || ws.isEmpty()) { 752a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein ws = new WorkSource(Binder.getCallingUid()); 762a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } else { 772a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mContext.enforceCallingOrSelfPermission( 782a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein android.Manifest.permission.UPDATE_DEVICE_STATS, null); 792a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 802a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return addLock(new WifiLock(lockMode, tag, binder, ws)); 812a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 822a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 832a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein /** 842a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * Method used by applications to release a WiFi Wake lock. This method checks permissions for 852a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * the caller and if allowed, releases the underlying WifiLock(s). 862a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * 872a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @param binder IBinder for the calling app. 882a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @return true if the lock was released, false if the caller did not hold any locks 892a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein */ 902a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein public boolean releaseWifiLock(IBinder binder) { 912a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 922a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return releaseLock(binder); 932a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 942a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 952a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein /** 962a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * Method used to get the strongest lock type currently held by the WifiLockManager. 972a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * 982a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * If no locks are held, WifiManager.WIFI_MODE_NO_LOCKS_HELD is returned. 992a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * 1002a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @return int representing the currently held (highest power consumption) lock. 1012a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein */ 1022a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein public synchronized int getStrongestLockMode() { 1032a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (mWifiLocks.isEmpty()) { 1042a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return WifiManager.WIFI_MODE_NO_LOCKS_HELD; 1052a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1062a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1072a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) { 1082a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return WifiManager.WIFI_MODE_FULL_HIGH_PERF; 1092a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1102a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1112a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (mFullLocksAcquired > mFullLocksReleased) { 1122a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return WifiManager.WIFI_MODE_FULL; 1132a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1142a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1152a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return WifiManager.WIFI_MODE_SCAN_ONLY; 1162a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1172a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1182a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein /** 1192a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * Method to create a WorkSource containing all active WifiLock WorkSources. 1202a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein */ 1212a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein public synchronized WorkSource createMergedWorkSource() { 1222a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein WorkSource mergedWS = new WorkSource(); 1232a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein for (WifiLock lock : mWifiLocks) { 1242a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mergedWS.add(lock.getWorkSource()); 1252a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1262a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return mergedWS; 1272a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1282a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1292a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein /** 1302a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * Method used to update WifiLocks with a new WorkSouce. 1312a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * 1322a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @param binder IBinder for the calling application. 1332a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein * @param ws WorkSource to add to the existing WifiLock(s). 1342a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein */ 1352a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein public synchronized void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { 1362a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein // Does the caller have permission to make this call? 1372a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mContext.enforceCallingOrSelfPermission( 1382a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein android.Manifest.permission.UPDATE_DEVICE_STATS, null); 1392a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1402a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein // Now check if there is an active lock 1412a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein WifiLock wl = findLockByBinder(binder); 1422a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (wl == null) { 1432a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein throw new IllegalArgumentException("Wifi lock not active"); 1442a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1452a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1462a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein WorkSource newWorkSource; 147fd828776e37a5a8405a9ce0d4175d7971efbedcdNarayan Kamath if (ws == null || ws.isEmpty()) { 1482a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein newWorkSource = new WorkSource(Binder.getCallingUid()); 1492a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } else { 1502a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein // Make a copy of the WorkSource before adding it to the WakeLock 1512a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein newWorkSource = new WorkSource(ws); 1522a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1532a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 154fd828776e37a5a8405a9ce0d4175d7971efbedcdNarayan Kamath if (mVerboseLoggingEnabled) { 155fd828776e37a5a8405a9ce0d4175d7971efbedcdNarayan Kamath Slog.d(TAG, "updateWifiLockWakeSource: " + wl + ", newWorkSource=" + newWorkSource); 156fd828776e37a5a8405a9ce0d4175d7971efbedcdNarayan Kamath } 157fd828776e37a5a8405a9ce0d4175d7971efbedcdNarayan Kamath 1582a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein long ident = Binder.clearCallingIdentity(); 1592a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein try { 160edf05fb9dddfef041d21964f889028294e34f7a3Narayan Kamath // Log the acquire before the release to avoid "holes" in the collected data due to 161edf05fb9dddfef041d21964f889028294e34f7a3Narayan Kamath // an acquire event immediately after a release in the case where newWorkSource and 162edf05fb9dddfef041d21964f889028294e34f7a3Narayan Kamath // wl.mWorkSource share one or more attribution UIDs. BatteryStats can correctly match 163edf05fb9dddfef041d21964f889028294e34f7a3Narayan Kamath // "nested" acquire / release pairs. 164edf05fb9dddfef041d21964f889028294e34f7a3Narayan Kamath mBatteryStats.noteFullWifiLockAcquiredFromSource(newWorkSource); 1652a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mBatteryStats.noteFullWifiLockReleasedFromSource(wl.mWorkSource); 166edf05fb9dddfef041d21964f889028294e34f7a3Narayan Kamath 1672a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein wl.mWorkSource = newWorkSource; 1682a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } catch (RemoteException e) { 1692a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } finally { 1702a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein Binder.restoreCallingIdentity(ident); 1712a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1722a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1732a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1742a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private static boolean isValidLockMode(int lockMode) { 1752a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (lockMode != WifiManager.WIFI_MODE_FULL 1762a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein && lockMode != WifiManager.WIFI_MODE_SCAN_ONLY 1772a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein && lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF) { 1782a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return false; 1792a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1802a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return true; 1812a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1822a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1832a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private synchronized boolean addLock(WifiLock lock) { 1842a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (mVerboseLoggingEnabled) { 1852a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein Slog.d(TAG, "addLock: " + lock); 1862a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1872a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1882a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (findLockByBinder(lock.getBinder()) != null) { 1892a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (mVerboseLoggingEnabled) { 1902a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein Slog.d(TAG, "attempted to add a lock when already holding one"); 1912a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1922a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return false; 1932a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 1942a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1952a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mWifiLocks.add(lock); 1962a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 1972a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein boolean lockAdded = false; 1982a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein long ident = Binder.clearCallingIdentity(); 1992a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein try { 2002a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mBatteryStats.noteFullWifiLockAcquiredFromSource(lock.mWorkSource); 2012a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein switch(lock.mMode) { 2022a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein case WifiManager.WIFI_MODE_FULL: 2032a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein ++mFullLocksAcquired; 2042a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein break; 2052a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 2062a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein ++mFullHighPerfLocksAcquired; 2072a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein break; 2082a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein case WifiManager.WIFI_MODE_SCAN_ONLY: 2092a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein ++mScanLocksAcquired; 2102a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein break; 2112a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2122a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein lockAdded = true; 2132a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } catch (RemoteException e) { 2142a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } finally { 2152a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein Binder.restoreCallingIdentity(ident); 2162a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2172a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return lockAdded; 2182a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2192a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 2202a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private synchronized WifiLock removeLock(IBinder binder) { 2212a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein WifiLock lock = findLockByBinder(binder); 2222a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (lock != null) { 2232a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mWifiLocks.remove(lock); 2242a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein lock.unlinkDeathRecipient(); 2252a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2262a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return lock; 2272a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2282a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 2292a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private synchronized boolean releaseLock(IBinder binder) { 2302a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein WifiLock wifiLock = removeLock(binder); 2312a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (wifiLock == null) { 2322a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein // attempting to release a lock that is not active. 2332a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return false; 2342a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2352a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 2362a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (mVerboseLoggingEnabled) { 2372a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein Slog.d(TAG, "releaseLock: " + wifiLock); 2382a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2392a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 2402a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein long ident = Binder.clearCallingIdentity(); 2412a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein try { 2422a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource); 2432a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein switch(wifiLock.mMode) { 2442a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein case WifiManager.WIFI_MODE_FULL: 2452a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein ++mFullLocksReleased; 2462a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein break; 2472a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 2482a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein ++mFullHighPerfLocksReleased; 2492a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein break; 2502a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein case WifiManager.WIFI_MODE_SCAN_ONLY: 2512a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein ++mScanLocksReleased; 2522a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein break; 2532a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2542a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } catch (RemoteException e) { 2552a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } finally { 2562a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein Binder.restoreCallingIdentity(ident); 2572a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2582a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return true; 2592a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2602a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 2612a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 2622a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private synchronized WifiLock findLockByBinder(IBinder binder) { 2632a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein for (WifiLock lock : mWifiLocks) { 2642a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (lock.getBinder() == binder) { 2652a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return lock; 2662a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2672a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2682a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return null; 2692a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2702a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 2712a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein protected void dump(PrintWriter pw) { 2722a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein pw.println("Locks acquired: " + mFullLocksAcquired + " full, " 2732a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein + mFullHighPerfLocksAcquired + " full high perf, " 2742a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein + mScanLocksAcquired + " scan"); 2752a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein pw.println("Locks released: " + mFullLocksReleased + " full, " 2762a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein + mFullHighPerfLocksReleased + " full high perf, " 2772a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein + mScanLocksReleased + " scan"); 2782a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein pw.println(); 2792a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein pw.println("Locks held:"); 2802a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein for (WifiLock lock : mWifiLocks) { 2812a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein pw.print(" "); 2822a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein pw.println(lock); 2832a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2842a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2852a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 2862a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein protected void enableVerboseLogging(int verbose) { 2872a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein if (verbose > 0) { 2882a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mVerboseLoggingEnabled = true; 2892a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } else { 2902a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mVerboseLoggingEnabled = false; 2912a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2922a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 2932a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 2942a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein private class WifiLock implements IBinder.DeathRecipient { 2952a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein String mTag; 2962a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein int mUid; 2972a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein IBinder mBinder; 2982a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein int mMode; 2992a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein WorkSource mWorkSource; 3002a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 3012a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein WifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) { 3022a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mTag = tag; 3032a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mBinder = binder; 3042a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mUid = Binder.getCallingUid(); 3052a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mMode = lockMode; 3062a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mWorkSource = ws; 3072a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein try { 3082a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mBinder.linkToDeath(this, 0); 3092a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } catch (RemoteException e) { 3102a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein binderDied(); 3112a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 3122a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 3132a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 3142a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein protected WorkSource getWorkSource() { 3152a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return mWorkSource; 3162a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 3172a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 3182a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein protected int getUid() { 3192a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return mUid; 3202a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 3212a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 3222a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein protected IBinder getBinder() { 3232a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein return mBinder; 3242a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 3252a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 3262a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein public void binderDied() { 3272a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein releaseLock(mBinder); 3282a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 3292a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 3302a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein public void unlinkDeathRecipient() { 3312a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein mBinder.unlinkToDeath(this, 0); 3322a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 3332a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein 3342a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein public String toString() { 335fd828776e37a5a8405a9ce0d4175d7971efbedcdNarayan Kamath return "WifiLock{" + this.mTag + " type=" + this.mMode + " uid=" + mUid 336fd828776e37a5a8405a9ce0d4175d7971efbedcdNarayan Kamath + " workSource=" + mWorkSource + "}"; 3372a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 3382a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein } 3392a7c2bec5d307a9e52de429c6303b7df9de900dcRebecca Silberstein} 340