summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/layout/call_detail.xml14
-rw-r--r--src/com/android/dialer/CallDetailActivity.java91
-rw-r--r--src/com/android/dialer/ProximitySensorManager.java237
3 files changed, 29 insertions, 313 deletions
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index 35c41c0b3..522c698ad 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -100,18 +100,4 @@
</LinearLayout>
- <!--
- Used to hide the UI when playing a voicemail and the proximity sensor
- is detecting something near the screen.
- -->
- <View
- android:id="@+id/blank"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@android:color/black"
- android:visibility="gone"
- android:clickable="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- />
</RelativeLayout>
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index df8197a10..69242d3da 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -27,6 +27,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.PowerManager;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -83,11 +84,6 @@ public class CallDetailActivity extends Activity implements ProximitySensorAware
private static final char LEFT_TO_RIGHT_EMBEDDING = '\u202A';
private static final char POP_DIRECTIONAL_FORMATTING = '\u202C';
- /** The time to wait before enabling the blank the screen due to the proximity sensor. */
- private static final long PROXIMITY_BLANK_DELAY_MILLIS = 100;
- /** The time to wait before disabling the blank the screen due to the proximity sensor. */
- private static final long PROXIMITY_UNBLANK_DELAY_MILLIS = 500;
-
/** The enumeration of {@link AsyncTask} objects used in this class. */
public enum Tasks {
MARK_VOICEMAIL_READ,
@@ -144,59 +140,7 @@ public class CallDetailActivity extends Activity implements ProximitySensorAware
/** Whether we should show "remove from call log" in the options menu. */
private boolean mHasRemoveFromCallLogOption;
- private ProximitySensorManager mProximitySensorManager;
- private final ProximitySensorListener mProximitySensorListener = new ProximitySensorListener();
-
- /** Listener to changes in the proximity sensor state. */
- private class ProximitySensorListener implements ProximitySensorManager.Listener {
- /** Used to show a blank view and hide the action bar. */
- private final Runnable mBlankRunnable = new Runnable() {
- @Override
- public void run() {
- View blankView = findViewById(R.id.blank);
- blankView.setVisibility(View.VISIBLE);
- getActionBar().hide();
- }
- };
- /** Used to remove the blank view and show the action bar. */
- private final Runnable mUnblankRunnable = new Runnable() {
- @Override
- public void run() {
- View blankView = findViewById(R.id.blank);
- blankView.setVisibility(View.GONE);
- getActionBar().show();
- }
- };
-
- @Override
- public synchronized void onNear() {
- clearPendingRequests();
- postDelayed(mBlankRunnable, PROXIMITY_BLANK_DELAY_MILLIS);
- }
-
- @Override
- public synchronized void onFar() {
- clearPendingRequests();
- postDelayed(mUnblankRunnable, PROXIMITY_UNBLANK_DELAY_MILLIS);
- }
-
- /** Removed any delayed requests that may be pending. */
- public synchronized void clearPendingRequests() {
- View blankView = findViewById(R.id.blank);
- blankView.removeCallbacks(mBlankRunnable);
- blankView.removeCallbacks(mUnblankRunnable);
- }
-
- /** Post a {@link Runnable} with a delay on the main thread. */
- private synchronized void postDelayed(Runnable runnable, long delayMillis) {
- // Post these instead of executing immediately so that:
- // - They are guaranteed to be executed on the main thread.
- // - If the sensor values changes rapidly for some time, the UI will not be
- // updated immediately.
- View blankView = findViewById(R.id.blank);
- blankView.postDelayed(runnable, delayMillis);
- }
- }
+ private PowerManager.WakeLock mProximityWakeLock;
static final String[] CALL_LOG_PROJECTION = new String[] {
CallLog.Calls.DATE,
@@ -251,7 +195,14 @@ public class CallDetailActivity extends Activity implements ProximitySensorAware
mAccountLabel = (TextView) findViewById(R.id.phone_account_label);
mDefaultCountryIso = GeoUtil.getCurrentCountryIso(this);
mContactPhotoManager = ContactPhotoManager.getInstance(this);
- mProximitySensorManager = new ProximitySensorManager(this, mProximitySensorListener);
+ final PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ if (powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
+ mProximityWakeLock = powerManager.newWakeLock(
+ PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
+ } else {
+ mProximityWakeLock = null;
+ }
+
mContactInfoHelper = new ContactInfoHelper(this, GeoUtil.getCurrentCountryIso(this));
getActionBar().setDisplayHomeAsUpEnabled(true);
@@ -752,18 +703,34 @@ public class CallDetailActivity extends Activity implements ProximitySensorAware
protected void onPause() {
// Immediately stop the proximity sensor.
disableProximitySensor(false);
- mProximitySensorListener.clearPendingRequests();
super.onPause();
}
@Override
public void enableProximitySensor() {
- mProximitySensorManager.enable();
+ if (mProximityWakeLock == null) {
+ return;
+ }
+ if (!mProximityWakeLock.isHeld()) {
+ Log.i(TAG, "Acquiring proximity wake lock");
+ mProximityWakeLock.acquire();
+ } else {
+ Log.i(TAG, "Proximity wake lock already acquired");
+ }
}
@Override
public void disableProximitySensor(boolean waitForFarState) {
- mProximitySensorManager.disable(waitForFarState);
+ if (mProximityWakeLock == null) {
+ return;
+ }
+ if (mProximityWakeLock.isHeld()) {
+ Log.i(TAG, "Releasing proximity wake lock");
+ int flags = (waitForFarState ? PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY : 0);
+ mProximityWakeLock.release(flags);
+ } else {
+ Log.i(TAG, "Proximity wake lock already released");
+ }
}
private void closeSystemDialogs() {
diff --git a/src/com/android/dialer/ProximitySensorManager.java b/src/com/android/dialer/ProximitySensorManager.java
deleted file mode 100644
index 42d740fc1..000000000
--- a/src/com/android/dialer/ProximitySensorManager.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2011 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.dialer;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-
-import javax.annotation.concurrent.GuardedBy;
-
-/**
- * Manages the proximity sensor and notifies a listener when enabled.
- */
-public class ProximitySensorManager {
- /**
- * Listener of the state of the proximity sensor.
- * <p>
- * This interface abstracts two possible states for the proximity sensor, near and far.
- * <p>
- * The actual meaning of these states depends on the actual sensor.
- */
- public interface Listener {
- /** Called when the proximity sensor transitions from the far to the near state. */
- public void onNear();
- /** Called when the proximity sensor transitions from the near to the far state. */
- public void onFar();
- }
-
- public static enum State {
- NEAR, FAR
- }
-
- private final ProximitySensorEventListener mProximitySensorListener;
-
- /**
- * The current state of the manager, i.e., whether it is currently tracking the state of the
- * sensor.
- */
- private boolean mManagerEnabled;
-
- /**
- * The listener to the state of the sensor.
- * <p>
- * Contains most of the logic concerning tracking of the sensor.
- * <p>
- * After creating an instance of this object, one should call {@link #register()} and
- * {@link #unregister()} to enable and disable the notifications.
- * <p>
- * Instead of calling unregister, one can call {@link #unregisterWhenFar()} to unregister the
- * listener the next time the sensor reaches the {@link State#FAR} state if currently in the
- * {@link State#NEAR} state.
- */
- private static class ProximitySensorEventListener implements SensorEventListener {
- private static final float FAR_THRESHOLD = 5.0f;
-
- private final SensorManager mSensorManager;
- private final Sensor mProximitySensor;
- private final float mMaxValue;
- private final Listener mListener;
-
- /**
- * The last state of the sensor.
- * <p>
- * Before registering and after unregistering we are always in the {@link State#FAR} state.
- */
- @GuardedBy("this") private State mLastState;
- /**
- * If this flag is set to true, we are waiting to reach the {@link State#FAR} state and
- * should notify the listener and unregister when that happens.
- */
- @GuardedBy("this") private boolean mWaitingForFarState;
-
- public ProximitySensorEventListener(SensorManager sensorManager, Sensor proximitySensor,
- Listener listener) {
- mSensorManager = sensorManager;
- mProximitySensor = proximitySensor;
- mMaxValue = proximitySensor.getMaximumRange();
- mListener = listener;
- // Initialize at far state.
- mLastState = State.FAR;
- mWaitingForFarState = false;
- }
-
- @Override
- public void onSensorChanged(SensorEvent event) {
- // Make sure we have a valid value.
- if (event.values == null) return;
- if (event.values.length == 0) return;
- float value = event.values[0];
- // Convert the sensor into a NEAR/FAR state.
- State state = getStateFromValue(value);
- synchronized (this) {
- // No change in state, do nothing.
- if (state == mLastState) return;
- // Keep track of the current state.
- mLastState = state;
- // If we are waiting to reach the far state and we are now in it, unregister.
- if (mWaitingForFarState && mLastState == State.FAR) {
- unregisterWithoutNotification();
- }
- }
- // Notify the listener of the state change.
- switch (state) {
- case NEAR:
- mListener.onNear();
- break;
-
- case FAR:
- mListener.onFar();
- break;
- }
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // Nothing to do here.
- }
-
- /** Returns the state of the sensor given its current value. */
- private State getStateFromValue(float value) {
- // Determine if the current value corresponds to the NEAR or FAR state.
- // Take case of the case where the proximity sensor is binary: if the current value is
- // equal to the maximum, we are always in the FAR state.
- return (value > FAR_THRESHOLD || value == mMaxValue) ? State.FAR : State.NEAR;
- }
-
- /**
- * Unregister the next time the sensor reaches the {@link State#FAR} state.
- */
- public synchronized void unregisterWhenFar() {
- if (mLastState == State.FAR) {
- // We are already in the far state, just unregister now.
- unregisterWithoutNotification();
- } else {
- mWaitingForFarState = true;
- }
- }
-
- /** Register the listener and call the listener as necessary. */
- public synchronized void register() {
- // It is okay to register multiple times.
- mSensorManager.registerListener(this, mProximitySensor, SensorManager.SENSOR_DELAY_UI);
- // We should no longer be waiting for the far state if we are registering again.
- mWaitingForFarState = false;
- }
-
- public void unregister() {
- State lastState;
- synchronized (this) {
- unregisterWithoutNotification();
- lastState = mLastState;
- // Always go back to the FAR state. That way, when we register again we will get a
- // transition when the sensor gets into the NEAR state.
- mLastState = State.FAR;
- }
- // Notify the listener if we changed the state to FAR while unregistering.
- if (lastState != State.FAR) {
- mListener.onFar();
- }
- }
-
- @GuardedBy("this")
- private void unregisterWithoutNotification() {
- mSensorManager.unregisterListener(this);
- mWaitingForFarState = false;
- }
- }
-
- public ProximitySensorManager(Context context, Listener listener) {
- SensorManager sensorManager =
- (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
- Sensor proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- if (proximitySensor == null) {
- // If there is no sensor, we should not do anything.
- mProximitySensorListener = null;
- } else {
- mProximitySensorListener =
- new ProximitySensorEventListener(sensorManager, proximitySensor, listener);
- }
- }
-
- /**
- * Enables the proximity manager.
- * <p>
- * The listener will start getting notifications of events.
- * <p>
- * This method is idempotent.
- */
- public void enable() {
- if (mProximitySensorListener != null && !mManagerEnabled) {
- mProximitySensorListener.register();
- mManagerEnabled = true;
- }
- }
-
- /**
- * Disables the proximity manager.
- * <p>
- * The listener will stop receiving notifications of events, possibly after receiving a last
- * {@link Listener#onFar()} callback.
- * <p>
- * If {@code waitForFarState} is true, if the sensor is not currently in the {@link State#FAR}
- * state, the listener will receive a {@link Listener#onFar()} callback the next time the sensor
- * actually reaches the {@link State#FAR} state.
- * <p>
- * If {@code waitForFarState} is false, the listener will receive a {@link Listener#onFar()}
- * callback immediately if the sensor is currently not in the {@link State#FAR} state.
- * <p>
- * This method is idempotent.
- */
- public void disable(boolean waitForFarState) {
- if (mProximitySensorListener != null && mManagerEnabled) {
- if (waitForFarState) {
- mProximitySensorListener.unregisterWhenFar();
- } else {
- mProximitySensorListener.unregister();
- }
- mManagerEnabled = false;
- }
- }
-}