From 7151398929e487f7f74b285f3e4c478f95daa7c6 Mon Sep 17 00:00:00 2001 From: Yorke Lee Date: Wed, 25 Feb 2015 20:23:53 -0800 Subject: Use new PowerManager API to implement voicemail proximity This allows us to fully blank out the screen instead of faking a black screen leaving the nav bar and notification bar active. Bug: 11734938 Change-Id: I716642fa7f85776d1701d3b95736065dec4d2eac --- src/com/android/dialer/CallDetailActivity.java | 91 +++----- src/com/android/dialer/ProximitySensorManager.java | 237 --------------------- 2 files changed, 29 insertions(+), 299 deletions(-) delete mode 100644 src/com/android/dialer/ProximitySensorManager.java (limited to 'src') diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java index fb663d729..08c9e029b 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, @@ -250,7 +194,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); @@ -751,18 +702,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. - *

- * This interface abstracts two possible states for the proximity sensor, near and far. - *

- * 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. - *

- * Contains most of the logic concerning tracking of the sensor. - *

- * After creating an instance of this object, one should call {@link #register()} and - * {@link #unregister()} to enable and disable the notifications. - *

- * 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. - *

- * 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. - *

- * The listener will start getting notifications of events. - *

- * This method is idempotent. - */ - public void enable() { - if (mProximitySensorListener != null && !mManagerEnabled) { - mProximitySensorListener.register(); - mManagerEnabled = true; - } - } - - /** - * Disables the proximity manager. - *

- * The listener will stop receiving notifications of events, possibly after receiving a last - * {@link Listener#onFar()} callback. - *

- * 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. - *

- * 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. - *

- * This method is idempotent. - */ - public void disable(boolean waitForFarState) { - if (mProximitySensorListener != null && mManagerEnabled) { - if (waitForFarState) { - mProximitySensorListener.unregisterWhenFar(); - } else { - mProximitySensorListener.unregister(); - } - mManagerEnabled = false; - } - } -} -- cgit v1.2.3