Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 74d18ed1 authored by Bruno Martins's avatar Bruno Martins Committed by Michael Bestas
Browse files

PowerManager: Add proximity check on wake



Co-authored-by: default avatarAdnan Begovic <adnan@cyngn.com>
Co-authored-by: default avatarChristopher R. Palmer <crpalmer@gmail.com>
Co-authored-by: default avatarDanesh M <daneshm90@gmail.com>
Co-authored-by: default avatardankoman <dankoman30@gmail.com>
Co-authored-by: default avatarErica Chang <echang@cyngn.com>
Co-authored-by: default avatarHan Wang <416810799@qq.com>
Co-authored-by: default avatarLuK1337 <priv.luk@gmail.com>
Co-authored-by: default avatarMichael Bestas <mkbestas@lineageos.org>
Co-authored-by: default avatarOliver Scott <olivercscott@gmail.com>
Co-authored-by: default avatarPat Erley <perley@cyngn.com>
Co-authored-by: default avatarRoman Birg <roman@cyngn.com>
Co-authored-by: default avatarSchubi <schubi@erlangen.ccc.de>
Co-authored-by: default avatarScott Mertz <scott@cyngn.com>
Co-authored-by: default avatarSteve Kondik <steve@cyngn.com>
Co-authored-by: default avatarvm03 <vasy@vasy.ru>
Change-Id: Ia5ff446d88435773acccc7467e66009000dc20cb
parent 1fecb4c6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -178,4 +178,6 @@ interface IPowerManager
    const int GO_TO_SLEEP_REASON_MAX = 10;
    const int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0;

    // Lineage custom API
    void wakeUpWithProximityCheck(long time, int reason, String details, String opPackageName, int displayId);
}
+18 −0
Original line number Diff line number Diff line
@@ -1715,6 +1715,24 @@ public final class PowerManager {
        }
    }

    /**
     * Forces the display with the supplied displayId to turn on only if nothing is blocking the
     * proximity sensor.
     *
     * @see #wakeUp
     *
     * @hide
     */
    public void wakeUpWithProximityCheck(long time, @WakeReason int reason, String details,
            int displayId) {
        try {
            mService.wakeUpWithProximityCheck(time, reason, details, mContext.getOpPackageName(),
                    displayId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Forces the device to start napping.
     * <p>
+20 −4
Original line number Diff line number Diff line
@@ -5335,7 +5335,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            }

            if (isWakeKey) {
                wakeUpFromWakeKey(event);
                wakeUpFromWakeKey(event, true);
            }
            return result;
        }
@@ -5760,7 +5760,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }

        if (isWakeKey) {
            wakeUpFromWakeKey(event);
            // Check proximity only on wake key
            wakeUpFromWakeKey(event, event.getKeyCode() == KeyEvent.KEYCODE_WAKEUP);
        }

        // If the key event is targeted to a specific display, then the user is interacting with
@@ -6283,11 +6284,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        wakeUpFromWakeKey(
                event.getEventTime(),
                event.getKeyCode(),
                event.getAction() == KeyEvent.ACTION_DOWN);
                event.getAction() == KeyEvent.ACTION_DOWN,
                false);
    }

    private void wakeUpFromWakeKey(KeyEvent event, boolean withProximityCheck) {
        wakeUpFromWakeKey(
                event.getEventTime(),
                event.getKeyCode(),
                event.getAction() == KeyEvent.ACTION_DOWN,
                withProximityCheck);
    }

    private void wakeUpFromWakeKey(long eventTime, int keyCode, boolean isDown) {
        if (mWindowWakeUpPolicy.wakeUpFromKey(DEFAULT_DISPLAY, eventTime, keyCode, isDown)) {
        wakeUpFromWakeKey(eventTime, keyCode, isDown, false);
    }

    private void wakeUpFromWakeKey(long eventTime, int keyCode, boolean isDown,
            boolean withProximityCheck) {
        if (mWindowWakeUpPolicy.wakeUpFromKey(DEFAULT_DISPLAY, eventTime, keyCode, isDown,
                withProximityCheck)) {
            final boolean keyCanLaunchHome = keyCode == KEYCODE_HOME || keyCode == KEYCODE_POWER;
            // Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
            if (shouldWakeUpWithHomeIntent() &&  keyCanLaunchHome) {
+42 −4
Original line number Diff line number Diff line
@@ -116,6 +116,22 @@ class WindowWakeUpPolicy {
     *      executed; {@code false} otherwise.
     */
    boolean wakeUpFromKey(int displayId, long eventTime, int keyCode, boolean isDown) {
        return wakeUpFromKey(displayId, eventTime, keyCode, isDown, false);
    }

    /**
     * Wakes up from a key event.
     *
     * @param displayId the id of the display to wake.
     * @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
     * @param keyCode the {@link android.view.KeyEvent} key code of the key event.
     * @param isDown {@code true} if the event's action is {@link KeyEvent#ACTION_DOWN}.
     * @param withProximityCheck {@code true} if we should check proximity sensor before wakeup.
     * @return {@code true} if the policy allows the requested wake up and the request has been
     *      executed; {@code false} otherwise.
     */
    boolean wakeUpFromKey(int displayId, long eventTime, int keyCode, boolean isDown,
            boolean withProximityCheck) {
        final boolean wakeAllowedDuringTheaterMode =
                keyCode == KEYCODE_POWER
                        ? mAllowTheaterModeWakeFromPowerKey
@@ -133,12 +149,14 @@ class WindowWakeUpPolicy {
                    displayId,
                    eventTime,
                    keyCode == KEYCODE_POWER ? WAKE_REASON_POWER_BUTTON : WAKE_REASON_WAKE_KEY,
                    keyCode == KEYCODE_POWER ? "POWER" : "KEY");
                    keyCode == KEYCODE_POWER ? "POWER" : "KEY",
                    withProximityCheck);
        } else {
            wakeUp(
                    eventTime,
                    keyCode == KEYCODE_POWER ? WAKE_REASON_POWER_BUTTON : WAKE_REASON_WAKE_KEY,
                    keyCode == KEYCODE_POWER ? "POWER" : "KEY");
                    keyCode == KEYCODE_POWER ? "POWER" : "KEY",
                    withProximityCheck);
        }
        return true;
    }
@@ -256,14 +274,34 @@ class WindowWakeUpPolicy {

    /** Wakes up {@link PowerManager}. */
    private void wakeUp(long wakeTime, @WakeReason int reason, String details) {
        wakeUp(wakeTime, reason, details, false);
    }

    private void wakeUp(long wakeTime, @WakeReason int reason, String details,
            boolean withProximityCheck) {
        if (withProximityCheck) {
            mPowerManager.wakeUpWithProximityCheck(wakeTime, reason, "android.policy:" + details,
                    Display.DEFAULT_DISPLAY);
        } else {
            mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details);
        }
    }

    /** Wakes up given display. */
    private void wakeUp(int displayId, long wakeTime, @WakeReason int reason, String details) {
        wakeUp(displayId, wakeTime, reason, details, false);
    }

    private void wakeUp(int displayId, long wakeTime, @WakeReason int reason, String details,
            boolean withProximityCheck) {
        // If we're given an invalid display id to wake, fall back to waking default display
        final int displayIdToWake =
                displayId == Display.INVALID_DISPLAY ? Display.DEFAULT_DISPLAY : displayId;
        if (withProximityCheck) {
            mPowerManager.wakeUpWithProximityCheck(wakeTime, reason, "android.policy:" + details,
                    displayIdToWake);
        } else {
            mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details, displayIdToWake);
        }
    }
}
+154 −13
Original line number Diff line number Diff line
@@ -59,6 +59,9 @@ import android.content.PermissionChecker;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
import android.hardware.devicestate.DeviceState;
@@ -105,6 +108,7 @@ import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.service.dreams.DreamManagerInternal;
import android.sysprop.PowerProperties;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.IntArray;
import android.util.KeyValueListParser;
@@ -149,6 +153,8 @@ import com.android.server.power.feature.PowerManagerFlags;

import dalvik.annotation.optimization.NeverCompile;

import lineageos.providers.LineageSettings;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -186,6 +192,8 @@ public final class PowerManagerService extends SystemService

    // Message: Sent when the policy want to release all timeout override wake locks.
    private static final int MSG_RELEASE_ALL_OVERRIDE_WAKE_LOCKS = 6;
    // Message: Sent when waking up with proximity check.
    private static final int MSG_WAKE_UP = 7;

    // Dirty bit: mWakeLocks changed
    private static final int DIRTY_WAKE_LOCKS = 1 << 0;
@@ -246,6 +254,9 @@ public final class PowerManagerService extends SystemService
    // This should perhaps be a setting.
    private static final int SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 5 * 1000;

    // Threshold to consider proximity sensor covered
    private static final float PROXIMITY_NEAR_THRESHOLD = 5.0f;

    // How long a partial wake lock must be held until we consider it a long wake lock.
    static final long MIN_LONG_WAKE_CHECK_INTERVAL = 60*1000;

@@ -1194,6 +1205,17 @@ public final class PowerManagerService extends SystemService
    private static native boolean nativeSetPowerMode(int mode, boolean enabled);
    private static native boolean nativeForceSuspend();

    // Whether proximity check on wake is enabled by default
    private boolean mProximityWakeEnabledByDefaultConfig;

    private boolean mProximityWakeSupported;
    private boolean mProximityWakeEnabled;
    private int mProximityTimeOut;
    private SensorManager mSensorManager;
    private Sensor mProximitySensor;
    private SensorEventListener mProximityListener;
    private PowerManager.WakeLock mProximityWakeLock;

    public PowerManagerService(Context context) {
        this(context, new Injector());
    }
@@ -1449,6 +1471,10 @@ public final class PowerManagerService extends SystemService
                // Shouldn't happen since in-process.
            }

            // Initialize proximity sensor
            mSensorManager = mContext.getSystemService(SensorManager.class);
            mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

            mLowPowerStandbyController.systemReady();

            // Go.
@@ -1519,6 +1545,11 @@ public final class PowerManagerService extends SystemService
                Settings.Global.DEVICE_DEMO_MODE),
                false, mSettingsObserver, UserHandle.USER_SYSTEM);

        // Register for Lineage settings changes.
        resolver.registerContentObserver(LineageSettings.System.getUriFor(
                LineageSettings.System.PROXIMITY_ON_WAKE),
                false, mSettingsObserver, UserHandle.USER_ALL);

        // Register for broadcasts from other components of the system.
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
@@ -1590,6 +1621,17 @@ public final class PowerManagerService extends SystemService
                com.android.internal.R.fraction.config_maximumScreenDimRatio, 1, 1);
        mSupportsDoubleTapWakeConfig = resources.getBoolean(
                com.android.internal.R.bool.config_supportDoubleTapWake);

        mProximityWakeSupported = resources.getBoolean(
                org.lineageos.platform.internal.R.bool.config_proximityCheckOnWake);
        mProximityWakeEnabledByDefaultConfig = resources.getBoolean(
                org.lineageos.platform.internal.R.bool.config_proximityCheckOnWakeEnabledByDefault);
        mProximityTimeOut = resources.getInteger(
                org.lineageos.platform.internal.R.integer.config_proximityCheckTimeout);
        if (mProximityWakeSupported) {
            mProximityWakeLock = mContext.getSystemService(PowerManager.class)
                    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ProximityWakeLock");
        }
    }

    @GuardedBy("mLock")
@@ -1643,6 +1685,10 @@ public final class PowerManagerService extends SystemService
            mSystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, retailDemoValue);
        }

        mProximityWakeEnabled = LineageSettings.System.getIntForUser(resolver,
                LineageSettings.System.PROXIMITY_ON_WAKE,
                mProximityWakeEnabledByDefaultConfig ? 1 : 0, UserHandle.USER_CURRENT) == 1;

        mDirty |= DIRTY_SETTINGS;
    }

@@ -5469,6 +5515,10 @@ public final class PowerManagerService extends SystemService
                case MSG_RELEASE_ALL_OVERRIDE_WAKE_LOCKS:
                    releaseAllOverrideWakeLocks(msg.arg1);
                    break;
                case MSG_WAKE_UP:
                    cleanupProximity();
                    ((Runnable) msg.obj).run();
                    break;
            }

            return true;
@@ -6186,12 +6236,24 @@ public final class PowerManagerService extends SystemService
        @Override // Binder call
        public void wakeUp(long eventTime, @WakeReason int reason, String details,
                String opPackageName) {
            wakeUpWithDisplayId(eventTime, reason, details, opPackageName, Display.DEFAULT_DISPLAY);
            wakeUpWithDisplayId(eventTime, reason, details, opPackageName, Display.DEFAULT_DISPLAY,
                false);
        }

        @Override // Binder call
        public void wakeUpWithProximityCheck(long eventTime, @WakeReason int reason,
                String details, String opPackageName, int displayId) {
            wakeUpWithDisplayId(eventTime, reason, details, opPackageName, displayId, true);
        }

        @Override // Binder call
        public void wakeUpWithDisplayId(long eventTime, @WakeReason int reason, String details,
                String opPackageName, int displayId) {
            wakeUpWithDisplayId(eventTime, reason, details, opPackageName, displayId, false);
        }

        public void wakeUpWithDisplayId(long eventTime, @WakeReason int reason, String details,
                String opPackageName, int displayId, boolean checkProximity) {
            final long now = mClock.uptimeMillis();
            if (eventTime > now) {
                Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
@@ -6202,6 +6264,7 @@ public final class PowerManagerService extends SystemService
                    android.Manifest.permission.DEVICE_POWER, null);

            final int uid = Binder.getCallingUid();
            final Runnable r = () -> {
                final long ident = Binder.clearCallingIdentity();
                try {
                    int displayGroupId = getDisplayGroupId(displayId);
@@ -6217,6 +6280,12 @@ public final class PowerManagerService extends SystemService
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            };
            if (checkProximity) {
                runWithProximityCheck(r);
            } else {
                r.run();
            }
        }

        @Override // Binder call
@@ -7526,4 +7595,76 @@ public final class PowerManagerService extends SystemService
        }
        return displayInfo.displayGroupId;
    }

    private void cleanupProximity() {
        synchronized (mProximityWakeLock) {
            cleanupProximityLocked();
        }
    }

    private void cleanupProximityLocked() {
        if (mProximityWakeLock.isHeld()) {
            mProximityWakeLock.release();
        }
        if (mProximityListener != null) {
            mSensorManager.unregisterListener(mProximityListener);
            mProximityListener = null;
        }
    }

    private void runWithProximityCheck(final Runnable r) {
        if (mHandler.hasMessages(MSG_WAKE_UP)) {
            // A message is already queued
            return;
        }

        final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
        final boolean hasIncomingCall = tm.getCallState() == TelephonyManager.CALL_STATE_RINGING;

        if (mProximityWakeSupported && mProximityWakeEnabled
                && mProximitySensor != null && !hasIncomingCall) {
            final Message msg = mHandler.obtainMessage(MSG_WAKE_UP);
            msg.obj = r;
            mHandler.sendMessageDelayed(msg, mProximityTimeOut);
            runPostProximityCheck(r);
        } else {
            r.run();
        }
    }

    private void runPostProximityCheck(final Runnable r) {
        if (mSensorManager == null) {
            r.run();
            return;
        }
        synchronized (mProximityWakeLock) {
            mProximityWakeLock.acquire();
            mProximityListener = new SensorEventListener() {
                @Override
                public void onSensorChanged(SensorEvent event) {
                    cleanupProximityLocked();
                    if (!mHandler.hasMessages(MSG_WAKE_UP)) {
                        Slog.w(TAG, "Proximity sensor took too long, "
                                + "wake event already triggered!");
                        return;
                    }
                    mHandler.removeMessages(MSG_WAKE_UP);
                    final float distance = event.values[0];
                    if (distance >= PROXIMITY_NEAR_THRESHOLD ||
                            distance >= mProximitySensor.getMaximumRange()) {
                        r.run();
                    } else {
                        Slog.w(TAG, "Not waking up. Proximity sensor is blocked.");
                    }
                }

                @Override
                public void onAccuracyChanged(Sensor sensor, int accuracy) {
                    // Do nothing
                }
            };
            mSensorManager.registerListener(mProximityListener,
                   mProximitySensor, SensorManager.SENSOR_DELAY_FASTEST);
        }
    }
}