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

Commit 23d681bb authored by Joe LaPenna's avatar Joe LaPenna
Browse files

Device Idle: Android wear support

- Provide config param: autoPowerModeThresholdAngle allowing us to
  adjust the tilt threshold on a per-device basis.
- Provide config param: autoPowerModePrefetchLocation allowing us to
  skip location prefectching on a per-device basis.
- Provide config param: autoPowerModeAnyMotionSensor allowing us to
  use a device-specific sensor on to detect additional types of movement
  that would trigger exiting device idle.
- PRovide config param: autoPowerModePreferWristTilt allows us to use
  the wrist tilt detector in lieu of the SMD if an anymotion sensor
isn't specified.
- Allow DeviceIdleController to use wrist tilt sensors if the device provides
  one.
- Use wrist tilt or SMD when an "any motion" sensor isn't available.
- Fix bugs where DeviceIdleController would crash on devices that did
  not have a location and/or gps provider (some android wear devices).

BUG: 22661021

Change-Id: Ib9f7cdf8f16483ba8f466b7b5c97bdf0494ba228
parent 38ae1196
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -166,6 +166,21 @@
         so that applications can still use their own mechanisms. -->
    <bool name="config_enableAutoPowerModes">false</bool>

    <!-- The threshold angle for any motion detection in auto-power save modes.
         In hundreths of a degree. -->
    <integer name="config_autoPowerModeThresholdAngle">200</integer>

    <!-- The sensor id of an "any motion" sensor used in auto-power save modes.
         0 indicates this sensor is not available. -->
    <integer name="config_autoPowerModeAnyMotionSensor">0</integer>

    <!-- If an any motion sensor is not available, prefer the wrist tilt detector over the
         SMD. -->
    <bool name="config_autoPowerModePreferWristTilt">false</bool>

    <!-- If a location should be pre-fetched when going into device idle. -->
    <bool name="config_autoPowerModePrefetchLocation">true</bool>

    <!-- The duration (in milliseconds) that the radio will scan for a signal
         when there's no network connection. If the scan doesn't timeout, use zero -->
    <integer name="config_radioScanningTimeout">0</integer>
+4 −0
Original line number Diff line number Diff line
@@ -253,6 +253,10 @@
  <java-symbol type="bool" name="config_cellBroadcastAppLinks" />
  <java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
  <java-symbol type="bool" name="config_enableAutoPowerModes" />
  <java-symbol type="integer" name="config_autoPowerModeThresholdAngle" />
  <java-symbol type="integer" name="config_autoPowerModeAnyMotionSensor" />
  <java-symbol type="bool" name="config_autoPowerModePreferWristTilt" />
  <java-symbol type="bool" name="config_autoPowerModePrefetchLocation" />
  <java-symbol type="bool" name="config_enable_emergency_call_while_sim_locked" />
  <java-symbol type="bool" name="config_enable_puk_unlock_screen" />
  <java-symbol type="bool" name="config_enableBurnInProtection" />
+8 −6
Original line number Diff line number Diff line
@@ -58,9 +58,6 @@ public class AnyMotionDetector {
    /** Current measurement state. */
    private int mState;

    /** Threshold angle in degrees beyond which the device is considered moving. */
    private final float THRESHOLD_ANGLE = 2f;

    /** Threshold energy above which the device is considered moving. */
    private final float THRESHOLD_ENERGY = 5f;

@@ -88,6 +85,9 @@ public class AnyMotionDetector {
    private SensorManager mSensorManager;
    private PowerManager.WakeLock mWakeLock;

    /** Threshold angle in degrees beyond which the device is considered moving. */
    private final float mThresholdAngle;

    /** The minimum number of samples required to detect AnyMotion. */
    private int mNumSufficientSamples;

@@ -106,7 +106,7 @@ public class AnyMotionDetector {
    private DeviceIdleCallback mCallback = null;

    public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm,
            DeviceIdleCallback callback) {
            DeviceIdleCallback callback, float thresholdAngle) {
        if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated.");
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
        mWakeLock.setReferenceCounted(false);
@@ -116,6 +116,7 @@ public class AnyMotionDetector {
        mMeasurementInProgress = false;
        mState = STATE_INACTIVE;
        mCallback = callback;
        mThresholdAngle = thresholdAngle;
        mRunningStats = new RunningSignalStats();
        mNumSufficientSamples = (int) Math.ceil(
                ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS));
@@ -224,8 +225,9 @@ public class AnyMotionDetector {
        Vector3 previousGravityVectorNormalized = mPreviousGravityVector.normalized();
        Vector3 currentGravityVectorNormalized = mCurrentGravityVector.normalized();
        float angle = previousGravityVectorNormalized.angleBetween(currentGravityVectorNormalized);
        if (DEBUG) Slog.d(TAG, "getStationaryStatus: angle = " + angle);
        if ((angle < THRESHOLD_ANGLE) && (mRunningStats.getEnergy() < THRESHOLD_ENERGY)) {
        if (DEBUG) Slog.d(TAG, "getStationaryStatus: angle = " + angle
                + " energy = " + mRunningStats.getEnergy());
        if ((angle < mThresholdAngle) && (mRunningStats.getEnergy() < THRESHOLD_ENERGY)) {
            return RESULT_STATIONARY;
        } else if (Float.isNaN(angle)) {
          /**
+57 −22
Original line number Diff line number Diff line
@@ -128,7 +128,8 @@ public class DeviceIdleController extends SystemService
    private boolean mNotMoving;
    private boolean mLocating;
    private boolean mLocated;
    private boolean mHaveGps;
    private boolean mHasGps;
    private boolean mHasNetworkLocation;
    private Location mLastGenericLocation;
    private Location mLastGpsLocation;

@@ -882,7 +883,23 @@ public class DeviceIdleController extends SystemService
                mDisplayManager = (DisplayManager) getContext().getSystemService(
                        Context.DISPLAY_SERVICE);
                mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
                mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
                int sigMotionSensorId = getContext().getResources().getInteger(
                        com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
                if (sigMotionSensorId > 0) {
                    mSigMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true);
                }
                if (mSigMotionSensor == null && getContext().getResources().getBoolean(
                        com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
                    mSigMotionSensor = mSensorManager.getDefaultSensor(
                            Sensor.TYPE_WRIST_TILT_GESTURE);
                }
                if (mSigMotionSensor == null) {
                    // As a last ditch, fall back to SMD.
                    mSigMotionSensor = mSensorManager.getDefaultSensor(
                            Sensor.TYPE_SIGNIFICANT_MOTION);
                }
                if (getContext().getResources().getBoolean(
                        com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
                    mLocationManager = (LocationManager) getContext().getSystemService(
                            Context.LOCATION_SERVICE);
                    mLocationRequest = new LocationRequest()
@@ -890,9 +907,13 @@ public class DeviceIdleController extends SystemService
                        .setInterval(0)
                        .setFastestInterval(0)
                        .setNumUpdates(1);
                }

                float angleThreshold = getContext().getResources().getInteger(
                        com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
                mAnyMotionDetector = new AnyMotionDetector(
                        (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
                        mHandler, mSensorManager, this);
                        mHandler, mSensorManager, this, angleThreshold);

                Intent intent = new Intent(ACTION_STEP_IDLE_STATE)
                        .setPackage("android")
@@ -1279,17 +1300,30 @@ public class DeviceIdleController extends SystemService
                EventLogTags.writeDeviceIdle(mState, "step");
                cancelSensingAlarmLocked();
                scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);
                if (mLocationManager != null
                        && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
                    mLocationManager.requestLocationUpdates(mLocationRequest,
                            mGenericLocationListener, mHandler.getLooper());
                    mLocating = true;
                mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener,
                        mHandler.getLooper());
                if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
                    mHaveGps = true;
                } else {
                    mHasNetworkLocation = false;
                }
                if (mLocationManager != null
                        && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
                    mHasGps = true;
                    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
                            mGpsLocationListener, mHandler.getLooper());
                    mLocating = true;
                } else {
                    mHaveGps = false;
                    mHasGps = false;
                }
                // If we have a location provider, we're all set, the listeners will move state
                // forward.
                if (mLocating) {
                    break;
                }

                // Otherwise, we have to move from locating into idle maintenance.
            case STATE_LOCATING:
                cancelSensingAlarmLocked();
                cancelLocatingLocked();
@@ -1346,7 +1380,7 @@ public class DeviceIdleController extends SystemService
        }
        if (DEBUG) Slog.d(TAG, "Generic location: " + location);
        mLastGenericLocation = new Location(location);
        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHaveGps) {
        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
            return;
        }
        mLocated = true;
@@ -1413,9 +1447,9 @@ public class DeviceIdleController extends SystemService
    void scheduleAlarmLocked(long delay, boolean idleUntil) {
        if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
        if (mSigMotionSensor == null) {
            // If there is no significant motion sensor on this device, then we won't schedule
            // If there is no motion sensor on this device, then we won't schedule
            // alarms, because we can't determine if the device is not moving.  This effectively
            // turns off normal exeuction of device idling, although it is still possible to
            // turns off normal execution of device idling, although it is still possible to
            // manually poke it by pretending like the alarm is going off.
            return;
        }
@@ -1902,8 +1936,9 @@ public class DeviceIdleController extends SystemService
            pw.print("  mSigMotionActive="); pw.println(mSigMotionActive);
            pw.print("  mSensing="); pw.print(mSensing); pw.print(" mNotMoving=");
                    pw.println(mNotMoving);
            pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHaveGps=");
                    pw.print(mHaveGps); pw.print(" mLocated="); pw.println(mLocated);
            pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
                    pw.print(mHasGps); pw.print(" mHasNetwork=");
                    pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
            if (mLastGenericLocation != null) {
                pw.print("  mLastGenericLocation="); pw.println(mLastGenericLocation);
            }