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 private boolean mEnabled = false; 66 67 public InCallOrientationEventListener(Context context) { 68 super(context); 69 } 70 71 /** 72 * Handles changes in device orientation. Notifies InCallPresenter of orientation changes. 73 * 74 * Note that this API receives sensor rotation in degrees as a param and we convert that to 75 * one of our screen orientation constants - (one of: {@link SCREEN_ORIENTATION_0}, 76 * {@link SCREEN_ORIENTATION_90}, {@link SCREEN_ORIENTATION_180}, 77 * {@link SCREEN_ORIENTATION_270}). 78 * 79 * @param rotation The new device sensor rotation in degrees 80 */ 81 @Override 82 public void onOrientationChanged(int rotation) { 83 if (rotation == OrientationEventListener.ORIENTATION_UNKNOWN) { 84 return; 85 } 86 87 final int orientation = toScreenOrientation(rotation); 88 89 if (orientation != SCREEN_ORIENTATION_UNKNOWN && sCurrentOrientation != orientation) { 90 sCurrentOrientation = orientation; 91 InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation); 92 } 93 } 94 95 /** 96 * Enables the OrientationEventListener and notifies listeners of current orientation if 97 * notify flag is true 98 * @param notify true or false. Notify device orientation changed if true. 99 */ 100 public void enable(boolean notify) { 101 if (mEnabled) { 102 Log.v(this, "enable: Orientation listener is already enabled. Ignoring..."); 103 return; 104 } 105 106 super.enable(); 107 mEnabled = true; 108 if (notify) { 109 InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation); 110 } 111 } 112 113 /** 114 * Enables the OrientationEventListener with notify flag defaulting to false. 115 */ 116 public void enable() { 117 enable(false); 118 } 119 120 /** 121 * Disables the OrientationEventListener. 122 */ 123 public void disable() { 124 if (!mEnabled) { 125 Log.v(this, "enable: Orientation listener is already disabled. Ignoring..."); 126 return; 127 } 128 129 mEnabled = false; 130 super.disable(); 131 } 132 133 /** 134 * Returns true the OrientationEventListener is enabled, false otherwise. 135 */ 136 public boolean isEnabled() { 137 return mEnabled; 138 } 139 140 /** 141 * Converts sensor rotation in degrees to screen orientation constants. 142 * @param rotation sensor rotation angle in degrees 143 * @return Screen orientation angle in degrees (0, 90, 180, 270). Returns -1 for degrees not 144 * within threshold to identify zones where orientation change should not be trigerred. 145 */ 146 private int toScreenOrientation(int rotation) { 147 // Sensor orientation 90 is equivalent to screen orientation 270 and vice versa. This 148 // function returns the screen orientation. So we convert sensor rotation 90 to 270 and 149 // vice versa here. 150 if (isInLeftRange(rotation, SCREEN_ORIENTATION_360, ROTATION_THRESHOLD) || 151 isInRightRange(rotation, SCREEN_ORIENTATION_0, ROTATION_THRESHOLD)) { 152 return SCREEN_ORIENTATION_0; 153 } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_90, ROTATION_THRESHOLD)) { 154 return SCREEN_ORIENTATION_270; 155 } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_180, ROTATION_THRESHOLD)) { 156 return SCREEN_ORIENTATION_180; 157 } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_270, ROTATION_THRESHOLD)) { 158 return SCREEN_ORIENTATION_90; 159 } 160 return SCREEN_ORIENTATION_UNKNOWN; 161 } 162 163 private static boolean isWithinRange(int value, int begin, int end) { 164 return value >= begin && value < end; 165 } 166 167 private static boolean isWithinThreshold(int value, int center, int threshold) { 168 return isWithinRange(value, center - threshold, center + threshold); 169 } 170 171 private static boolean isInLeftRange(int value, int center, int threshold) { 172 return isWithinRange(value, center - threshold, center); 173 } 174 175 private static boolean isInRightRange(int value, int center, int threshold) { 176 return isWithinRange(value, center, center + threshold); 177 } 178 } 179