Home | History | Annotate | Download | only in incallui
      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