blob: 854bdd1930626bf796f062156136c3e0ccdd6ff1 [file] [log] [blame]
/*
* 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;
}
}