Loading packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java 0 → 100644 +256 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.doze; import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto; import com.android.systemui.statusbar.phone.DozeParameters; import android.annotation.AnyThread; import android.app.ActivityManager; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorManager; import android.hardware.TriggerEvent; import android.hardware.TriggerEventListener; import android.media.AudioAttributes; import android.net.Uri; import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.Vibrator; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import java.util.List; public class DozeSensors { private static final boolean DEBUG = DozeService.DEBUG; private static final String TAG = "DozeSensors"; private final Context mContext; private final SensorManager mSensorManager; private final TriggerSensor[] mSensors; private final ContentResolver mResolver; private final TriggerSensor mPickupSensor; private final DozeParameters mDozeParameters; private final AmbientDisplayConfiguration mConfig; private final PowerManager.WakeLock mWakeLock; private final Callback mCallback; private final Handler mHandler = new Handler(); public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters, AmbientDisplayConfiguration config, PowerManager.WakeLock wakeLock, Callback callback) { mContext = context; mSensorManager = sensorManager; mDozeParameters = dozeParameters; mConfig = config; mWakeLock = wakeLock; mResolver = mContext.getContentResolver(); mSensors = new TriggerSensor[] { new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION), null /* setting */, dozeParameters.getPulseOnSigMotion(), DozeLog.PULSE_REASON_SENSOR_SIGMOTION), mPickupSensor = new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE), Settings.Secure.DOZE_PULSE_ON_PICK_UP, config.pulseOnPickupAvailable(), DozeLog.PULSE_REASON_SENSOR_PICKUP), new TriggerSensor( findSensorWithType(config.doubleTapSensorType()), Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, true /* configured */, DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP) }; mCallback = callback; } private Sensor findSensorWithType(String type) { if (TextUtils.isEmpty(type)) { return null; } List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL); for (Sensor s : sensorList) { if (type.equals(s.getStringType())) { return s; } } return null; } public void setListen(boolean listen) { for (TriggerSensor s : mSensors) { s.setListening(listen); if (listen) { s.registerSettingsObserver(mSettingsObserver); } } if (!listen) { mResolver.unregisterContentObserver(mSettingsObserver); } } public void reregisterAllSensors() { for (TriggerSensor s : mSensors) { s.setListening(false); } for (TriggerSensor s : mSensors) { s.setListening(true); } } public void onUserSwitched() { for (TriggerSensor s : mSensors) { s.updateListener(); } } private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange, Uri uri, int userId) { if (userId != ActivityManager.getCurrentUser()) { return; } for (TriggerSensor s : mSensors) { s.updateListener(); } } }; public void setDisableSensorsInterferingWithProximity(boolean disable) { mPickupSensor.setDisabled(disable); } private class TriggerSensor extends TriggerEventListener { final Sensor mSensor; final boolean mConfigured; final int mPulseReason; final String mSetting; private boolean mRequested; private boolean mRegistered; private boolean mDisabled; public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason) { mSensor = sensor; mSetting = setting; mConfigured = configured; mPulseReason = pulseReason; } public void setListening(boolean listen) { if (mRequested == listen) return; mRequested = listen; updateListener(); } public void setDisabled(boolean disabled) { if (mDisabled == disabled) return; mDisabled = disabled; updateListener(); } public void updateListener() { if (!mConfigured || mSensor == null) return; if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) { mRegistered = mSensorManager.requestTriggerSensor(this, mSensor); if (DEBUG) Log.d(TAG, "requestTriggerSensor " + mRegistered); } else if (mRegistered) { final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor); if (DEBUG) Log.d(TAG, "cancelTriggerSensor " + rt); mRegistered = false; } } private boolean enabledBySetting() { if (TextUtils.isEmpty(mSetting)) { return true; } return Settings.Secure.getIntForUser(mResolver, mSetting, 1, UserHandle.USER_CURRENT) != 0; } @Override public String toString() { return new StringBuilder("{mRegistered=").append(mRegistered) .append(", mRequested=").append(mRequested) .append(", mDisabled=").append(mDisabled) .append(", mConfigured=").append(mConfigured) .append(", mSensor=").append(mSensor).append("}").toString(); } @Override @AnyThread public void onTrigger(TriggerEvent event) { mWakeLock.acquire(); try { if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event)); boolean sensorPerformsProxCheck = false; if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { int subType = (int) event.values[0]; MetricsLogger.action( mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE, subType); sensorPerformsProxCheck = mDozeParameters.getPickupSubtypePerformsProxCheck(subType); } mRegistered = false; mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck); updateListener(); // reregister, this sensor only fires once } finally { mWakeLock.release(); } } public void registerSettingsObserver(ContentObserver settingsObserver) { if (mConfigured && !TextUtils.isEmpty(mSetting)) { mResolver.registerContentObserver( Settings.Secure.getUriFor(mSetting), false /* descendants */, mSettingsObserver, UserHandle.USER_ALL); } } private String triggerEventToString(TriggerEvent event) { if (event == null) return null; final StringBuilder sb = new StringBuilder("TriggerEvent[") .append(event.timestamp).append(',') .append(event.sensor.getName()); if (event.values != null) { for (int i = 0; i < event.values.length; i++) { sb.append(',').append(event.values[i]); } } return sb.append(']').toString(); } } public interface Callback { void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck); } } packages/SystemUI/src/com/android/systemui/doze/DozeService.java +21 −204 Original line number Diff line number Diff line Loading @@ -16,47 +16,35 @@ package com.android.systemui.doze; import android.app.ActivityManager; import android.app.UiModeManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.TriggerEvent; import android.hardware.TriggerEventListener; import android.media.AudioAttributes; import android.net.Uri; import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.Vibrator; import android.provider.Settings; import android.service.dreams.DreamService; import android.text.TextUtils; import android.util.Log; import android.view.Display; import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.SystemUIApplication; import com.android.systemui.statusbar.phone.DozeParameters; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Date; import java.util.List; public class DozeService extends DreamService { public class DozeService extends DreamService implements DozeSensors.Callback { private static final String TAG = "DozeService"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String ACTION_BASE = "com.android.systemui.doze"; private static final String PULSE_ACTION = ACTION_BASE + ".pulse"; Loading @@ -72,9 +60,8 @@ public class DozeService extends DreamService { private final Handler mHandler = new Handler(); private DozeHost mHost; private DozeSensors mDozeSensors; private SensorManager mSensorManager; private TriggerSensor[] mSensors; private TriggerSensor mPickupSensor; private PowerManager mPowerManager; private PowerManager.WakeLock mWakeLock; private UiModeManager mUiModeManager; Loading @@ -101,10 +88,6 @@ public class DozeService extends DreamService { pw.print(" mWakeLock: held="); pw.println(mWakeLock.isHeld()); pw.print(" mHost: "); pw.println(mHost); pw.print(" mBroadcastReceiverRegistered: "); pw.println(mBroadcastReceiverRegistered); for (TriggerSensor s : mSensors) { pw.print(" sensor: "); pw.println(s); } pw.print(" mDisplayStateSupported: "); pw.println(mDisplayStateSupported); pw.print(" mPowerSaveActive: "); pw.println(mPowerSaveActive); pw.print(" mCarMode: "); pw.println(mCarMode); Loading @@ -129,30 +112,14 @@ public class DozeService extends DreamService { mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); mConfig = new AmbientDisplayConfiguration(mContext); mSensors = new TriggerSensor[] { new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION), null /* setting */, mDozeParameters.getPulseOnSigMotion(), mDozeParameters.getVibrateOnSigMotion(), DozeLog.PULSE_REASON_SENSOR_SIGMOTION), mPickupSensor = new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE), Settings.Secure.DOZE_PULSE_ON_PICK_UP, mConfig.pulseOnPickupAvailable(), mDozeParameters.getVibrateOnPickup(), DozeLog.PULSE_REASON_SENSOR_PICKUP), new TriggerSensor( findSensorWithType(mConfig.doubleTapSensorType()), Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, true, mDozeParameters.getVibrateOnPickup(), DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP) }; mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mWakeLock.setReferenceCounted(true); mDisplayStateSupported = mDozeParameters.getDisplayStateSupported(); mUiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE); turnDisplayOff(); mDozeSensors = new DozeSensors(mContext, mSensorManager, mDozeParameters, mConfig, mWakeLock, this); } @Override Loading Loading @@ -282,7 +249,7 @@ public class DozeService extends DreamService { if (mPulsing && mDreaming) { mPulsing = false; if (REREGISTER_ALL_SENSORS_ON_SCREEN_OFF) { reregisterAllSensors(); mDozeSensors.reregisterAllSensors(); } turnDisplayOff(); } Loading Loading @@ -313,22 +280,11 @@ public class DozeService extends DreamService { private void listenForPulseSignals(boolean listen) { if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen); for (TriggerSensor s : mSensors) { s.setListening(listen); } mDozeSensors.setListen(listen); listenForBroadcasts(listen); listenForNotifications(listen); } private void reregisterAllSensors() { for (TriggerSensor s : mSensors) { s.setListening(false); } for (TriggerSensor s : mSensors) { s.setListening(true); } } private void listenForBroadcasts(boolean listen) { if (listen) { final IntentFilter filter = new IntentFilter(PULSE_ACTION); Loading @@ -336,18 +292,10 @@ public class DozeService extends DreamService { filter.addAction(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(mBroadcastReceiver, filter); for (TriggerSensor s : mSensors) { if (s.mConfigured && !TextUtils.isEmpty(s.mSetting)) { mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(s.mSetting), false /* descendants */, mSettingsObserver, UserHandle.USER_ALL); } } mBroadcastReceiverRegistered = true; } else { if (mBroadcastReceiverRegistered) { mContext.unregisterReceiver(mBroadcastReceiver); mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); } mBroadcastReceiverRegistered = false; } Loading @@ -368,17 +316,18 @@ public class DozeService extends DreamService { requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); } private static String triggerEventToString(TriggerEvent event) { if (event == null) return null; final StringBuilder sb = new StringBuilder("TriggerEvent[") .append(event.timestamp).append(',') .append(event.sensor.getName()); if (event.values != null) { for (int i = 0; i < event.values.length; i++) { sb.append(',').append(event.values[i]); } @Override public void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck) { requestPulse(pulseReason, sensorPerformedProxCheck); if (pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP) { final long timeSinceNotification = SystemClock.elapsedRealtime() - mNotificationPulseTime; final boolean withinVibrationThreshold = timeSinceNotification < mDozeParameters.getPickupVibrationThreshold(); DozeLog.tracePickupPulse(mContext, withinVibrationThreshold); } return sb.append(']').toString(); } private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { Loading @@ -395,21 +344,7 @@ public class DozeService extends DreamService { } } if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { for (TriggerSensor s : mSensors) { s.updateListener(); } } } }; private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange, Uri uri, int userId) { if (userId != ActivityManager.getCurrentUser()) { return; } for (TriggerSensor s : mSensors) { s.updateListener(); mDozeSensors.onUserSwitched(); } } }; Loading Loading @@ -442,122 +377,6 @@ public class DozeService extends DreamService { } }; private Sensor findSensorWithType(String type) { if (TextUtils.isEmpty(type)) { return null; } List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL); for (Sensor s : sensorList) { if (type.equals(s.getStringType())) { return s; } } return null; } private class TriggerSensor extends TriggerEventListener { final Sensor mSensor; final boolean mConfigured; final boolean mDebugVibrate; final int mPulseReason; final String mSetting; private boolean mRequested; private boolean mRegistered; private boolean mDisabled; public TriggerSensor(Sensor sensor, String setting, boolean configured, boolean debugVibrate, int pulseReason) { mSensor = sensor; mSetting = setting; mConfigured = configured; mDebugVibrate = debugVibrate; mPulseReason = pulseReason; } public void setListening(boolean listen) { if (mRequested == listen) return; mRequested = listen; updateListener(); } public void setDisabled(boolean disabled) { if (mDisabled == disabled) return; mDisabled = disabled; updateListener(); } public void updateListener() { if (!mConfigured || mSensor == null) return; if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) { mRegistered = mSensorManager.requestTriggerSensor(this, mSensor); if (DEBUG) Log.d(mTag, "requestTriggerSensor " + mRegistered); } else if (mRegistered) { final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor); if (DEBUG) Log.d(mTag, "cancelTriggerSensor " + rt); mRegistered = false; } } private boolean enabledBySetting() { if (TextUtils.isEmpty(mSetting)) { return true; } return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSetting, 1, UserHandle.USER_CURRENT) != 0; } @Override public String toString() { return new StringBuilder("{mRegistered=").append(mRegistered) .append(", mRequested=").append(mRequested) .append(", mDisabled=").append(mDisabled) .append(", mConfigured=").append(mConfigured) .append(", mDebugVibrate=").append(mDebugVibrate) .append(", mSensor=").append(mSensor).append("}").toString(); } @Override public void onTrigger(TriggerEvent event) { mWakeLock.acquire(); try { if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event)); boolean sensorPerformsProxCheck = false; if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { int subType = (int) event.values[0]; MetricsLogger.action(mContext, MetricsEvent.ACTION_AMBIENT_GESTURE, subType); sensorPerformsProxCheck = mDozeParameters.getPickupSubtypePerformsProxCheck( subType); } if (mDebugVibrate) { final Vibrator v = (Vibrator) mContext.getSystemService( Context.VIBRATOR_SERVICE); if (v != null) { v.vibrate(1000, new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).build()); } } mRegistered = false; requestPulse(mPulseReason, sensorPerformsProxCheck); updateListener(); // reregister, this sensor only fires once // record pickup gesture, also keep track of whether we might have been triggered // by recent vibration. final long timeSinceNotification = SystemClock.elapsedRealtime() - mNotificationPulseTime; final boolean withinVibrationThreshold = timeSinceNotification < mDozeParameters.getPickupVibrationThreshold(); if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { DozeLog.tracePickupPulse(mContext, withinVibrationThreshold); } } finally { mWakeLock.release(); } } } private abstract class ProximityCheck implements SensorEventListener, Runnable { private static final int TIMEOUT_DELAY_MS = 500; Loading @@ -581,8 +400,7 @@ public class DozeService extends DreamService { finishWithResult(RESULT_UNKNOWN); return; } // the pickup sensor interferes with the prox event, disable it until we have a result mPickupSensor.setDisabled(true); mDozeSensors.setDisableSensorsInterferingWithProximity(true); mMaxRange = sensor.getMaximumRange(); mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0, Loading Loading @@ -614,8 +432,7 @@ public class DozeService extends DreamService { if (mRegistered) { mHandler.removeCallbacks(this); mSensorManager.unregisterListener(this); // we're done - reenable the pickup sensor mPickupSensor.setDisabled(false); mDozeSensors.setDisableSensorsInterferingWithProximity(false); mRegistered = false; } onProximityResult(result); Loading Loading
packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java 0 → 100644 +256 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.doze; import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto; import com.android.systemui.statusbar.phone.DozeParameters; import android.annotation.AnyThread; import android.app.ActivityManager; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorManager; import android.hardware.TriggerEvent; import android.hardware.TriggerEventListener; import android.media.AudioAttributes; import android.net.Uri; import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.Vibrator; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import java.util.List; public class DozeSensors { private static final boolean DEBUG = DozeService.DEBUG; private static final String TAG = "DozeSensors"; private final Context mContext; private final SensorManager mSensorManager; private final TriggerSensor[] mSensors; private final ContentResolver mResolver; private final TriggerSensor mPickupSensor; private final DozeParameters mDozeParameters; private final AmbientDisplayConfiguration mConfig; private final PowerManager.WakeLock mWakeLock; private final Callback mCallback; private final Handler mHandler = new Handler(); public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters, AmbientDisplayConfiguration config, PowerManager.WakeLock wakeLock, Callback callback) { mContext = context; mSensorManager = sensorManager; mDozeParameters = dozeParameters; mConfig = config; mWakeLock = wakeLock; mResolver = mContext.getContentResolver(); mSensors = new TriggerSensor[] { new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION), null /* setting */, dozeParameters.getPulseOnSigMotion(), DozeLog.PULSE_REASON_SENSOR_SIGMOTION), mPickupSensor = new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE), Settings.Secure.DOZE_PULSE_ON_PICK_UP, config.pulseOnPickupAvailable(), DozeLog.PULSE_REASON_SENSOR_PICKUP), new TriggerSensor( findSensorWithType(config.doubleTapSensorType()), Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, true /* configured */, DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP) }; mCallback = callback; } private Sensor findSensorWithType(String type) { if (TextUtils.isEmpty(type)) { return null; } List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL); for (Sensor s : sensorList) { if (type.equals(s.getStringType())) { return s; } } return null; } public void setListen(boolean listen) { for (TriggerSensor s : mSensors) { s.setListening(listen); if (listen) { s.registerSettingsObserver(mSettingsObserver); } } if (!listen) { mResolver.unregisterContentObserver(mSettingsObserver); } } public void reregisterAllSensors() { for (TriggerSensor s : mSensors) { s.setListening(false); } for (TriggerSensor s : mSensors) { s.setListening(true); } } public void onUserSwitched() { for (TriggerSensor s : mSensors) { s.updateListener(); } } private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange, Uri uri, int userId) { if (userId != ActivityManager.getCurrentUser()) { return; } for (TriggerSensor s : mSensors) { s.updateListener(); } } }; public void setDisableSensorsInterferingWithProximity(boolean disable) { mPickupSensor.setDisabled(disable); } private class TriggerSensor extends TriggerEventListener { final Sensor mSensor; final boolean mConfigured; final int mPulseReason; final String mSetting; private boolean mRequested; private boolean mRegistered; private boolean mDisabled; public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason) { mSensor = sensor; mSetting = setting; mConfigured = configured; mPulseReason = pulseReason; } public void setListening(boolean listen) { if (mRequested == listen) return; mRequested = listen; updateListener(); } public void setDisabled(boolean disabled) { if (mDisabled == disabled) return; mDisabled = disabled; updateListener(); } public void updateListener() { if (!mConfigured || mSensor == null) return; if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) { mRegistered = mSensorManager.requestTriggerSensor(this, mSensor); if (DEBUG) Log.d(TAG, "requestTriggerSensor " + mRegistered); } else if (mRegistered) { final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor); if (DEBUG) Log.d(TAG, "cancelTriggerSensor " + rt); mRegistered = false; } } private boolean enabledBySetting() { if (TextUtils.isEmpty(mSetting)) { return true; } return Settings.Secure.getIntForUser(mResolver, mSetting, 1, UserHandle.USER_CURRENT) != 0; } @Override public String toString() { return new StringBuilder("{mRegistered=").append(mRegistered) .append(", mRequested=").append(mRequested) .append(", mDisabled=").append(mDisabled) .append(", mConfigured=").append(mConfigured) .append(", mSensor=").append(mSensor).append("}").toString(); } @Override @AnyThread public void onTrigger(TriggerEvent event) { mWakeLock.acquire(); try { if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event)); boolean sensorPerformsProxCheck = false; if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { int subType = (int) event.values[0]; MetricsLogger.action( mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE, subType); sensorPerformsProxCheck = mDozeParameters.getPickupSubtypePerformsProxCheck(subType); } mRegistered = false; mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck); updateListener(); // reregister, this sensor only fires once } finally { mWakeLock.release(); } } public void registerSettingsObserver(ContentObserver settingsObserver) { if (mConfigured && !TextUtils.isEmpty(mSetting)) { mResolver.registerContentObserver( Settings.Secure.getUriFor(mSetting), false /* descendants */, mSettingsObserver, UserHandle.USER_ALL); } } private String triggerEventToString(TriggerEvent event) { if (event == null) return null; final StringBuilder sb = new StringBuilder("TriggerEvent[") .append(event.timestamp).append(',') .append(event.sensor.getName()); if (event.values != null) { for (int i = 0; i < event.values.length; i++) { sb.append(',').append(event.values[i]); } } return sb.append(']').toString(); } } public interface Callback { void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck); } }
packages/SystemUI/src/com/android/systemui/doze/DozeService.java +21 −204 Original line number Diff line number Diff line Loading @@ -16,47 +16,35 @@ package com.android.systemui.doze; import android.app.ActivityManager; import android.app.UiModeManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.TriggerEvent; import android.hardware.TriggerEventListener; import android.media.AudioAttributes; import android.net.Uri; import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.Vibrator; import android.provider.Settings; import android.service.dreams.DreamService; import android.text.TextUtils; import android.util.Log; import android.view.Display; import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.SystemUIApplication; import com.android.systemui.statusbar.phone.DozeParameters; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Date; import java.util.List; public class DozeService extends DreamService { public class DozeService extends DreamService implements DozeSensors.Callback { private static final String TAG = "DozeService"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String ACTION_BASE = "com.android.systemui.doze"; private static final String PULSE_ACTION = ACTION_BASE + ".pulse"; Loading @@ -72,9 +60,8 @@ public class DozeService extends DreamService { private final Handler mHandler = new Handler(); private DozeHost mHost; private DozeSensors mDozeSensors; private SensorManager mSensorManager; private TriggerSensor[] mSensors; private TriggerSensor mPickupSensor; private PowerManager mPowerManager; private PowerManager.WakeLock mWakeLock; private UiModeManager mUiModeManager; Loading @@ -101,10 +88,6 @@ public class DozeService extends DreamService { pw.print(" mWakeLock: held="); pw.println(mWakeLock.isHeld()); pw.print(" mHost: "); pw.println(mHost); pw.print(" mBroadcastReceiverRegistered: "); pw.println(mBroadcastReceiverRegistered); for (TriggerSensor s : mSensors) { pw.print(" sensor: "); pw.println(s); } pw.print(" mDisplayStateSupported: "); pw.println(mDisplayStateSupported); pw.print(" mPowerSaveActive: "); pw.println(mPowerSaveActive); pw.print(" mCarMode: "); pw.println(mCarMode); Loading @@ -129,30 +112,14 @@ public class DozeService extends DreamService { mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); mConfig = new AmbientDisplayConfiguration(mContext); mSensors = new TriggerSensor[] { new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION), null /* setting */, mDozeParameters.getPulseOnSigMotion(), mDozeParameters.getVibrateOnSigMotion(), DozeLog.PULSE_REASON_SENSOR_SIGMOTION), mPickupSensor = new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE), Settings.Secure.DOZE_PULSE_ON_PICK_UP, mConfig.pulseOnPickupAvailable(), mDozeParameters.getVibrateOnPickup(), DozeLog.PULSE_REASON_SENSOR_PICKUP), new TriggerSensor( findSensorWithType(mConfig.doubleTapSensorType()), Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, true, mDozeParameters.getVibrateOnPickup(), DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP) }; mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mWakeLock.setReferenceCounted(true); mDisplayStateSupported = mDozeParameters.getDisplayStateSupported(); mUiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE); turnDisplayOff(); mDozeSensors = new DozeSensors(mContext, mSensorManager, mDozeParameters, mConfig, mWakeLock, this); } @Override Loading Loading @@ -282,7 +249,7 @@ public class DozeService extends DreamService { if (mPulsing && mDreaming) { mPulsing = false; if (REREGISTER_ALL_SENSORS_ON_SCREEN_OFF) { reregisterAllSensors(); mDozeSensors.reregisterAllSensors(); } turnDisplayOff(); } Loading Loading @@ -313,22 +280,11 @@ public class DozeService extends DreamService { private void listenForPulseSignals(boolean listen) { if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen); for (TriggerSensor s : mSensors) { s.setListening(listen); } mDozeSensors.setListen(listen); listenForBroadcasts(listen); listenForNotifications(listen); } private void reregisterAllSensors() { for (TriggerSensor s : mSensors) { s.setListening(false); } for (TriggerSensor s : mSensors) { s.setListening(true); } } private void listenForBroadcasts(boolean listen) { if (listen) { final IntentFilter filter = new IntentFilter(PULSE_ACTION); Loading @@ -336,18 +292,10 @@ public class DozeService extends DreamService { filter.addAction(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(mBroadcastReceiver, filter); for (TriggerSensor s : mSensors) { if (s.mConfigured && !TextUtils.isEmpty(s.mSetting)) { mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(s.mSetting), false /* descendants */, mSettingsObserver, UserHandle.USER_ALL); } } mBroadcastReceiverRegistered = true; } else { if (mBroadcastReceiverRegistered) { mContext.unregisterReceiver(mBroadcastReceiver); mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); } mBroadcastReceiverRegistered = false; } Loading @@ -368,17 +316,18 @@ public class DozeService extends DreamService { requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); } private static String triggerEventToString(TriggerEvent event) { if (event == null) return null; final StringBuilder sb = new StringBuilder("TriggerEvent[") .append(event.timestamp).append(',') .append(event.sensor.getName()); if (event.values != null) { for (int i = 0; i < event.values.length; i++) { sb.append(',').append(event.values[i]); } @Override public void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck) { requestPulse(pulseReason, sensorPerformedProxCheck); if (pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP) { final long timeSinceNotification = SystemClock.elapsedRealtime() - mNotificationPulseTime; final boolean withinVibrationThreshold = timeSinceNotification < mDozeParameters.getPickupVibrationThreshold(); DozeLog.tracePickupPulse(mContext, withinVibrationThreshold); } return sb.append(']').toString(); } private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { Loading @@ -395,21 +344,7 @@ public class DozeService extends DreamService { } } if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { for (TriggerSensor s : mSensors) { s.updateListener(); } } } }; private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange, Uri uri, int userId) { if (userId != ActivityManager.getCurrentUser()) { return; } for (TriggerSensor s : mSensors) { s.updateListener(); mDozeSensors.onUserSwitched(); } } }; Loading Loading @@ -442,122 +377,6 @@ public class DozeService extends DreamService { } }; private Sensor findSensorWithType(String type) { if (TextUtils.isEmpty(type)) { return null; } List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL); for (Sensor s : sensorList) { if (type.equals(s.getStringType())) { return s; } } return null; } private class TriggerSensor extends TriggerEventListener { final Sensor mSensor; final boolean mConfigured; final boolean mDebugVibrate; final int mPulseReason; final String mSetting; private boolean mRequested; private boolean mRegistered; private boolean mDisabled; public TriggerSensor(Sensor sensor, String setting, boolean configured, boolean debugVibrate, int pulseReason) { mSensor = sensor; mSetting = setting; mConfigured = configured; mDebugVibrate = debugVibrate; mPulseReason = pulseReason; } public void setListening(boolean listen) { if (mRequested == listen) return; mRequested = listen; updateListener(); } public void setDisabled(boolean disabled) { if (mDisabled == disabled) return; mDisabled = disabled; updateListener(); } public void updateListener() { if (!mConfigured || mSensor == null) return; if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) { mRegistered = mSensorManager.requestTriggerSensor(this, mSensor); if (DEBUG) Log.d(mTag, "requestTriggerSensor " + mRegistered); } else if (mRegistered) { final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor); if (DEBUG) Log.d(mTag, "cancelTriggerSensor " + rt); mRegistered = false; } } private boolean enabledBySetting() { if (TextUtils.isEmpty(mSetting)) { return true; } return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSetting, 1, UserHandle.USER_CURRENT) != 0; } @Override public String toString() { return new StringBuilder("{mRegistered=").append(mRegistered) .append(", mRequested=").append(mRequested) .append(", mDisabled=").append(mDisabled) .append(", mConfigured=").append(mConfigured) .append(", mDebugVibrate=").append(mDebugVibrate) .append(", mSensor=").append(mSensor).append("}").toString(); } @Override public void onTrigger(TriggerEvent event) { mWakeLock.acquire(); try { if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event)); boolean sensorPerformsProxCheck = false; if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { int subType = (int) event.values[0]; MetricsLogger.action(mContext, MetricsEvent.ACTION_AMBIENT_GESTURE, subType); sensorPerformsProxCheck = mDozeParameters.getPickupSubtypePerformsProxCheck( subType); } if (mDebugVibrate) { final Vibrator v = (Vibrator) mContext.getSystemService( Context.VIBRATOR_SERVICE); if (v != null) { v.vibrate(1000, new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).build()); } } mRegistered = false; requestPulse(mPulseReason, sensorPerformsProxCheck); updateListener(); // reregister, this sensor only fires once // record pickup gesture, also keep track of whether we might have been triggered // by recent vibration. final long timeSinceNotification = SystemClock.elapsedRealtime() - mNotificationPulseTime; final boolean withinVibrationThreshold = timeSinceNotification < mDozeParameters.getPickupVibrationThreshold(); if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { DozeLog.tracePickupPulse(mContext, withinVibrationThreshold); } } finally { mWakeLock.release(); } } } private abstract class ProximityCheck implements SensorEventListener, Runnable { private static final int TIMEOUT_DELAY_MS = 500; Loading @@ -581,8 +400,7 @@ public class DozeService extends DreamService { finishWithResult(RESULT_UNKNOWN); return; } // the pickup sensor interferes with the prox event, disable it until we have a result mPickupSensor.setDisabled(true); mDozeSensors.setDisableSensorsInterferingWithProximity(true); mMaxRange = sensor.getMaximumRange(); mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0, Loading Loading @@ -614,8 +432,7 @@ public class DozeService extends DreamService { if (mRegistered) { mHandler.removeCallbacks(this); mSensorManager.unregisterListener(this); // we're done - reenable the pickup sensor mPickupSensor.setDisabled(false); mDozeSensors.setDisableSensorsInterferingWithProximity(false); mRegistered = false; } onProximityResult(result); Loading