summaryrefslogtreecommitdiff
path: root/java/com/android/incallui/InCallOrientationEventListener.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/incallui/InCallOrientationEventListener.java')
-rw-r--r--java/com/android/incallui/InCallOrientationEventListener.java194
1 files changed, 194 insertions, 0 deletions
diff --git a/java/com/android/incallui/InCallOrientationEventListener.java b/java/com/android/incallui/InCallOrientationEventListener.java
new file mode 100644
index 000000000..e6b0bc027
--- /dev/null
+++ b/java/com/android/incallui/InCallOrientationEventListener.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2015 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.incallui;
+
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.support.annotation.IntDef;
+import android.view.OrientationEventListener;
+import com.android.dialer.common.LogUtil;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class listens to Orientation events and overrides onOrientationChanged which gets invoked
+ * when an orientation change occurs. When that happens, we notify InCallUI registrants of the
+ * change.
+ */
+public class InCallOrientationEventListener extends OrientationEventListener {
+
+ public static final int SCREEN_ORIENTATION_0 = 0;
+ public static final int SCREEN_ORIENTATION_90 = 90;
+ public static final int SCREEN_ORIENTATION_180 = 180;
+ public static final int SCREEN_ORIENTATION_270 = 270;
+ public static final int SCREEN_ORIENTATION_360 = 360;
+
+ /** Screen orientation angles one of 0, 90, 180, 270, 360 in degrees. */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ SCREEN_ORIENTATION_0,
+ SCREEN_ORIENTATION_90,
+ SCREEN_ORIENTATION_180,
+ SCREEN_ORIENTATION_270,
+ SCREEN_ORIENTATION_360,
+ SCREEN_ORIENTATION_UNKNOWN
+ })
+ public @interface ScreenOrientation {}
+
+ // We use SCREEN_ORIENTATION_USER so that reverse-portrait is not allowed.
+ public static final int ACTIVITY_PREFERENCE_ALLOW_ROTATION = ActivityInfo.SCREEN_ORIENTATION_USER;
+
+ public static final int ACTIVITY_PREFERENCE_DISALLOW_ROTATION =
+ ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+
+ /**
+ * This is to identify dead zones where we won't notify others of orientation changed. Say for e.g
+ * our threshold is x degrees. We will only notify UI when our current rotation is within x
+ * degrees right or left of the screen orientation angles. If it's not within those ranges, we
+ * return SCREEN_ORIENTATION_UNKNOWN and ignore it.
+ */
+ public static final int SCREEN_ORIENTATION_UNKNOWN = -1;
+
+ // Rotation threshold is 10 degrees. So if the rotation angle is within 10 degrees of any of
+ // the above angles, we will notify orientation changed.
+ private static final int ROTATION_THRESHOLD = 10;
+
+ /** Cache the current rotation of the device. */
+ @ScreenOrientation private static int sCurrentOrientation = SCREEN_ORIENTATION_0;
+
+ private boolean mEnabled = false;
+
+ public InCallOrientationEventListener(Context context) {
+ super(context);
+ }
+
+ private static boolean isWithinRange(int value, int begin, int end) {
+ return value >= begin && value < end;
+ }
+
+ private static boolean isWithinThreshold(int value, int center, int threshold) {
+ return isWithinRange(value, center - threshold, center + threshold);
+ }
+
+ private static boolean isInLeftRange(int value, int center, int threshold) {
+ return isWithinRange(value, center - threshold, center);
+ }
+
+ private static boolean isInRightRange(int value, int center, int threshold) {
+ return isWithinRange(value, center, center + threshold);
+ }
+
+ @ScreenOrientation
+ public static int getCurrentOrientation() {
+ return sCurrentOrientation;
+ }
+
+ /**
+ * Handles changes in device orientation. Notifies InCallPresenter of orientation changes.
+ *
+ * <p>Note that this API receives sensor rotation in degrees as a param and we convert that to one
+ * of our screen orientation constants - (one of: {@link #SCREEN_ORIENTATION_0}, {@link
+ * #SCREEN_ORIENTATION_90}, {@link #SCREEN_ORIENTATION_180}, {@link #SCREEN_ORIENTATION_270}).
+ *
+ * @param rotation The new device sensor rotation in degrees
+ */
+ @Override
+ public void onOrientationChanged(int rotation) {
+ if (rotation == OrientationEventListener.ORIENTATION_UNKNOWN) {
+ return;
+ }
+
+ final int orientation = toScreenOrientation(rotation);
+
+ if (orientation != SCREEN_ORIENTATION_UNKNOWN && sCurrentOrientation != orientation) {
+ LogUtil.i(
+ "InCallOrientationEventListener.onOrientationChanged",
+ "orientation: %d -> %d",
+ sCurrentOrientation,
+ orientation);
+ sCurrentOrientation = orientation;
+ InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation);
+ }
+ }
+
+ /**
+ * Enables the OrientationEventListener and notifies listeners of current orientation if notify
+ * flag is true
+ *
+ * @param notify true or false. Notify device orientation changed if true.
+ */
+ public void enable(boolean notify) {
+ if (mEnabled) {
+ Log.v(this, "enable: Orientation listener is already enabled. Ignoring...");
+ return;
+ }
+
+ super.enable();
+ mEnabled = true;
+ if (notify) {
+ InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation);
+ }
+ }
+
+ /** Enables the OrientationEventListener with notify flag defaulting to false. */
+ @Override
+ public void enable() {
+ enable(false);
+ }
+
+ /** Disables the OrientationEventListener. */
+ @Override
+ public void disable() {
+ if (!mEnabled) {
+ Log.v(this, "enable: Orientation listener is already disabled. Ignoring...");
+ return;
+ }
+
+ mEnabled = false;
+ super.disable();
+ }
+
+ /** Returns true the OrientationEventListener is enabled, false otherwise. */
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ /**
+ * Converts sensor rotation in degrees to screen orientation constants.
+ *
+ * @param rotation sensor rotation angle in degrees
+ * @return Screen orientation angle in degrees (0, 90, 180, 270). Returns -1 for degrees not
+ * within threshold to identify zones where orientation change should not be trigerred.
+ */
+ @ScreenOrientation
+ private int toScreenOrientation(int rotation) {
+ // Sensor orientation 90 is equivalent to screen orientation 270 and vice versa. This
+ // function returns the screen orientation. So we convert sensor rotation 90 to 270 and
+ // vice versa here.
+ if (isInLeftRange(rotation, SCREEN_ORIENTATION_360, ROTATION_THRESHOLD)
+ || isInRightRange(rotation, SCREEN_ORIENTATION_0, ROTATION_THRESHOLD)) {
+ return SCREEN_ORIENTATION_0;
+ } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_90, ROTATION_THRESHOLD)) {
+ return SCREEN_ORIENTATION_270;
+ } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_180, ROTATION_THRESHOLD)) {
+ return SCREEN_ORIENTATION_180;
+ } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_270, ROTATION_THRESHOLD)) {
+ return SCREEN_ORIENTATION_90;
+ }
+ return SCREEN_ORIENTATION_UNKNOWN;
+ }
+}