Merge "Improve heuristics for detecting wireless chargers." into jb-mr1.1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b5e4835e3a
@ -344,7 +344,7 @@ final class DisplayPowerController {
|
||||
* Creates the display power controller.
|
||||
*/
|
||||
public DisplayPowerController(Looper looper, Context context, Notifier notifier,
|
||||
LightsService lights, TwilightService twilight,
|
||||
LightsService lights, TwilightService twilight, SensorManager sensorManager,
|
||||
DisplayManagerService displayManager,
|
||||
DisplayBlanker displayBlanker,
|
||||
Callbacks callbacks, Handler callbackHandler) {
|
||||
@ -356,7 +356,7 @@ final class DisplayPowerController {
|
||||
|
||||
mLights = lights;
|
||||
mTwilight = twilight;
|
||||
mSensorManager = new SystemSensorManager(mHandler.getLooper());
|
||||
mSensorManager = sensorManager;
|
||||
mDisplayManager = displayManager;
|
||||
|
||||
final Resources resources = context.getResources();
|
||||
|
@ -35,6 +35,8 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.SystemSensorManager;
|
||||
import android.net.Uri;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Binder;
|
||||
@ -153,11 +155,6 @@ public final class PowerManagerService extends IPowerManager.Stub
|
||||
// Otherwise the user won't get much screen on time before dimming occurs.
|
||||
private static final float MAXIMUM_SCREEN_DIM_RATIO = 0.2f;
|
||||
|
||||
// Upper bound on the battery charge percentage in order to consider turning
|
||||
// the screen on when the device starts charging wirelessly.
|
||||
// See point of use for more details.
|
||||
private static final int WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT = 95;
|
||||
|
||||
// The name of the boot animation service in init.rc.
|
||||
private static final String BOOT_ANIMATION_SERVICE = "bootanim";
|
||||
|
||||
@ -179,6 +176,7 @@ public final class PowerManagerService extends IPowerManager.Stub
|
||||
private WindowManagerPolicy mPolicy;
|
||||
private Notifier mNotifier;
|
||||
private DisplayPowerController mDisplayPowerController;
|
||||
private WirelessChargerDetector mWirelessChargerDetector;
|
||||
private SettingsObserver mSettingsObserver;
|
||||
private DreamManagerService mDreamManager;
|
||||
private LightsService.Light mAttentionLight;
|
||||
@ -423,6 +421,8 @@ public final class PowerManagerService extends IPowerManager.Stub
|
||||
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
|
||||
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
|
||||
|
||||
SensorManager sensorManager = new SystemSensorManager(mHandler.getLooper());
|
||||
|
||||
// The notifier runs on the system server's main looper so as not to interfere
|
||||
// with the animations and other critical functions of the power manager.
|
||||
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
|
||||
@ -430,11 +430,14 @@ public final class PowerManagerService extends IPowerManager.Stub
|
||||
mScreenOnBlocker, mPolicy);
|
||||
|
||||
// The display power controller runs on the power manager service's
|
||||
// own handler thread.
|
||||
// own handler thread to ensure timely operation.
|
||||
mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
|
||||
mContext, mNotifier, mLightsService, twilight, mDisplayManagerService,
|
||||
mDisplayBlanker, mDisplayPowerControllerCallbacks, mHandler);
|
||||
mContext, mNotifier, mLightsService, twilight, sensorManager,
|
||||
mDisplayManagerService, mDisplayBlanker,
|
||||
mDisplayPowerControllerCallbacks, mHandler);
|
||||
|
||||
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
|
||||
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"));
|
||||
mSettingsObserver = new SettingsObserver(mHandler);
|
||||
mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
|
||||
|
||||
@ -1139,65 +1142,51 @@ public final class PowerManagerService extends IPowerManager.Stub
|
||||
if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
|
||||
mDirty |= DIRTY_IS_POWERED;
|
||||
|
||||
// Update wireless dock detection state.
|
||||
final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
|
||||
mIsPowered, mPlugType, mBatteryLevel);
|
||||
|
||||
// Treat plugging and unplugging the devices as a user activity.
|
||||
// Users find it disconcerting when they plug or unplug the device
|
||||
// and it shuts off right away.
|
||||
// Some devices also wake the device when plugged or unplugged because
|
||||
// they don't have a charging LED.
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType)) {
|
||||
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
|
||||
dockedOnWirelessCharger)) {
|
||||
wakeUpNoUpdateLocked(now);
|
||||
}
|
||||
userActivityNoUpdateLocked(
|
||||
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
|
||||
|
||||
// Tell the notifier whether wireless charging has started so that
|
||||
// it can provide feedback to the user. Refer to
|
||||
// shouldWakeUpWhenPluggedOrUnpluggedLocked for justification of the
|
||||
// heuristics used here.
|
||||
if (!wasPowered && mIsPowered
|
||||
&& mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS
|
||||
&& mBatteryLevel < WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT) {
|
||||
// it can provide feedback to the user.
|
||||
if (dockedOnWirelessCharger) {
|
||||
mNotifier.onWirelessChargingStarted();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(boolean wasPowered, int oldPlugType) {
|
||||
private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(
|
||||
boolean wasPowered, int oldPlugType, boolean dockedOnWirelessCharger) {
|
||||
// Don't wake when powered unless configured to do so.
|
||||
if (!mWakeUpWhenPluggedOrUnpluggedConfig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Need more accurate detection of wireless chargers.
|
||||
//
|
||||
// We are unable to accurately detect whether the device is resting on the
|
||||
// charger unless it is actually receiving power. This causes us some grief
|
||||
// because the device might not appear to be plugged into the wireless charger
|
||||
// unless it actually charging.
|
||||
//
|
||||
// To avoid spuriously waking the screen, we apply a special policy to
|
||||
// wireless chargers.
|
||||
//
|
||||
// 1. Don't wake the device when unplugged from wireless charger because
|
||||
// it might be that the device is still resting on the wireless charger
|
||||
// but is not receiving power anymore because the battery is full.
|
||||
//
|
||||
// 2. Don't wake the device when plugged into a wireless charger if the
|
||||
// battery already appears to be mostly full. This situation may indicate
|
||||
// that the device was resting on the charger the whole time and simply
|
||||
// wasn't receiving power because the battery was full. We can't tell
|
||||
// whether the device was just placed on the charger or whether it has
|
||||
// been there for half of the night slowly discharging until it hit
|
||||
// the point where it needed to start charging again.
|
||||
// Don't wake when undocked from wireless charger.
|
||||
// See WirelessChargerDetector for justification.
|
||||
if (wasPowered && !mIsPowered
|
||||
&& oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't wake when docked on wireless charger unless we are certain of it.
|
||||
// See WirelessChargerDetector for justification.
|
||||
if (!wasPowered && mIsPowered
|
||||
&& mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS
|
||||
&& mBatteryLevel >= WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT) {
|
||||
&& !dockedOnWirelessCharger) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2183,6 +2172,7 @@ public final class PowerManagerService extends IPowerManager.Stub
|
||||
pw.println("POWER MANAGER (dumpsys power)\n");
|
||||
|
||||
final DisplayPowerController dpc;
|
||||
final WirelessChargerDetector wcd;
|
||||
synchronized (mLock) {
|
||||
pw.println("Power Manager State:");
|
||||
pw.println(" mDirty=0x" + Integer.toHexString(mDirty));
|
||||
@ -2264,11 +2254,16 @@ public final class PowerManagerService extends IPowerManager.Stub
|
||||
pw.println("Display Blanker: " + mDisplayBlanker);
|
||||
|
||||
dpc = mDisplayPowerController;
|
||||
wcd = mWirelessChargerDetector;
|
||||
}
|
||||
|
||||
if (dpc != null) {
|
||||
dpc.dump(pw);
|
||||
}
|
||||
|
||||
if (wcd != null) {
|
||||
wcd.dump(pw);
|
||||
}
|
||||
}
|
||||
|
||||
private SuspendBlocker createSuspendBlockerLocked(String name) {
|
||||
|
@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.server.power;
|
||||
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.BatteryManager;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Implements heuristics to detect docking or undocking from a wireless charger.
|
||||
* <p>
|
||||
* Some devices have wireless charging circuits that are unable to detect when the
|
||||
* device is resting on a wireless charger except when the device is actually
|
||||
* receiving power from the charger. The device may stop receiving power
|
||||
* if the battery is already nearly full or if it is too hot. As a result, we cannot
|
||||
* always rely on the battery service wireless plug signal to accurately indicate
|
||||
* whether the device has been docked or undocked from a wireless charger.
|
||||
* </p><p>
|
||||
* This is a problem because the power manager typically wakes up the screen and
|
||||
* plays a tone when the device is docked in a wireless charger. It is important
|
||||
* for the system to suppress spurious docking and undocking signals because they
|
||||
* can be intrusive for the user (especially if they cause a tone to be played
|
||||
* late at night for no apparent reason).
|
||||
* </p><p>
|
||||
* To avoid spurious signals, we apply some special policies to wireless chargers.
|
||||
* </p><p>
|
||||
* 1. Don't wake the device when undocked from the wireless charger because
|
||||
* it might be that the device is still resting on the wireless charger
|
||||
* but is not receiving power anymore because the battery is full.
|
||||
* Ideally we would wake the device if we could be certain that the user had
|
||||
* picked it up from the wireless charger but due to hardware limitations we
|
||||
* must be more conservative.
|
||||
* </p><p>
|
||||
* 2. Don't wake the device when docked on a wireless charger if the
|
||||
* battery already appears to be mostly full. This situation may indicate
|
||||
* that the device was resting on the charger the whole time and simply
|
||||
* wasn't receiving power because the battery was already full. We can't tell
|
||||
* whether the device was just placed on the charger or whether it has
|
||||
* been there for half of the night slowly discharging until it reached
|
||||
* the point where it needed to start charging again. So we suppress docking
|
||||
* signals that occur when the battery level is above a given threshold.
|
||||
* </p><p>
|
||||
* 3. Don't wake the device when docked on a wireless charger if it does
|
||||
* not appear to have moved since it was last undocked because it may
|
||||
* be that the prior undocking signal was spurious. We use the gravity
|
||||
* sensor to detect this case.
|
||||
* </p>
|
||||
*/
|
||||
final class WirelessChargerDetector {
|
||||
private static final String TAG = "WirelessChargerDetector";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
// Number of nanoseconds per millisecond.
|
||||
private static final long NANOS_PER_MS = 1000000;
|
||||
|
||||
// The minimum amount of time to spend watching the sensor before making
|
||||
// a determination of whether movement occurred.
|
||||
private static final long SETTLE_TIME_NANOS = 500 * NANOS_PER_MS;
|
||||
|
||||
// The minimum number of samples that must be collected.
|
||||
private static final int MIN_SAMPLES = 3;
|
||||
|
||||
// Upper bound on the battery charge percentage in order to consider turning
|
||||
// the screen on when the device starts charging wirelessly.
|
||||
private static final int WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT = 95;
|
||||
|
||||
// To detect movement, we compute the angle between the gravity vector
|
||||
// at rest and the current gravity vector. This field specifies the
|
||||
// cosine of the maximum angle variance that we tolerate while at rest.
|
||||
private static final double MOVEMENT_ANGLE_COS_THRESHOLD = Math.cos(5 * Math.PI / 180);
|
||||
|
||||
// Sanity thresholds for the gravity vector.
|
||||
private static final double MIN_GRAVITY = SensorManager.GRAVITY_EARTH - 1.0f;
|
||||
private static final double MAX_GRAVITY = SensorManager.GRAVITY_EARTH + 1.0f;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
private final SensorManager mSensorManager;
|
||||
private final SuspendBlocker mSuspendBlocker;
|
||||
|
||||
// The gravity sensor, or null if none.
|
||||
private Sensor mGravitySensor;
|
||||
|
||||
// Previously observed wireless power state.
|
||||
private boolean mPoweredWirelessly;
|
||||
|
||||
// True if the device is thought to be at rest on a wireless charger.
|
||||
private boolean mAtRest;
|
||||
|
||||
// The gravity vector most recently observed while at rest.
|
||||
private float mRestX, mRestY, mRestZ;
|
||||
|
||||
/* These properties are only meaningful while detection is in progress. */
|
||||
|
||||
// True if detection is in progress.
|
||||
// The suspend blocker is held while this is the case.
|
||||
private boolean mDetectionInProgress;
|
||||
|
||||
// True if the rest position should be updated if at rest.
|
||||
// Otherwise, the current rest position is simply checked and cleared if movement
|
||||
// is detected but no new rest position is stored.
|
||||
private boolean mMustUpdateRestPosition;
|
||||
|
||||
// The total number of samples collected.
|
||||
private int mTotalSamples;
|
||||
|
||||
// The number of samples collected that showed evidence of not being at rest.
|
||||
private int mMovingSamples;
|
||||
|
||||
// The time and value of the first sample that was collected.
|
||||
private long mFirstSampleTime;
|
||||
private float mFirstSampleX, mFirstSampleY, mFirstSampleZ;
|
||||
|
||||
public WirelessChargerDetector(SensorManager sensorManager,
|
||||
SuspendBlocker suspendBlocker) {
|
||||
mSensorManager = sensorManager;
|
||||
mSuspendBlocker = suspendBlocker;
|
||||
|
||||
mGravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw) {
|
||||
synchronized (mLock) {
|
||||
pw.println();
|
||||
pw.println("Wireless Charger Detector State:");
|
||||
pw.println(" mGravitySensor=" + mGravitySensor);
|
||||
pw.println(" mPoweredWirelessly=" + mPoweredWirelessly);
|
||||
pw.println(" mAtRest=" + mAtRest);
|
||||
pw.println(" mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ);
|
||||
pw.println(" mDetectionInProgress=" + mDetectionInProgress);
|
||||
pw.println(" mMustUpdateRestPosition=" + mMustUpdateRestPosition);
|
||||
pw.println(" mTotalSamples=" + mTotalSamples);
|
||||
pw.println(" mMovingSamples=" + mMovingSamples);
|
||||
pw.println(" mFirstSampleTime=" + mFirstSampleTime);
|
||||
pw.println(" mFirstSampleX=" + mFirstSampleX
|
||||
+ ", mFirstSampleY=" + mFirstSampleY + ", mFirstSampleZ=" + mFirstSampleZ);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the charging state and returns true if docking was detected.
|
||||
*
|
||||
* @param isPowered True if the device is powered.
|
||||
* @param plugType The current plug type.
|
||||
* @param batteryLevel The current battery level.
|
||||
* @return True if the device is determined to have just been docked on a wireless
|
||||
* charger, after suppressing spurious docking or undocking signals.
|
||||
*/
|
||||
public boolean update(boolean isPowered, int plugType, int batteryLevel) {
|
||||
synchronized (mLock) {
|
||||
final boolean wasPoweredWirelessly = mPoweredWirelessly;
|
||||
|
||||
if (isPowered && plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
|
||||
// The device is receiving power from the wireless charger.
|
||||
// Update the rest position asynchronously.
|
||||
mPoweredWirelessly = true;
|
||||
mMustUpdateRestPosition = true;
|
||||
startDetectionLocked();
|
||||
} else {
|
||||
// The device may or may not be on the wireless charger depending on whether
|
||||
// the unplug signal that we received was spurious.
|
||||
mPoweredWirelessly = false;
|
||||
if (mAtRest) {
|
||||
if (plugType != 0 && plugType != BatteryManager.BATTERY_PLUGGED_WIRELESS) {
|
||||
// The device was plugged into a new non-wireless power source.
|
||||
// It's safe to assume that it is no longer on the wireless charger.
|
||||
mMustUpdateRestPosition = false;
|
||||
clearAtRestLocked();
|
||||
} else {
|
||||
// The device may still be on the wireless charger but we don't know.
|
||||
// Check whether the device has remained at rest on the charger
|
||||
// so that we will know to ignore the next wireless plug event
|
||||
// if needed.
|
||||
startDetectionLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Report that the device has been docked only if the device just started
|
||||
// receiving power wirelessly, has a high enough battery level that we
|
||||
// can be assured that charging was not delayed due to the battery previously
|
||||
// having been full, and the device is not known to already be at rest
|
||||
// on the wireless charger from earlier.
|
||||
return mPoweredWirelessly && !wasPoweredWirelessly
|
||||
&& batteryLevel < WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT
|
||||
&& !mAtRest;
|
||||
}
|
||||
}
|
||||
|
||||
private void startDetectionLocked() {
|
||||
if (!mDetectionInProgress && mGravitySensor != null) {
|
||||
if (mSensorManager.registerListener(mListener, mGravitySensor,
|
||||
SensorManager.SENSOR_DELAY_UI)) {
|
||||
mSuspendBlocker.acquire();
|
||||
mDetectionInProgress = true;
|
||||
mTotalSamples = 0;
|
||||
mMovingSamples = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processSample(long timeNanos, float x, float y, float z) {
|
||||
synchronized (mLock) {
|
||||
if (!mDetectionInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
mTotalSamples += 1;
|
||||
if (mTotalSamples == 1) {
|
||||
// Save information about the first sample collected.
|
||||
mFirstSampleTime = timeNanos;
|
||||
mFirstSampleX = x;
|
||||
mFirstSampleY = y;
|
||||
mFirstSampleZ = z;
|
||||
} else {
|
||||
// Determine whether movement has occurred relative to the first sample.
|
||||
if (hasMoved(mFirstSampleX, mFirstSampleY, mFirstSampleZ, x, y, z)) {
|
||||
mMovingSamples += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the at rest flag if movement has occurred relative to the rest sample.
|
||||
if (mAtRest && hasMoved(mRestX, mRestY, mRestZ, x, y, z)) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "No longer at rest: "
|
||||
+ "mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ
|
||||
+ ", x=" + x + ", y=" + y + ", z=" + z);
|
||||
}
|
||||
clearAtRestLocked();
|
||||
}
|
||||
|
||||
// Save the result when done.
|
||||
if (timeNanos - mFirstSampleTime >= SETTLE_TIME_NANOS
|
||||
&& mTotalSamples >= MIN_SAMPLES) {
|
||||
mSensorManager.unregisterListener(mListener);
|
||||
if (mMustUpdateRestPosition) {
|
||||
if (mMovingSamples == 0) {
|
||||
mAtRest = true;
|
||||
mRestX = x;
|
||||
mRestY = y;
|
||||
mRestZ = z;
|
||||
} else {
|
||||
clearAtRestLocked();
|
||||
}
|
||||
mMustUpdateRestPosition = false;
|
||||
}
|
||||
mDetectionInProgress = false;
|
||||
mSuspendBlocker.release();
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "New state: mAtRest=" + mAtRest
|
||||
+ ", mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ
|
||||
+ ", mTotalSamples=" + mTotalSamples
|
||||
+ ", mMovingSamples=" + mMovingSamples);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearAtRestLocked() {
|
||||
mAtRest = false;
|
||||
mRestX = 0;
|
||||
mRestY = 0;
|
||||
mRestZ = 0;
|
||||
}
|
||||
|
||||
private static boolean hasMoved(float x1, float y1, float z1,
|
||||
float x2, float y2, float z2) {
|
||||
final double dotProduct = (x1 * x2) + (y1 * y2) + (z1 * z2);
|
||||
final double mag1 = Math.sqrt((x1 * x1) + (y1 * y1) + (z1 * z1));
|
||||
final double mag2 = Math.sqrt((x2 * x2) + (y2 * y2) + (z2 * z2));
|
||||
if (mag1 < MIN_GRAVITY || mag1 > MAX_GRAVITY
|
||||
|| mag2 < MIN_GRAVITY || mag2 > MAX_GRAVITY) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Weird gravity vector: mag1=" + mag1 + ", mag2=" + mag2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
final boolean moved = (dotProduct < mag1 * mag2 * MOVEMENT_ANGLE_COS_THRESHOLD);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Check: moved=" + moved
|
||||
+ ", x1=" + x1 + ", y1=" + y1 + ", z1=" + z1
|
||||
+ ", x2=" + x2 + ", y2=" + y2 + ", z2=" + z2
|
||||
+ ", angle=" + (Math.acos(dotProduct / mag1 / mag2) * 180 / Math.PI)
|
||||
+ ", dotProduct=" + dotProduct
|
||||
+ ", mag1=" + mag1 + ", mag2=" + mag2);
|
||||
}
|
||||
return moved;
|
||||
}
|
||||
|
||||
private final SensorEventListener mListener = new SensorEventListener() {
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
processSample(event.timestamp, event.values[0], event.values[1], event.values[2]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user