170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar/* 270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Copyright (C) 2015 The Android Open Source Project 370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * 470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Licensed under the Apache License, Version 2.0 (the "License"); 570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * you may not use this file except in compliance with the License. 670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * You may obtain a copy of the License at 770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * 870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * http://www.apache.org/licenses/LICENSE-2.0 970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * 1070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Unless required by applicable law or agreed to in writing, software 1170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * distributed under the License is distributed on an "AS IS" BASIS, 1270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * See the License for the specific language governing permissions and 1470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * limitations under the License 1570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar */ 1670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 1770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkarpackage com.android.incallui; 1870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 1970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkarimport android.content.Context; 2070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkarimport android.content.res.Configuration; 2170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkarimport android.view.OrientationEventListener; 2270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkarimport android.hardware.SensorManager; 2370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkarimport android.view.Surface; 2470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkarimport android.content.pm.ActivityInfo; 2570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 2670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar/** 2770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * This class listens to Orientation events and overrides onOrientationChanged which gets 2870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * invoked when an orientation change occurs. When that happens, we notify InCallUI registrants 2970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * of the change. 3070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar */ 3170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkarpublic class InCallOrientationEventListener extends OrientationEventListener { 3270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 3370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar /** 3470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Screen orientation angles one of 0, 90, 180, 270, 360 in degrees. 3570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar */ 3670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public static int SCREEN_ORIENTATION_0 = 0; 3770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public static int SCREEN_ORIENTATION_90 = 90; 3870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public static int SCREEN_ORIENTATION_180 = 180; 3970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public static int SCREEN_ORIENTATION_270 = 270; 4070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public static int SCREEN_ORIENTATION_360 = 360; 4170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 4270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public static int FULL_SENSOR_SCREEN_ORIENTATION = 4370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; 4470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 4570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public static int NO_SENSOR_SCREEN_ORIENTATION = 4670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 4770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 4870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar /** 4970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * This is to identify dead zones where we won't notify others of orientation changed. 5070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Say for e.g our threshold is x degrees. We will only notify UI when our current rotation is 5170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * within x degrees right or left of the screen orientation angles. If it's not within those 5270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * ranges, we return SCREEN_ORIENTATION_UNKNOWN and ignore it. 5370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar */ 5470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar private static int SCREEN_ORIENTATION_UNKNOWN = -1; 5570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 5670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar // Rotation threshold is 10 degrees. So if the rotation angle is within 10 degrees of any of 5770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar // the above angles, we will notify orientation changed. 5870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar private static int ROTATION_THRESHOLD = 10; 5970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 6070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 6170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar /** 6270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Cache the current rotation of the device. 6370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar */ 6470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar private static int sCurrentOrientation = SCREEN_ORIENTATION_0; 6550b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn private boolean mEnabled = false; 6670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 6770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public InCallOrientationEventListener(Context context) { 6870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar super(context); 6970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 7070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 7170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar /** 7270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Handles changes in device orientation. Notifies InCallPresenter of orientation changes. 7370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * 7470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Note that this API receives sensor rotation in degrees as a param and we convert that to 7570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * one of our screen orientation constants - (one of: {@link SCREEN_ORIENTATION_0}, 7670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * {@link SCREEN_ORIENTATION_90}, {@link SCREEN_ORIENTATION_180}, 7770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * {@link SCREEN_ORIENTATION_270}). 7870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * 7970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * @param rotation The new device sensor rotation in degrees 8070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar */ 8170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar @Override 8270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public void onOrientationChanged(int rotation) { 8370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar if (rotation == OrientationEventListener.ORIENTATION_UNKNOWN) { 8470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return; 8570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 8670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 8770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar final int orientation = toScreenOrientation(rotation); 8870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 8970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar if (orientation != SCREEN_ORIENTATION_UNKNOWN && sCurrentOrientation != orientation) { 9070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar sCurrentOrientation = orientation; 9170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation); 9270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 9370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 9470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 9570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar /** 9670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Enables the OrientationEventListener and notifies listeners of current orientation if 9770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * notify flag is true 9870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * @param notify true or false. Notify device orientation changed if true. 9970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar */ 10070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public void enable(boolean notify) { 10150b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn if (mEnabled) { 10250b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn Log.v(this, "enable: Orientation listener is already enabled. Ignoring..."); 10350b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn return; 10450b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn } 10550b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn 10670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar super.enable(); 10750b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn mEnabled = true; 10870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar if (notify) { 10970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation); 11070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 11170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 11270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 11370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar /** 11470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Enables the OrientationEventListener with notify flag defaulting to false. 11570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar */ 11670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar public void enable() { 11770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar enable(false); 11870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 11970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 12070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar /** 12150b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn * Disables the OrientationEventListener. 12250b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn */ 12350b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn public void disable() { 12450b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn if (!mEnabled) { 12550b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn Log.v(this, "enable: Orientation listener is already disabled. Ignoring..."); 12650b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn return; 12750b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn } 12850b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn 12950b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn mEnabled = false; 13050b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn super.disable(); 13150b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn } 13250b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn 13350b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn /** 13450b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn * Returns true the OrientationEventListener is enabled, false otherwise. 13550b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn */ 13650b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn public boolean isEnabled() { 13750b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn return mEnabled; 13850b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn } 13950b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn 14050b2f304bde9bdb8c8c5ca57efafb53a417afa78Tyler Gunn /** 14170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * Converts sensor rotation in degrees to screen orientation constants. 14270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * @param rotation sensor rotation angle in degrees 14370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * @return Screen orientation angle in degrees (0, 90, 180, 270). Returns -1 for degrees not 14470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar * within threshold to identify zones where orientation change should not be trigerred. 14570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar */ 14670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar private int toScreenOrientation(int rotation) { 14770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar // Sensor orientation 90 is equivalent to screen orientation 270 and vice versa. This 14870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar // function returns the screen orientation. So we convert sensor rotation 90 to 270 and 14970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar // vice versa here. 15070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar if (isInLeftRange(rotation, SCREEN_ORIENTATION_360, ROTATION_THRESHOLD) || 15170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar isInRightRange(rotation, SCREEN_ORIENTATION_0, ROTATION_THRESHOLD)) { 15270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return SCREEN_ORIENTATION_0; 15370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_90, ROTATION_THRESHOLD)) { 15470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return SCREEN_ORIENTATION_270; 15570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_180, ROTATION_THRESHOLD)) { 15670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return SCREEN_ORIENTATION_180; 15770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } else if (isWithinThreshold(rotation, SCREEN_ORIENTATION_270, ROTATION_THRESHOLD)) { 15870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return SCREEN_ORIENTATION_90; 15970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 16070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return SCREEN_ORIENTATION_UNKNOWN; 16170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 16270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 16370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar private static boolean isWithinRange(int value, int begin, int end) { 16470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return value >= begin && value < end; 16570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 16670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 16770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar private static boolean isWithinThreshold(int value, int center, int threshold) { 16870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return isWithinRange(value, center - threshold, center + threshold); 16970c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 17070c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 17170c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar private static boolean isInLeftRange(int value, int center, int threshold) { 17270c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return isWithinRange(value, center - threshold, center); 17370c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 17470c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar 17570c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar private static boolean isInRightRange(int value, int center, int threshold) { 17670c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar return isWithinRange(value, center, center + threshold); 17770c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar } 17870c216c16d28552d851aadcc0bf6928522f0da6bNivedita Sarkar} 179