diff options
Diffstat (limited to 'InCallUI')
5 files changed, 240 insertions, 125 deletions
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java index a807a12ea..3dc2c9daf 100644 --- a/InCallUI/src/com/android/incallui/InCallActivity.java +++ b/InCallUI/src/com/android/incallui/InCallActivity.java @@ -90,6 +90,7 @@ public class InCallActivity extends TransactionSafeActivity implements FragmentD private FragmentManager mChildFragmentManager; private AlertDialog mDialog; + private InCallOrientationEventListener mInCallOrientationEventListener; /** * Use to pass 'showDialpad' from {@link #onNewIntent} to {@link #onResume} @@ -146,11 +147,6 @@ public class InCallActivity extends TransactionSafeActivity implements FragmentD */ private OrientationEventListener mOrientationEventListener; - /** - * Used to determine if a change in rotation has occurred. - */ - private static int sPreviousRotation = -1; - @Override protected void onCreate(Bundle icicle) { Log.d(this, "onCreate()... this = " + this); @@ -218,41 +214,7 @@ public class InCallActivity extends TransactionSafeActivity implements FragmentD } } - mOrientationEventListener = new OrientationEventListener(this, - SensorManager.SENSOR_DELAY_NORMAL) { - @Override - public void onOrientationChanged(int orientation) { - // Device is flat, don't change orientation. - if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) { - return; - } - - int newRotation; - // We only shift if we're within 22.5 (23) degrees of the target - // orientation. This avoids flopping back and forth when holding - // the device at 45 degrees or so. - if (orientation >= 337 || orientation <= 23) { - newRotation = Surface.ROTATION_0; - } else if (orientation >= 67 && orientation <= 113) { - // Why not 90? Because screen and sensor orientation are - // reversed. - newRotation = Surface.ROTATION_270; - } else if (orientation >= 157 && orientation <= 203) { - newRotation = Surface.ROTATION_180; - } else if (orientation >= 247 && orientation <= 293) { - newRotation = Surface.ROTATION_90; - } else { - // Device is between orientations, so leave orientation the same. - return; - } - - // Orientation is the current device orientation in degrees. Ultimately we want - // the rotation (in fixed 90 degree intervals). - if (newRotation != sPreviousRotation) { - doOrientationChanged(newRotation); - } - } - }; + mInCallOrientationEventListener = new InCallOrientationEventListener(this); Log.d(this, "onCreate(): exit"); } @@ -283,6 +245,8 @@ public class InCallActivity extends TransactionSafeActivity implements FragmentD // setting activity should be last thing in setup process InCallPresenter.getInstance().setActivity(this); + enableInCallOrientationEventListener(getRequestedOrientation() == + InCallOrientationEventListener.FULL_SENSOR_SCREEN_ORIENTATION); InCallPresenter.getInstance().onActivityStarted(); } @@ -331,6 +295,7 @@ public class InCallActivity extends TransactionSafeActivity implements FragmentD @Override protected void onStop() { Log.d(this, "onStop()..."); + enableInCallOrientationEventListener(false); InCallPresenter.getInstance().updateIsChangingConfigurations(); InCallPresenter.getInstance().onActivityStopped(); mOrientationEventListener.disable(); @@ -547,25 +512,6 @@ public class InCallActivity extends TransactionSafeActivity implements FragmentD return false; } - /** - * Handles changes in device rotation. - * - * @param rotation The new device rotation (one of: {@link Surface#ROTATION_0}, - * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, - * {@link Surface#ROTATION_270}). - */ - private void doOrientationChanged(int rotation) { - Log.d(this, "doOrientationChanged prevOrientation=" + sPreviousRotation + - " newOrientation=" + rotation); - // Check to see if the rotation changed to prevent triggering rotation change events - // for other configuration changes. - if (rotation != sPreviousRotation) { - sPreviousRotation = rotation; - InCallPresenter.getInstance().onDeviceRotationChange(rotation); - InCallPresenter.getInstance().onDeviceOrientationChange(sPreviousRotation); - } - } - public CallButtonFragment getCallButtonFragment() { return mCallButtonFragment; } @@ -944,4 +890,17 @@ public class InCallActivity extends TransactionSafeActivity implements FragmentD public void setDispatchTouchEventListener(OnTouchListener mDispatchTouchEventListener) { this.mDispatchTouchEventListener = mDispatchTouchEventListener; } + + /** + * Enables the OrientationEventListener if enable flag is true. Disables it if enable is + * false + * @param enable true or false. + */ + public void enableInCallOrientationEventListener(boolean enable) { + if (enable) { + mInCallOrientationEventListener.enable(enable); + } else { + mInCallOrientationEventListener.disable(); + } + } } diff --git a/InCallUI/src/com/android/incallui/InCallOrientationEventListener.java b/InCallUI/src/com/android/incallui/InCallOrientationEventListener.java new file mode 100644 index 000000000..d3334a3ef --- /dev/null +++ b/InCallUI/src/com/android/incallui/InCallOrientationEventListener.java @@ -0,0 +1,151 @@ +/* + * 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.res.Configuration; +import android.view.OrientationEventListener; +import android.hardware.SensorManager; +import android.view.Surface; +import android.content.pm.ActivityInfo; + +/** + * 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 { + + /** + * Screen orientation angles one of 0, 90, 180, 270, 360 in degrees. + */ + public static int SCREEN_ORIENTATION_0 = 0; + public static int SCREEN_ORIENTATION_90 = 90; + public static int SCREEN_ORIENTATION_180 = 180; + public static int SCREEN_ORIENTATION_270 = 270; + public static int SCREEN_ORIENTATION_360 = 360; + + public static int FULL_SENSOR_SCREEN_ORIENTATION = + ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; + + public static int NO_SENSOR_SCREEN_ORIENTATION = + 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. + */ + private static 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 int ROTATION_THRESHOLD = 10; + + + /** + * Cache the current rotation of the device. + */ + private static int sCurrentOrientation = SCREEN_ORIENTATION_0; + + public InCallOrientationEventListener(Context context) { + super(context); + } + + /** + * Handles changes in device orientation. Notifies InCallPresenter of orientation changes. + * + * 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 && sCurrentOrientation != orientation) { + sCurrentOrientation = orientation; + InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation); + } + } + + /** + * Enables the OrientationEventListener and notifies listeners of current orientation if + * notify flag is true + * @param notify true or false. Notify device orientation changed if true. + */ + public void enable(boolean notify) { + super.enable(); + if (notify) { + InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation); + } + } + + /** + * Enables the OrientationEventListener with notify flag defaulting to false. + */ + public void enable() { + enable(false); + } + + /** + * 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. + */ + 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; + } + + 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); + } +} diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java index c8fe0cb77..836c9242e 100644 --- a/InCallUI/src/com/android/incallui/InCallPresenter.java +++ b/InCallUI/src/com/android/incallui/InCallPresenter.java @@ -1525,64 +1525,32 @@ public class InCallPresenter implements CallList.Listener, } /** - * Handles changes to the device rotation. + * Notifies listeners of changes in orientation and notify calls of rotation angle change. * - * @param rotation The device rotation (one of: {@link Surface#ROTATION_0}, - * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, - * {@link Surface#ROTATION_270}). + * @param orientation The screen orientation of the device (one of: + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_0}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_90}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_180}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_270}). */ - public void onDeviceRotationChange(int rotation) { - Log.d(this, "onDeviceRotationChange: rotation=" + rotation); - // First translate to rotation in degrees. + public void onDeviceOrientationChange(int orientation) { + Log.d(this, "onDeviceOrientationChange: orientation= " + orientation); + if (mCallList != null) { - mCallList.notifyCallsOfDeviceRotation(toRotationAngle(rotation)); + mCallList.notifyCallsOfDeviceRotation(orientation); } else { - Log.w(this, "onDeviceRotationChange: CallList is null."); + Log.w(this, "onDeviceOrientationChange: CallList is null."); } - } - /** - * Converts rotation constants to rotation in degrees. - * @param rotation Rotation constants (one of: {@link Surface#ROTATION_0}, - * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, - * {@link Surface#ROTATION_270}). - */ - public static int toRotationAngle(int rotation) { - int rotationAngle; - switch (rotation) { - case Surface.ROTATION_0: - rotationAngle = 0; - break; - case Surface.ROTATION_90: - rotationAngle = 90; - break; - case Surface.ROTATION_180: - rotationAngle = 180; - break; - case Surface.ROTATION_270: - rotationAngle = 270; - break; - default: - rotationAngle = 0; - } - return rotationAngle; - } - - /** - * Notifies listeners of changes in orientation (e.g. portrait/landscape). - * - * @param orientation The orientation of the device (one of: {@link Surface#ROTATION_0}, - * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, - * {@link Surface#ROTATION_270}). - */ - public void onDeviceOrientationChange(int orientation) { + // Notify listeners of device orientation changed. for (InCallOrientationListener listener : mOrientationListeners) { listener.onDeviceOrientationChanged(orientation); } } /** - * Configures the in-call UI activity so it can change orientations or not. + * Configures the in-call UI activity so it can change orientations or not. Enables the + * orientation event listener if allowOrientationChange is true, disables it if false. * * @param allowOrientationChange {@code True} if the in-call UI can change between portrait * and landscape. {@Code False} if the in-call UI should be locked in portrait. @@ -1594,12 +1562,15 @@ public class InCallPresenter implements CallList.Listener, } if (!allowOrientationChange) { - mInCallActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); + mInCallActivity.setRequestedOrientation( + InCallOrientationEventListener.NO_SENSOR_SCREEN_ORIENTATION); } else { // Using SCREEN_ORIENTATION_FULL_SENSOR allows for reverse-portrait orientation, where // SCREEN_ORIENTATION_SENSOR does not. - mInCallActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); + mInCallActivity.setRequestedOrientation( + InCallOrientationEventListener.FULL_SENSOR_SCREEN_ORIENTATION); } + mInCallActivity.enableInCallOrientationEventListener(allowOrientationChange); } public void enableScreenTimeout(boolean enable) { diff --git a/InCallUI/src/com/android/incallui/VideoCallFragment.java b/InCallUI/src/com/android/incallui/VideoCallFragment.java index eca9ab883..7c83f6e7e 100644 --- a/InCallUI/src/com/android/incallui/VideoCallFragment.java +++ b/InCallUI/src/com/android/incallui/VideoCallFragment.java @@ -697,6 +697,33 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter, } } + /** + * Sets the rotation of the preview surface. Called when the dimensions change due to a + * device orientation change. + * + * Please note that the screen orientation passed in is subtracted from 360 to get the actual + * preview rotation values. + * + * @param rotation The screen orientation. One of - + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_0}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_90}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_180}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_270}). + */ + @Override + public void setPreviewRotation(int orientation) { + Log.d(this, "setPreviewRotation: orientation=" + orientation); + if (sPreviewSurface != null) { + TextureView preview = sPreviewSurface.getTextureView(); + + if (preview == null ) { + return; + } + + preview.setRotation(orientation); + } + } + @Override public void setPreviewSurfaceSize(int width, int height) { final boolean isPreviewSurfaceAvailable = sPreviewSurface != null; diff --git a/InCallUI/src/com/android/incallui/VideoCallPresenter.java b/InCallUI/src/com/android/incallui/VideoCallPresenter.java index eb9b62005..262adb46d 100644 --- a/InCallUI/src/com/android/incallui/VideoCallPresenter.java +++ b/InCallUI/src/com/android/incallui/VideoCallPresenter.java @@ -153,7 +153,7 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi /** * Determines the device orientation (portrait/lanscape). */ - private int mDeviceOrientation; + private int mDeviceOrientation = InCallOrientationEventListener.SCREEN_ORIENTATION_0; /** * Tracks the state of the preview surface negotiation with the telephony layer. @@ -247,7 +247,6 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi InCallVideoCallCallbackNotifier.getInstance().addSessionModificationListener(this); mCurrentVideoState = VideoProfile.STATE_AUDIO_ONLY; mCurrentCallState = Call.State.INVALID; - mDeviceOrientation = ui.getCurrentRotation(); } /** @@ -697,12 +696,7 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi videoCall.setDisplaySurface(ui.getDisplayVideoSurface()); } - final int rotation = ui.getCurrentRotation(); - if (rotation != VideoCallFragment.ORIENTATION_UNKNOWN) { - videoCall.setDeviceOrientation(InCallPresenter.toRotationAngle(rotation)); - onDeviceOrientationChanged(rotation); - } - + videoCall.setDeviceOrientation(mDeviceOrientation); enableCamera(videoCall, isCameraRequired(newVideoState)); } mCurrentVideoState = newVideoState; @@ -1010,21 +1004,31 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi /** * Handles changes to the device orientation. - * - * @param orientation The device orientation (one of: {@link Surface#ROTATION_0}, - * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, - * {@link Surface#ROTATION_270}). + * @param orientation The screen orientation of the device (one of: + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_0}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_90}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_180}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_270}). */ @Override public void onDeviceOrientationChanged(int orientation) { mDeviceOrientation = orientation; - Point previewDimensions = getUi().getPreviewSize(); + + VideoCallUi ui = getUi(); + if (ui == null) { + Log.e(this, "onDeviceOrientationChanged: VideoCallUi is null"); + return; + } + + Point previewDimensions = ui.getPreviewSize(); if (previewDimensions == null) { return; } Log.d(this, "onDeviceOrientationChanged: orientation=" + orientation + " size: " + previewDimensions); changePreviewDimensions(previewDimensions.x, previewDimensions.y); + + ui.setPreviewRotation(mDeviceOrientation); } @Override @@ -1074,10 +1078,12 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi /** * Sets the preview surface size based on the current device orientation. + * See: {@link InCallOrientationEventListener#SCREEN_ORIENTATION_0}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_90}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_180}, + * {@link InCallOrientationEventListener#SCREEN_ORIENTATION_270}). * - * @param orientation The device orientation (one of: {@link Surface#ROTATION_0}, - * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, - * {@link Surface#ROTATION_270}). + * @param orientation The device orientation * @param aspectRatio The aspect ratio of the camera (width / height). */ private void setPreviewSize(int orientation, float aspectRatio) { @@ -1089,8 +1095,8 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi int height; int width; - if (orientation == Surface.ROTATION_90 || orientation == Surface.ROTATION_270) { - // Landscape or reverse landscape orientation. + if (orientation == InCallOrientationEventListener.SCREEN_ORIENTATION_90 || + orientation == InCallOrientationEventListener.SCREEN_ORIENTATION_270) { width = (int) (mMinimumVideoDimension * aspectRatio); height = (int) mMinimumVideoDimension; } else { @@ -1374,5 +1380,6 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi void cleanupSurfaces(); ImageView getPreviewPhotoView(); void adjustPreviewLocation(boolean shiftUp, int offset); + void setPreviewRotation(int orientation); } } |