Commit b9004e2b authored by Peter Kotwicz's avatar Peter Kotwicz Committed by Commit Bot

[Android WebAPK] Delay locking screen orientation for new-style WebAPKs 1/2

Android throws an IllegalStateException when
Activity#setRequestedOrientation() while the activity is translucent.
This CL:
- Delays setting the screen orientation in WebappActivity till the
activity's translucency is removed
- Adds a method to SplashscreenObserver to notify that translucency was
removed.

NOPRESUBMIT=true
BUG=957835

Change-Id: I5971ec6b97f6ad50f71dd6e87f3fd19ecb7681db
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1589105
Commit-Queue: Peter Kotwicz <pkotwicz@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/heads/master@{#659046}
parent 18d556b8
...@@ -1244,7 +1244,7 @@ public class VrShellDelegate ...@@ -1244,7 +1244,7 @@ public class VrShellDelegate
if (mActivity.getCompositorViewHolder() != null) { if (mActivity.getCompositorViewHolder() != null) {
mActivity.getCompositorViewHolder().onEnterVr(); mActivity.getCompositorViewHolder().onEnterVr();
} }
ScreenOrientationProvider.setOrientationDelegate(this); ScreenOrientationProvider.getInstance().setOrientationDelegate(this);
// Hide system UI. // Hide system UI.
VrModuleProvider.getDelegate().setSystemUiVisibilityForVr(mActivity); VrModuleProvider.getDelegate().setSystemUiVisibilityForVr(mActivity);
...@@ -1263,7 +1263,7 @@ public class VrShellDelegate ...@@ -1263,7 +1263,7 @@ public class VrShellDelegate
@TargetApi(Build.VERSION_CODES.KITKAT) @TargetApi(Build.VERSION_CODES.KITKAT)
private void restoreWindowMode() { private void restoreWindowMode() {
ScreenOrientationProvider.setOrientationDelegate(null); ScreenOrientationProvider.getInstance().setOrientationDelegate(null);
mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Restore orientation. // Restore orientation.
......
...@@ -17,6 +17,9 @@ public class WebApkSplashscreenMetrics implements SplashscreenObserver { ...@@ -17,6 +17,9 @@ public class WebApkSplashscreenMetrics implements SplashscreenObserver {
mShellApkLaunchTimeMs = shellApkLaunchTimeMs; mShellApkLaunchTimeMs = shellApkLaunchTimeMs;
} }
@Override
public void onTranslucencyRemoved() {}
@Override @Override
public void onSplashscreenHidden(long startTimestamp, long endTimestamp) { public void onSplashscreenHidden(long startTimestamp, long endTimestamp) {
if (mShellApkLaunchTimeMs == -1) return; if (mShellApkLaunchTimeMs == -1) return;
......
...@@ -126,7 +126,7 @@ public class ArImmersiveOverlay implements SurfaceHolder.Callback2, ...@@ -126,7 +126,7 @@ public class ArImmersiveOverlay implements SurfaceHolder.Callback2,
} }
// Save current orientation mode, and then lock current orientation. // Save current orientation mode, and then lock current orientation.
ScreenOrientationProvider.setOrientationDelegate(this); ScreenOrientationProvider.getInstance().setOrientationDelegate(this);
if (mRestoreOrientation == null) { if (mRestoreOrientation == null) {
mRestoreOrientation = mActivity.getRequestedOrientation(); mRestoreOrientation = mActivity.getRequestedOrientation();
} }
...@@ -160,7 +160,7 @@ public class ArImmersiveOverlay implements SurfaceHolder.Callback2, ...@@ -160,7 +160,7 @@ public class ArImmersiveOverlay implements SurfaceHolder.Callback2,
mCleanupInProgress = true; mCleanupInProgress = true;
// Restore orientation. // Restore orientation.
ScreenOrientationProvider.setOrientationDelegate(null); ScreenOrientationProvider.getInstance().setOrientationDelegate(null);
if (mRestoreOrientation != null) mActivity.setRequestedOrientation(mRestoreOrientation); if (mRestoreOrientation != null) mActivity.setRequestedOrientation(mRestoreOrientation);
mRestoreOrientation = null; mRestoreOrientation = null;
......
...@@ -8,6 +8,9 @@ package org.chromium.chrome.browser.webapps; ...@@ -8,6 +8,9 @@ package org.chromium.chrome.browser.webapps;
* Observer interface for WebApp activity splashscreen. * Observer interface for WebApp activity splashscreen.
*/ */
public interface SplashscreenObserver { public interface SplashscreenObserver {
/** Called when the activity's translucency is removed. */
void onTranslucencyRemoved();
/** /**
* Called when the splash screen is hidden. * Called when the splash screen is hidden.
* @param startTimestamp Time that the splash screen was shown. * @param startTimestamp Time that the splash screen was shown.
......
...@@ -294,9 +294,6 @@ public class WebappActivity extends SingleTabActivity { ...@@ -294,9 +294,6 @@ public class WebappActivity extends SingleTabActivity {
StrictMode.setThreadPolicy(oldPolicy); StrictMode.setThreadPolicy(oldPolicy);
} }
ScreenOrientationProvider.lockOrientation(
getWindowAndroid(), (byte) mWebappInfo.orientation());
// When turning on TalkBack on Android, hitting app switcher to bring a WebappActivity to // When turning on TalkBack on Android, hitting app switcher to bring a WebappActivity to
// front will speak "Web App", which is the label of WebappActivity. Therefore, we set title // front will speak "Web App", which is the label of WebappActivity. Therefore, we set title
// of the WebappActivity explicitly to make it speak the short name of the Web App. // of the WebappActivity explicitly to make it speak the short name of the Web App.
...@@ -304,6 +301,8 @@ public class WebappActivity extends SingleTabActivity { ...@@ -304,6 +301,8 @@ public class WebappActivity extends SingleTabActivity {
super.performPreInflationStartup(); super.performPreInflationStartup();
applyScreenOrientation();
if (mWebappInfo.displayMode() == WebDisplayMode.FULLSCREEN) { if (mWebappInfo.displayMode() == WebDisplayMode.FULLSCREEN) {
enterImmersiveMode(); enterImmersiveMode();
} }
...@@ -889,6 +888,32 @@ public class WebappActivity extends SingleTabActivity { ...@@ -889,6 +888,32 @@ public class WebappActivity extends SingleTabActivity {
mSplashController.setDelegate(delegate); mSplashController.setDelegate(delegate);
} }
/** Sets the screen orientation. */
private void applyScreenOrientation() {
if (mWebappInfo.isSplashProvidedByWebApk()) {
// When the splash screen is provided by the WebAPK, the activity is initially
// translucent. Setting the screen orientation while the activity is translucent
// throws an exception. Delay setting it.
ScreenOrientationProvider.getInstance().delayOrientationRequests(getWindowAndroid());
addSplashscreenObserver(new SplashscreenObserver() {
@Override
public void onTranslucencyRemoved() {
ScreenOrientationProvider.getInstance().runDelayedOrientationRequests(
getWindowAndroid());
}
@Override
public void onSplashscreenHidden(long startTimestamp, long endTimestamp) {}
});
// Fall through and queue up request for the default screen orientation because the web
// page might change it via JavaScript.
}
ScreenOrientationProvider.getInstance().lockOrientation(
getWindowAndroid(), (byte) mWebappInfo.orientation());
}
/** /**
* Register an observer to the splashscreen hidden/visible events for this activity. * Register an observer to the splashscreen hidden/visible events for this activity.
*/ */
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "content/browser/screen_orientation/screen_orientation_delegate_android.h" #include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
#include "base/android/scoped_java_ref.h"
#include "content/browser/screen_orientation/screen_orientation_provider.h" #include "content/browser/screen_orientation/screen_orientation_provider.h"
#include "jni/ScreenOrientationProviderImpl_jni.h" #include "jni/ScreenOrientationProviderImpl_jni.h"
#include "ui/android/window_android.h" #include "ui/android/window_android.h"
...@@ -27,25 +28,33 @@ bool ScreenOrientationDelegateAndroid::FullScreenRequired( ...@@ -27,25 +28,33 @@ bool ScreenOrientationDelegateAndroid::FullScreenRequired(
void ScreenOrientationDelegateAndroid::Lock( void ScreenOrientationDelegateAndroid::Lock(
WebContents* web_contents, WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) { blink::WebScreenOrientationLockType lock_orientation) {
base::android::ScopedJavaLocalRef<jobject> java_instance =
Java_ScreenOrientationProviderImpl_getInstance(
base::android::AttachCurrentThread());
gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow(); gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow();
Java_ScreenOrientationProviderImpl_lockOrientation( Java_ScreenOrientationProviderImpl_lockOrientation(
base::android::AttachCurrentThread(), base::android::AttachCurrentThread(), java_instance,
window ? window->GetJavaObject() : nullptr, window ? window->GetJavaObject() : nullptr, lock_orientation);
lock_orientation);
} }
bool ScreenOrientationDelegateAndroid::ScreenOrientationProviderSupported() { bool ScreenOrientationDelegateAndroid::ScreenOrientationProviderSupported() {
// TODO(MLamouri): Consider moving isOrientationLockEnabled to a separate // TODO(MLamouri): Consider moving isOrientationLockEnabled to a separate
// function, so reported error messages can differentiate between the device // function, so reported error messages can differentiate between the device
// never supporting orientation or currently not support orientation. // never supporting orientation or currently not support orientation.
base::android::ScopedJavaLocalRef<jobject> java_instance =
Java_ScreenOrientationProviderImpl_getInstance(
base::android::AttachCurrentThread());
return Java_ScreenOrientationProviderImpl_isOrientationLockEnabled( return Java_ScreenOrientationProviderImpl_isOrientationLockEnabled(
base::android::AttachCurrentThread()); base::android::AttachCurrentThread(), java_instance);
} }
void ScreenOrientationDelegateAndroid::Unlock(WebContents* web_contents) { void ScreenOrientationDelegateAndroid::Unlock(WebContents* web_contents) {
base::android::ScopedJavaLocalRef<jobject> java_instance =
Java_ScreenOrientationProviderImpl_getInstance(
base::android::AttachCurrentThread());
gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow(); gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow();
Java_ScreenOrientationProviderImpl_unlockOrientation( Java_ScreenOrientationProviderImpl_unlockOrientation(
base::android::AttachCurrentThread(), base::android::AttachCurrentThread(), java_instance,
window ? window->GetJavaObject() : nullptr); window ? window->GetJavaObject() : nullptr);
} }
......
...@@ -564,6 +564,7 @@ junit_binary("content_junit_tests") { ...@@ -564,6 +564,7 @@ junit_binary("content_junit_tests") {
java_files = [ java_files = [
"junit/src/org/chromium/content/browser/BindingManagerTest.java", "junit/src/org/chromium/content/browser/BindingManagerTest.java",
"junit/src/org/chromium/content/browser/ChildProcessRankingTest.java", "junit/src/org/chromium/content/browser/ChildProcessRankingTest.java",
"junit/src/org/chromium/content/browser/ScreenOrientationProviderImplTest.java",
"junit/src/org/chromium/content/browser/UiThreadTaskTraitsImplTest.java", "junit/src/org/chromium/content/browser/UiThreadTaskTraitsImplTest.java",
"junit/src/org/chromium/content/browser/accessibility/BrowserAccessibilityStateTest.java", "junit/src/org/chromium/content/browser/accessibility/BrowserAccessibilityStateTest.java",
"junit/src/org/chromium/content/browser/SpareChildConnectionTest.java", "junit/src/org/chromium/content/browser/SpareChildConnectionTest.java",
......
...@@ -9,24 +9,53 @@ import android.content.Context; ...@@ -9,24 +9,53 @@ import android.content.Context;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Pair;
import android.view.Surface; import android.view.Surface;
import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.ApplicationStatus.ActivityStateListener;
import org.chromium.base.Log; import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.content_public.browser.ScreenOrientationDelegate; import org.chromium.content_public.browser.ScreenOrientationDelegate;
import org.chromium.content_public.browser.ScreenOrientationProvider;
import org.chromium.content_public.common.ScreenOrientationConstants; import org.chromium.content_public.common.ScreenOrientationConstants;
import org.chromium.content_public.common.ScreenOrientationValues; import org.chromium.content_public.common.ScreenOrientationValues;
import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.display.DisplayAndroid; import org.chromium.ui.display.DisplayAndroid;
import java.util.Map;
import java.util.WeakHashMap;
/** /**
* This is the implementation of the C++ counterpart ScreenOrientationProvider. * This is the implementation of the C++ counterpart ScreenOrientationProvider.
*/ */
@JNINamespace("content") @JNINamespace("content")
public class ScreenOrientationProviderImpl { public class ScreenOrientationProviderImpl
implements ActivityStateListener, ScreenOrientationProvider {
private static class Holder {
private static ScreenOrientationProviderImpl sInstance =
new ScreenOrientationProviderImpl();
}
private static final String TAG = "cr.ScreenOrientation"; private static final String TAG = "cr.ScreenOrientation";
private static ScreenOrientationDelegate sDelegate;
private ScreenOrientationDelegate mDelegate;
/**
* The keys of the map are the activities for which screen orientation requests are
* delayed.
* The values of the map are the most recent screen orientation request for each activity.
* The map will contain an entry with a null value if screen orientation requests are delayed
* for an activity but no screen orientation requests have been made for the activity.
*/
private Map<Activity, Pair<Boolean, Integer>> mDelayedRequests = new WeakHashMap<>();
@CalledByNative
public static ScreenOrientationProviderImpl getInstance() {
return Holder.sInstance;
}
private static int getOrientationFromWebScreenOrientations(byte orientation, private static int getOrientationFromWebScreenOrientations(byte orientation,
@Nullable WindowAndroid window, Context context) { @Nullable WindowAndroid window, Context context) {
...@@ -70,10 +99,16 @@ public class ScreenOrientationProviderImpl { ...@@ -70,10 +99,16 @@ public class ScreenOrientationProviderImpl {
} }
} }
@CalledByNative @Override
public static void lockOrientation(@Nullable WindowAndroid window, byte webScreenOrientation) { public void onActivityStateChange(Activity activity, @ActivityState int newState) {
if (sDelegate != null && !sDelegate.canLockOrientation()) return; if (newState == ActivityState.DESTROYED) {
mDelayedRequests.remove(activity);
}
}
@CalledByNative
@Override
public void lockOrientation(@Nullable WindowAndroid window, byte webScreenOrientation) {
// WindowAndroid may be null if the tab is being reparented. // WindowAndroid may be null if the tab is being reparented.
if (window == null) return; if (window == null) return;
Activity activity = window.getActivity().get(); Activity activity = window.getActivity().get();
...@@ -89,11 +124,12 @@ public class ScreenOrientationProviderImpl { ...@@ -89,11 +124,12 @@ public class ScreenOrientationProviderImpl {
return; return;
} }
activity.setRequestedOrientation(orientation); setMaybeDelayedRequestedOrientation(activity, true /* lock */, orientation);
} }
@CalledByNative @CalledByNative
public static void unlockOrientation(@Nullable WindowAndroid window) { @Override
public void unlockOrientation(@Nullable WindowAndroid window) {
// WindowAndroid may be null if the tab is being reparented. // WindowAndroid may be null if the tab is being reparented.
if (window == null) return; if (window == null) return;
Activity activity = window.getActivity().get(); Activity activity = window.getActivity().get();
...@@ -122,20 +158,71 @@ public class ScreenOrientationProviderImpl { ...@@ -122,20 +158,71 @@ public class ScreenOrientationProviderImpl {
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
// Do nothing, defaultOrientation should be SCREEN_ORIENTATION_UNSPECIFIED. // Do nothing, defaultOrientation should be SCREEN_ORIENTATION_UNSPECIFIED.
} finally { } finally {
if (sDelegate == null || sDelegate.canUnlockOrientation(activity, defaultOrientation)) { setMaybeDelayedRequestedOrientation(activity, false /* lock */, defaultOrientation);
activity.setRequestedOrientation(defaultOrientation); }
} }
@Override
public void delayOrientationRequests(WindowAndroid window) {
Activity activity = window.getActivity().get();
if ((activity == null || areRequestsDelayedForActivity(activity))) {
return;
}
mDelayedRequests.put(activity, null);
ApplicationStatus.registerStateListenerForActivity(this, activity);
}
@Override
public void runDelayedOrientationRequests(WindowAndroid window) {
Activity activity = window.getActivity().get();
if ((activity == null || !areRequestsDelayedForActivity(activity))) {
return;
}
Pair<Boolean, Integer> delayedRequest = mDelayedRequests.remove(activity);
if (delayedRequest != null) {
setRequestedOrientationNow(activity, delayedRequest.first, delayedRequest.second);
}
if (mDelayedRequests.isEmpty()) {
ApplicationStatus.unregisterActivityStateListener(this);
} }
} }
@CalledByNative @CalledByNative
private static boolean isOrientationLockEnabled() { public boolean isOrientationLockEnabled() {
return sDelegate == null || sDelegate.canLockOrientation(); return mDelegate == null || mDelegate.canLockOrientation();
} }
public static void setOrientationDelegate(ScreenOrientationDelegate delegate) { @Override
sDelegate = delegate; public void setOrientationDelegate(ScreenOrientationDelegate delegate) {
mDelegate = delegate;
} }
private ScreenOrientationProviderImpl() {} /** Returns whether screen orientation requests are delayed for the passed-in activity. */
private boolean areRequestsDelayedForActivity(Activity activity) {
return mDelayedRequests.containsKey(activity);
}
/** Sets the requested orientation for the activity delaying the request if needed. */
private void setMaybeDelayedRequestedOrientation(
Activity activity, boolean lock, int orientation) {
if (areRequestsDelayedForActivity(activity)) {
mDelayedRequests.put(activity, Pair.create(lock, orientation));
} else {
setRequestedOrientationNow(activity, lock, orientation);
}
}
/** Sets the requested orientation for the activity. */
private void setRequestedOrientationNow(Activity activity, boolean lock, int orientation) {
if (mDelegate != null) {
if ((lock && !mDelegate.canLockOrientation())
|| (!lock && !mDelegate.canUnlockOrientation(activity, orientation))) {
return;
}
}
activity.setRequestedOrientation(orientation);
}
} }
...@@ -12,23 +12,25 @@ import org.chromium.ui.base.WindowAndroid; ...@@ -12,23 +12,25 @@ import org.chromium.ui.base.WindowAndroid;
/** /**
* Interface providing the access to C++ ScreenOrientationProvider. * Interface providing the access to C++ ScreenOrientationProvider.
*/ */
public final class ScreenOrientationProvider { public interface ScreenOrientationProvider {
private ScreenOrientationProvider() {} static ScreenOrientationProvider getInstance() {
return ScreenOrientationProviderImpl.getInstance();
}
/** /**
* Locks screen rotation to a given orientation. * Locks screen rotation to a given orientation.
* @param window Window to lock rotation on. * @param window Window to lock rotation on.
* @param webScreenOrientation Screen orientation. * @param webScreenOrientation Screen orientation.
*/ */
public static void lockOrientation(@Nullable WindowAndroid window, byte webScreenOrientation) { void lockOrientation(@Nullable WindowAndroid window, byte webScreenOrientation);
ScreenOrientationProviderImpl.lockOrientation(window, webScreenOrientation);
}
public static void unlockOrientation(@Nullable WindowAndroid window) { void unlockOrientation(@Nullable WindowAndroid window);
ScreenOrientationProviderImpl.unlockOrientation(window);
}
public static void setOrientationDelegate(ScreenOrientationDelegate delegate) { /** Delays screen orientation requests for the given window. */
ScreenOrientationProviderImpl.setOrientationDelegate(delegate); void delayOrientationRequests(WindowAndroid window);
}
/** Runs delayed screen orientation requests for the given window. */
void runDelayedOrientationRequests(WindowAndroid window);
void setOrientationDelegate(ScreenOrientationDelegate delegate);
} }
...@@ -231,7 +231,7 @@ public class ScreenOrientationListenerTest { ...@@ -231,7 +231,7 @@ public class ScreenOrientationListenerTest {
int callCount = mCallbackHelper.getCallCount(); int callCount = mCallbackHelper.getCallCount();
TestThreadUtils.runOnUiThreadBlocking(() -> { TestThreadUtils.runOnUiThreadBlocking(() -> {
ScreenOrientationProvider.lockOrientation( ScreenOrientationProvider.getInstance().lockOrientation(
mActivityTestRule.getWebContents().getTopLevelNativeWindow(), mActivityTestRule.getWebContents().getTopLevelNativeWindow(),
(byte) orientationValue); (byte) orientationValue);
}); });
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.content.browser;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.content_public.common.ScreenOrientationValues;
import org.chromium.ui.base.ActivityWindowAndroid;
import java.lang.ref.WeakReference;
/** Unit tests for {@link ScreenOrientationProviderImpl } */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public final class ScreenOrientationProviderImplTest {
/**
* Tests that when screen orientation requests are delayed that newer requests overwrite older
* requests for a given activity.
*/
@Test
public void testDelayRequests() {
final Activity activity = Robolectric.buildActivity(Activity.class).create().get();
ActivityWindowAndroid window = buildMockWindowForActivity(activity);
// Last orientation lock request should take precedence.
ScreenOrientationProviderImpl instance = ScreenOrientationProviderImpl.getInstance();
instance.delayOrientationRequests(window);
instance.lockOrientation(window, (byte) ScreenOrientationValues.PORTRAIT_PRIMARY);
instance.lockOrientation(window, (byte) ScreenOrientationValues.LANDSCAPE_PRIMARY);
Assert.assertEquals(
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, activity.getRequestedOrientation());
instance.runDelayedOrientationRequests(window);
Assert.assertEquals(
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, activity.getRequestedOrientation());
// Lock then unlock screen orientation while requests are delayed.
instance.delayOrientationRequests(window);
instance.lockOrientation(window, (byte) ScreenOrientationValues.PORTRAIT_PRIMARY);
instance.unlockOrientation(window);
Assert.assertEquals(
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, activity.getRequestedOrientation());
instance.runDelayedOrientationRequests(window);
Assert.assertEquals(
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, activity.getRequestedOrientation());
}
/**
* Tests that whether screen orientation requests are delayed can be toggled for each activity
* independently.
*/
@Test
public void testDelayRequestsAppliesOnlyToActivity() {
final Activity activity1 = Robolectric.buildActivity(Activity.class).create().get();
ActivityWindowAndroid window1 = buildMockWindowForActivity(activity1);
final Activity activity2 = Robolectric.buildActivity(Activity.class).create().get();
ActivityWindowAndroid window2 = buildMockWindowForActivity(activity2);
ScreenOrientationProviderImpl instance = ScreenOrientationProviderImpl.getInstance();
instance.delayOrientationRequests(window1);
instance.lockOrientation(window1, (byte) ScreenOrientationValues.PORTRAIT_PRIMARY);
instance.lockOrientation(window2, (byte) ScreenOrientationValues.LANDSCAPE_PRIMARY);
Assert.assertEquals(
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, activity1.getRequestedOrientation());
Assert.assertEquals(
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, activity2.getRequestedOrientation());
instance.runDelayedOrientationRequests(window1);
Assert.assertEquals(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, activity1.getRequestedOrientation());
Assert.assertEquals(
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, activity2.getRequestedOrientation());
}
/**
* Tests that removing the screen orientation request delay is a no-op if there are no pending
* screen orientation requests.
*/
@Test
public void testRemoveDelayNoPendingRequests() {
final Activity activity = Robolectric.buildActivity(Activity.class).create().get();
ActivityWindowAndroid window = buildMockWindowForActivity(activity);
ScreenOrientationProviderImpl instance = ScreenOrientationProviderImpl.getInstance();
instance.delayOrientationRequests(window);
instance.runDelayedOrientationRequests(window);
Assert.assertEquals(
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, activity.getRequestedOrientation());
}
private ActivityWindowAndroid buildMockWindowForActivity(Activity activity) {
ActivityWindowAndroid window = Mockito.mock(ActivityWindowAndroid.class);
Mockito.when(window.getActivity()).thenReturn(new WeakReference<>(activity));
return window;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment