| /* |
| * 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 currentOrientation = SCREEN_ORIENTATION_0; |
| |
| private boolean enabled = 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 currentOrientation; |
| } |
| |
| /** |
| * 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 && currentOrientation != orientation) { |
| LogUtil.i( |
| "InCallOrientationEventListener.onOrientationChanged", |
| "orientation: %d -> %d", |
| currentOrientation, |
| orientation); |
| currentOrientation = orientation; |
| InCallPresenter.getInstance().onDeviceOrientationChange(currentOrientation); |
| } |
| } |
| |
| /** |
| * Enables the OrientationEventListener and optionally notifies listeners of the current |
| * orientation. |
| * |
| * @param notifyDeviceOrientationChange Whether to notify listeners that the device orientation is |
| * changed. |
| */ |
| public void enable(boolean notifyDeviceOrientationChange) { |
| if (enabled) { |
| Log.v(this, "enable: Orientation listener is already enabled. Ignoring..."); |
| return; |
| } |
| |
| super.enable(); |
| enabled = true; |
| if (notifyDeviceOrientationChange) { |
| InCallPresenter.getInstance().onDeviceOrientationChange(currentOrientation); |
| } |
| } |
| |
| /** Enables the OrientationEventListener. */ |
| @Override |
| public void enable() { |
| enable(false /* notifyDeviceOrientationChange */); |
| } |
| |
| /** Disables the OrientationEventListener. */ |
| @Override |
| public void disable() { |
| if (!enabled) { |
| Log.v(this, "enable: Orientation listener is already disabled. Ignoring..."); |
| return; |
| } |
| |
| enabled = false; |
| super.disable(); |
| } |
| |
| /** Returns true the OrientationEventListener is enabled, false otherwise. */ |
| public boolean isEnabled() { |
| return enabled; |
| } |
| |
| /** |
| * 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; |
| } |
| } |