|
@@ -0,0 +1,163 @@
|
|
|
+/*
|
|
|
+ * Nextcloud Talk application
|
|
|
+ *
|
|
|
+ * @author Mario Danic
|
|
|
+ * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
|
|
+ *
|
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
|
+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
+ * at your option) any later version.
|
|
|
+ *
|
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+ * GNU General Public License for more details.
|
|
|
+ *
|
|
|
+ * You should have received a copy of the GNU General Public License
|
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
+ *
|
|
|
+ * This class is in part based on the code from the great people that wrote Signal
|
|
|
+ * https://github.com/signalapp/Signal-Android/raw/f9adb4e4554a44fd65b77320e34bf4bccf7924ce/src/org/thoughtcrime/securesms/webrtc/locks/LockManager.java
|
|
|
+ */
|
|
|
+
|
|
|
+package com.nextcloud.talk.utils.power;
|
|
|
+
|
|
|
+import android.annotation.SuppressLint;
|
|
|
+import android.content.Context;
|
|
|
+import android.net.wifi.WifiManager;
|
|
|
+import android.os.Build;
|
|
|
+import android.os.PowerManager;
|
|
|
+import android.provider.Settings;
|
|
|
+import autodagger.AutoInjector;
|
|
|
+import com.nextcloud.talk.application.NextcloudTalkApplication;
|
|
|
+
|
|
|
+import javax.inject.Inject;
|
|
|
+
|
|
|
+@AutoInjector(NextcloudTalkApplication.class)
|
|
|
+
|
|
|
+public class PowerManagerUtils {
|
|
|
+ private static final String TAG = "PowerManagerUtils";
|
|
|
+
|
|
|
+ @Inject
|
|
|
+ Context context;
|
|
|
+
|
|
|
+ private final PowerManager.WakeLock fullLock;
|
|
|
+ private final PowerManager.WakeLock partialLock;
|
|
|
+ private final WifiManager.WifiLock wifiLock;
|
|
|
+ private ProximityLock proximityLock;
|
|
|
+
|
|
|
+ private final boolean wifiLockEnforced;
|
|
|
+ private boolean proximityDisabled = false;
|
|
|
+
|
|
|
+ public enum PhoneState {
|
|
|
+ IDLE,
|
|
|
+ PROCESSING, //used when the phone is active but before the user should be alerted.
|
|
|
+ INTERACTIVE,
|
|
|
+ WITHOUT_PROXIMITY_SENSOR_LOCK,
|
|
|
+ WITH_PROXIMITY_SENSOR_LOCK
|
|
|
+ }
|
|
|
+
|
|
|
+ public enum WakeLockState {
|
|
|
+ FULL,
|
|
|
+ PARTIAL,
|
|
|
+ SLEEP,
|
|
|
+ PROXIMITY
|
|
|
+ }
|
|
|
+
|
|
|
+ public PowerManagerUtils() {
|
|
|
+ NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
|
|
|
+
|
|
|
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
|
|
+ fullLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "nctalk:fullwakelock");
|
|
|
+ partialLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "nctalk:partialwakelock");
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
|
+ proximityLock = new ProximityLock(pm);
|
|
|
+ }
|
|
|
+
|
|
|
+ // we suppress a possible leak because this is indeed application context
|
|
|
+ @SuppressLint("WifiManagerPotentialLeak") WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
|
|
+ wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "nctalk:wifiwakelock");
|
|
|
+
|
|
|
+ fullLock.setReferenceCounted(false);
|
|
|
+ partialLock.setReferenceCounted(false);
|
|
|
+ wifiLock.setReferenceCounted(false);
|
|
|
+
|
|
|
+ wifiLockEnforced = isWifiPowerActiveModeEnabled(context);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void updatePhoneState(PhoneState state) {
|
|
|
+ switch(state) {
|
|
|
+ case IDLE:
|
|
|
+ setWakeLockState(WakeLockState.SLEEP);
|
|
|
+ break;
|
|
|
+ case PROCESSING:
|
|
|
+ setWakeLockState(WakeLockState.PARTIAL);
|
|
|
+ break;
|
|
|
+ case INTERACTIVE:
|
|
|
+ setWakeLockState(WakeLockState.FULL);
|
|
|
+ break;
|
|
|
+ case WITH_PROXIMITY_SENSOR_LOCK:
|
|
|
+ proximityDisabled = false;
|
|
|
+ updateInCallWakeLockState();
|
|
|
+ break;
|
|
|
+ case WITHOUT_PROXIMITY_SENSOR_LOCK:
|
|
|
+ proximityDisabled = true;
|
|
|
+ updateInCallWakeLockState();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateInCallWakeLockState() {
|
|
|
+ if (wifiLockEnforced && !proximityDisabled) {
|
|
|
+ setWakeLockState(WakeLockState.PROXIMITY);
|
|
|
+ } else {
|
|
|
+ setWakeLockState(WakeLockState.FULL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isWifiPowerActiveModeEnabled(Context context) {
|
|
|
+ int wifi_pwr_active_mode = Settings.Secure.getInt(context.getContentResolver(), "wifi_pwr_active_mode", -1);
|
|
|
+ return (wifi_pwr_active_mode != 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressLint("WakelockTimeout")
|
|
|
+ private synchronized void setWakeLockState(WakeLockState newState) {
|
|
|
+ switch(newState) {
|
|
|
+ case FULL:
|
|
|
+ fullLock.acquire();
|
|
|
+ partialLock.acquire();
|
|
|
+ wifiLock.acquire();
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
|
+ proximityLock.release();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PARTIAL:
|
|
|
+ partialLock.acquire();
|
|
|
+ wifiLock.acquire();
|
|
|
+ fullLock.release();
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
|
+ proximityLock.release();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case SLEEP:
|
|
|
+ fullLock.release();
|
|
|
+ partialLock.release();
|
|
|
+ wifiLock.release();
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
|
+ proximityLock.release();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PROXIMITY:
|
|
|
+ partialLock.acquire();
|
|
|
+ wifiLock.acquire();
|
|
|
+ fullLock.release();
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
|
+ proximityLock.acquire();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ // something went very very wrong
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|