1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.incallui; 18 19 import android.content.Context; 20 import android.content.res.Configuration; 21 import android.view.OrientationEventListener; 22 import android.hardware.SensorManager; 23 import android.view.Surface; 24 import android.content.pm.ActivityInfo; 25 26 /** 27 * This class listens to Orientation events and overrides onOrientationChanged which gets 28 * invoked when an orientation change occurs. When that happens, we notify InCallUI registrants 29 * of the change. 30 */ 31 public class InCallOrientationEventListener extends OrientationEventListener { 32 33 /** 34 * Screen orientation angles one of 0, 90, 180, 270, 360 in degrees. 35 */ 36 public static int SCREEN_ORIENTATION_0 = 0; 37 public static int SCREEN_ORIENTATION_90 = 90; 38 public static int SCREEN_ORIENTATION_180 = 180; 39 public static int SCREEN_ORIENTATION_270 = 270; 40 public static int SCREEN_ORIENTATION_360 = 360; 41 42 public static int FULL_SENSOR_SCREEN_ORIENTATION = 43 ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; 44 45 public static int NO_SENSOR_SCREEN_ORIENTATION = 46 ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 47 48 /** 49 * This is to identify dead zones where we won't notify others of orientation changed. 50 * Say for e.g our threshold is x degrees. We will only notify UI when our current rotation is 51 * within x degrees right or left of the screen orientation angles. If it's not within those 52 * ranges, we return SCREEN_ORIENTATION_UNKNOWN and ignore it. 53 */ 54 private static int SCREEN_ORIENTATION_UNKNOWN = -1; 55 56 // Rotation threshold is 10 degrees. So if the rotation angle is within 10 degrees of any of 57 // the above angles, we will notify orientation changed. 58 private static int ROTATION_THRESHOLD = 10; 59 60 61 /** 62 * Cache the current rotation of the device. 63 */ 64 private static int sCurrentOrientation = SCREEN_ORIENTATION_0; 65 InCallOrientationEventListener(Context context)66 public InCallOrientationEventListener(Context context) { 67 super(context); 68 } 69 70 /** 71 * Handles changes in device orientation. Notifies InCallPresenter of orientation changes. 72 * 73 * Note that this API receives sensor rotation in degrees as a param and we convert that to 74 * one of our screen orientation constants - (one of: {@link SCREEN_ORIENTATION_0}, 75 * {@link SCREEN_ORIENTATION_90}, {@link SCREEN_ORIENTATION_180}, 76 * {@link SCREEN_ORIENTATION_270}). 77 * 78 * @param rotation The new device sensor rotation in degrees 79 */ 80 @Override onOrientationChanged(int rotation)81 public void onOrientationChanged(int rotation) { 82 if (rotation == OrientationEventListener.ORIENTATION_UNKNOWN) { 83 return; 84 } 85 86 final int orientation = toScreenOrientation(rotation); 87 88 if (orientation != SCREEN_ORIENTATION_UNKNOWN && sCurrentOrientation != orientation) { 89 sCurrentOrientation = orientation; 90 InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation); 91 } 92 } 93 94 /** 95 * Enables the OrientationEventListener and notifies listeners of current orientation if 96 * notify flag is true 97 * @param notify true or false. Notify device orientation changed if true. 98 */ enable(boolean notify)99 public void enable(boolean notify) { 100 super.enable(); 101 if (notify) { 102 InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation); 103 } 104 } 105 106 /** 107 * Enables the OrientationEventListener with notify flag defaulting to false. 108 */ enable()109 public void enable() { 110 enable(false); 111 } 112 113 /** 114 * Converts sensor rotation in degrees to screen orientation constants. 115 * @param rotation sensor rotation angle in degrees 116 * @return Screen orientation angle in degrees (0, 90, 180, 270). Returns -1 for degrees not 117 * within threshold to identify zones where orientation change should not be trigerred. 118 */ toScreenOrientation(int rotation)119 private int toScreenOrientation(int rotation) { 120 // Sensor orientation 90 is equivalent to screen orientation 270 and vice versa. This 121 // function returns the screen orientation. So we convert sensor rotation 90 to 270 and 122 // vice versa here. 123 if (isInLeftRange(rotation, SCREEN_ORIENTATION_360, ROTATION_THRESHOLD) || 124 isInRightRange(rotation, SCREEN_ORIENTATION_0, ROTATION_THRESHOLD)) { 125 return SCREEN_ORIENTATION_0; 126 } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_90, ROTATION_THRESHOLD)) { 127 return SCREEN_ORIENTATION_270; 128 } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_180, ROTATION_THRESHOLD)) { 129 return SCREEN_ORIENTATION_180; 130 } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_270, ROTATION_THRESHOLD)) { 131 return SCREEN_ORIENTATION_90; 132 } 133 return SCREEN_ORIENTATION_UNKNOWN; 134 } 135 isWithinRange(int value, int begin, int end)136 private static boolean isWithinRange(int value, int begin, int end) { 137 return value >= begin && value < end; 138 } 139 isWithinThreshold(int value, int center, int threshold)140 private static boolean isWithinThreshold(int value, int center, int threshold) { 141 return isWithinRange(value, center - threshold, center + threshold); 142 } 143 isInLeftRange(int value, int center, int threshold)144 private static boolean isInLeftRange(int value, int center, int threshold) { 145 return isWithinRange(value, center - threshold, center); 146 } 147 isInRightRange(int value, int center, int threshold)148 private static boolean isInRightRange(int value, int center, int threshold) { 149 return isWithinRange(value, center, center + threshold); 150 } 151 } 152