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