Backed out 6 changesets (bug 1476106) for failure at bf1f28e2b46d for failure at testing/marionette/harness/marionette_harness/tests/unit/test_screen_orientation.py
authordvarga <dvarga@mozilla.com>
Wed, 08 Aug 2018 22:39:03 +0300
changeset 430585 b7cd9638d4a4c7d2f9df0cf7dbcb2a85bbafa7b7
parent 430584 bf959a3fdcfc65fc282cac4b8375147fce6c9a33
child 430586 9d267b4bd26889fe936dff2c7b05d3b9415ccb44
push id67529
push userdvarga@mozilla.com
push dateWed, 08 Aug 2018 19:42:20 +0000
treeherderautoland@b7cd9638d4a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1476106
milestone63.0a1
backs outbf1f28e2b46d1580b889c90511d42a887ead5f2c
ab38b11f85dd33bf8401451cafddd70a638af3b7
b1a3ff0760bfd2d26d3f22e58139ca28e94f8d1e
deb22f602d59ebe947e568749d4075ed2d563640
3b1084efc943a6819dfb067437918010d17d4a25
6d885f08136bb257b5a3a1e4758db3a2198ce351
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 6 changesets (bug 1476106) for failure at bf1f28e2b46d for failure at testing/marionette/harness/marionette_harness/tests/unit/test_screen_orientation.py Backed out changeset bf1f28e2b46d (bug 1476106) Backed out changeset ab38b11f85dd (bug 1476106) Backed out changeset b1a3ff0760bf (bug 1476106) Backed out changeset deb22f602d59 (bug 1476106) Backed out changeset 3b1084efc943 (bug 1476106) Backed out changeset 6d885f08136b (bug 1476106)
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
mobile/android/base/java/org/mozilla/gecko/prompts/PromptService.java
mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/ScreenManagerHelper.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
widget/android/ScreenHelperAndroid.cpp
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -2,17 +2,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.AppConstants.Versions;
 import org.mozilla.gecko.GeckoProfileDirectories.NoMozillaDirectoryException;
-import org.mozilla.gecko.GeckoScreenOrientation.ScreenOrientation;
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.annotation.WrapForJNI;
 import org.mozilla.gecko.health.HealthRecorder;
 import org.mozilla.gecko.health.SessionInformation;
 import org.mozilla.gecko.health.StubbedHealthRecorder;
 import org.mozilla.gecko.home.HomeConfig.PanelType;
 import org.mozilla.gecko.menu.GeckoMenu;
 import org.mozilla.gecko.menu.GeckoMenuInflater;
@@ -36,16 +35,17 @@ import org.mozilla.gecko.util.EventCallb
 import org.mozilla.gecko.util.FileUtils;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.PrefUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.util.ViewUtil;
 import org.mozilla.gecko.widget.ActionModePresenter;
 import org.mozilla.gecko.widget.AnchoredPopup;
+import org.mozilla.geckoview.GeckoRuntime;
 import org.mozilla.geckoview.GeckoSession;
 import org.mozilla.geckoview.GeckoSessionSettings;
 import org.mozilla.geckoview.GeckoView;
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.annotation.TargetApi;
 import android.app.Activity;
@@ -108,17 +108,16 @@ import static org.mozilla.gecko.Tabs.INV
 import static org.mozilla.gecko.mma.MmaDelegate.DOWNLOAD_MEDIA_SAVED_IMAGE;
 import static org.mozilla.gecko.mma.MmaDelegate.READER_AVAILABLE;
 
 public abstract class GeckoApp extends GeckoActivity
                                implements AnchoredPopup.OnVisibilityChangeListener,
                                           BundleEventListener,
                                           GeckoMenu.Callback,
                                           GeckoMenu.MenuPresenter,
-                                          GeckoScreenOrientation.OrientationChangeListener,
                                           GeckoSession.ContentDelegate,
                                           ScreenOrientationDelegate,
                                           Tabs.OnTabsChangedListener,
                                           ViewTreeObserver.OnGlobalLayoutListener {
 
     private static final String LOGTAG = "GeckoApp";
     private static final long ONE_DAY_MS = TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS);
 
@@ -978,17 +977,16 @@ public abstract class GeckoApp extends G
         earlyStartJavaSampler(intent);
 
         // Workaround for <http://code.google.com/p/android/issues/detail?id=20915>.
         try {
             Class.forName("android.os.AsyncTask");
         } catch (ClassNotFoundException e) { }
 
         GeckoAppShell.setScreenOrientationDelegate(this);
-        GeckoScreenOrientation.getInstance().addListener(this);
 
         // Tell Stumbler to register a local broadcast listener to listen for preference intents.
         // We do this via intents since we can't easily access Stumbler directly,
         // as it might be compiled outside of Fennec.
         final Intent stumblerIntent = new Intent(getApplicationContext(), SafeReceiver.class);
         stumblerIntent.setAction(INTENT_REGISTER_STUMBLER_LISTENER);
         getApplicationContext().sendBroadcast(stumblerIntent);
 
@@ -1062,16 +1060,18 @@ public abstract class GeckoApp extends G
             }
         } else if (savedInstanceState != null) {
             // Bug 896992 - This intent has already been handled; reset the intent.
             setIntent(new Intent(Intent.ACTION_MAIN));
         }
 
         super.onCreate(savedInstanceState);
 
+        GeckoScreenOrientation.getInstance().update(getResources().getConfiguration().orientation);
+
         setContentView(getLayout());
 
         // Set up Gecko layout.
         mRootLayout = (RelativeLayout) findViewById(R.id.root_layout);
         mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout);
         mMainLayout = (RelativeLayout) findViewById(R.id.main_layout);
         mLayerView = (GeckoView) findViewById(R.id.layer_view);
 
@@ -1925,16 +1925,21 @@ public abstract class GeckoApp extends G
         if (mIsAbortingAppLaunch) {
             return;
         }
 
         foregrounded = true;
 
         GeckoAppShell.setScreenOrientationDelegate(this);
 
+        int newOrientation = getResources().getConfiguration().orientation;
+        if (GeckoScreenOrientation.getInstance().update(newOrientation)) {
+            refreshChrome();
+        }
+
         // We use two times: a pseudo-unique wall-clock time to identify the
         // current session across power cycles, and the elapsed realtime to
         // track the duration of the session.
         final long now = System.currentTimeMillis();
         final long realTime = android.os.SystemClock.elapsedRealtime();
 
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
@@ -2124,18 +2129,16 @@ public abstract class GeckoApp extends G
             });
         }
 
         super.onDestroy();
 
         Tabs.unregisterOnTabsChangedListener(this);
         Tabs.getInstance().detachFromContext();
 
-        GeckoScreenOrientation.getInstance().removeListener(this);
-
         if (mShutdownOnDestroy) {
             GeckoApplication.shutdown(!mRestartOnShutdown ? null : new Intent(
                     Intent.ACTION_MAIN, /* uri */ null, getApplicationContext(), getClass()));
         }
     }
 
     public void showSDKVersionError() {
         final String message = getString(R.string.unsupported_sdk_version,
@@ -2170,16 +2173,29 @@ public abstract class GeckoApp extends G
         Log.d(LOGTAG, "onConfigurationChanged: " + newConfig.locale);
 
         final LocaleManager localeManager = BrowserLocaleManager.getInstance();
         final Locale changed = localeManager.onSystemConfigurationChanged(this, getResources(), newConfig, mLastLocale);
         if (changed != null) {
             onLocaleChanged(Locales.getLanguageTag(changed));
         }
 
+        // onConfigurationChanged is not called for 180 degree orientation changes,
+        // we will miss such rotations and the screen orientation will not be
+        // updated.
+        if (GeckoScreenOrientation.getInstance().update(newConfig.orientation)) {
+            if (mFormAssistPopup != null)
+                mFormAssistPopup.hide();
+            refreshChrome();
+        }
+
+        if (mPromptService != null) {
+            mPromptService.changePromptOrientation(newConfig.orientation);
+        }
+
         super.onConfigurationChanged(newConfig);
     }
 
     public String getContentProcessName() {
         return AppConstants.MOZ_CHILD_PROCESS_NAME;
     }
 
     public void addEnvToIntent(Intent intent) {
@@ -2507,17 +2523,9 @@ public abstract class GeckoApp extends G
         // We want to support the Screen Orientation API, and it always makes sense to lock the
         // orientation of a browser Activity, so we support locking.
         if (getRequestedOrientation() == requestedActivityInfoOrientation) {
             return false;
         }
         setRequestedOrientation(requestedActivityInfoOrientation);
         return true;
     }
-
-    @Override
-    public void onScreenOrientationChanged(ScreenOrientation newOrientation) {
-        if (mFormAssistPopup != null) {
-            mFormAssistPopup.hide();
-        }
-        refreshChrome();
-    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.customtabs;
 
 import android.app.PendingIntent;
 import android.content.ActivityNotFoundException;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.Browser;
 import android.support.annotation.ColorInt;
 import android.support.annotation.NonNull;
@@ -33,16 +34,18 @@ import android.widget.ProgressBar;
 
 import org.mozilla.gecko.ActivityHandlerHelper;
 import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.Clipboard;
 import org.mozilla.gecko.DoorHangerPopup;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.FormAssistPopup;
 import org.mozilla.gecko.GeckoApplication;
+import org.mozilla.gecko.GeckoSharedPrefs;
+import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.SnackbarBuilder;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.menu.GeckoMenu;
 import org.mozilla.gecko.menu.GeckoMenuInflater;
 import org.mozilla.gecko.mozglue.SafeIntent;
 import org.mozilla.gecko.permissions.Permissions;
@@ -51,17 +54,19 @@ import org.mozilla.gecko.text.TextSelect
 import org.mozilla.gecko.util.ActivityUtils;
 import org.mozilla.gecko.util.ColorUtil;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.IntentUtils;
 import org.mozilla.gecko.util.PackageUtil;
 import org.mozilla.gecko.webapps.WebApps;
 import org.mozilla.gecko.widget.ActionModePresenter;
 import org.mozilla.gecko.widget.GeckoPopupMenu;
+import org.mozilla.geckoview.GeckoResponse;
 import org.mozilla.geckoview.GeckoResult;
+import org.mozilla.geckoview.GeckoRuntime;
 import org.mozilla.geckoview.GeckoSession;
 import org.mozilla.geckoview.GeckoSessionSettings;
 import org.mozilla.geckoview.GeckoView;
 
 import java.util.List;
 
 public class CustomTabsActivity extends AppCompatActivity
                                 implements ActionModePresenter,
@@ -181,16 +186,25 @@ public class CustomTabsActivity extends 
     }
 
     @Override
     public void onRequestPermissionsResult(final int requestCode, final String[] permissions,
                                            final int[] grantResults) {
         Permissions.onRequestPermissionsResult(this, permissions, grantResults);
     }
 
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        if (mPromptService != null) {
+            mPromptService.changePromptOrientation(newConfig.orientation);
+        }
+    }
+
     private void sendTelemetry() {
         final SafeIntent startIntent = new SafeIntent(getIntent());
 
         Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT, "customtab");
         if (IntentUtil.hasToolbarColor(startIntent)) {
             Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT, "customtab-hasToolbarColor");
         }
         if (IntentUtil.hasActionButton(startIntent)) {
--- a/mobile/android/base/java/org/mozilla/gecko/prompts/PromptService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/prompts/PromptService.java
@@ -1,62 +1,58 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.prompts;
 
 import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.GeckoScreenOrientation;
-import org.mozilla.gecko.GeckoScreenOrientation.ScreenOrientation;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 
 import android.content.Context;
 
-public class PromptService implements BundleEventListener,
-                                      GeckoScreenOrientation.OrientationChangeListener {
+public class PromptService implements BundleEventListener {
     private static final String LOGTAG = "GeckoPromptService";
 
     private final Context context;
     private final EventDispatcher dispatcher;
     private Prompt currentPrompt;
+    private int currentOrientation;
 
     public PromptService(final Context context, final EventDispatcher dispatcher) {
         this.context = context;
-        GeckoScreenOrientation.getInstance().addListener(this);
+        this.currentOrientation = context.getResources().getConfiguration().orientation;
         this.dispatcher = dispatcher;
         this.dispatcher.registerUiThreadListener(this,
             "Prompt:Show",
             "Prompt:ShowTop");
     }
 
     public void destroy() {
         dispatcher.unregisterUiThreadListener(this,
             "Prompt:Show",
             "Prompt:ShowTop");
-        GeckoScreenOrientation.getInstance().removeListener(this);
     }
 
     // BundleEventListener implementation
     @Override
     public void handleMessage(final String event, final GeckoBundle message,
                               final EventCallback callback) {
         currentPrompt = new Prompt(context, new Prompt.PromptCallback() {
             @Override
             public void onPromptFinished(final GeckoBundle result) {
                 callback.sendSuccess(result);
                 currentPrompt = null;
             }
         });
         currentPrompt.show(message);
     }
 
-    // OrientationChangeListener implementation
-    @Override
-    public void onScreenOrientationChanged(ScreenOrientation newOrientation) {
-        if (currentPrompt != null) {
+    public void changePromptOrientation(int newOrientation) {
+        if (currentPrompt != null && currentOrientation != newOrientation) {
             currentPrompt.resetLayout();
         }
+        currentOrientation = newOrientation;
     }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.webapps;
 
 import android.annotation.TargetApi;
 import android.app.ActivityManager;
 import android.content.ActivityNotFoundException;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.support.customtabs.CustomTabsIntent;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.view.ActionMode;
 import android.util.Log;
@@ -23,25 +24,29 @@ import android.widget.Toast;
 
 import org.mozilla.gecko.ActivityHandlerHelper;
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.DoorHangerPopup;
 import org.mozilla.gecko.FormAssistPopup;
 import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoScreenOrientation;
+import org.mozilla.gecko.GeckoSharedPrefs;
+import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.customtabs.CustomTabsActivity;
 import org.mozilla.gecko.permissions.Permissions;
 import org.mozilla.gecko.prompts.PromptService;
 import org.mozilla.gecko.text.TextSelection;
 import org.mozilla.gecko.util.ActivityUtils;
 import org.mozilla.gecko.util.ColorUtil;
 import org.mozilla.gecko.widget.ActionModePresenter;
+import org.mozilla.geckoview.GeckoResponse;
 import org.mozilla.geckoview.GeckoResult;
+import org.mozilla.geckoview.GeckoRuntime;
 import org.mozilla.geckoview.GeckoSession;
 import org.mozilla.geckoview.GeckoSessionSettings;
 import org.mozilla.geckoview.GeckoView;
 
 public class WebAppActivity extends AppCompatActivity
                             implements ActionModePresenter,
                                        GeckoSession.ContentDelegate,
                                        GeckoSession.NavigationDelegate {
@@ -168,16 +173,25 @@ public class WebAppActivity extends AppC
             return;
         }
 
         updateFromManifest();
 
         mGeckoSession.loadUri(mManifest.getStartUri().toString());
     }
 
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        if (mPromptService != null) {
+            mPromptService.changePromptOrientation(newConfig.orientation);
+        }
+    }
+
     private void fallbackToFennec(String message) {
         if (message != null) {
             Toast.makeText(this, message, Toast.LENGTH_LONG).show();
         }
 
         try {
             Intent intent = new Intent(this, BrowserApp.class);
             intent.setAction(Intent.ACTION_VIEW);
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
@@ -23,37 +23,49 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.TreeMap;
 
 import org.mozilla.gecko.annotation.JNITarget;
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.annotation.WrapForJNI;
+import org.mozilla.gecko.permissions.Permissions;
+import org.mozilla.gecko.process.GeckoProcessManager;
+import org.mozilla.gecko.SysInfo;
 import org.mozilla.gecko.util.BitmapUtils;
 import org.mozilla.gecko.util.HardwareCodecCapabilityUtils;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.IOUtils;
 import org.mozilla.gecko.util.ProxySelector;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.geckoview.BuildConfig;
 
+import android.Manifest;
 import android.annotation.SuppressLint;
+import android.app.Activity;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.Signature;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.ImageFormat;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.SurfaceTexture;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.hardware.Camera;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.location.Criteria;
@@ -61,32 +73,43 @@ import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.LocaleList;
 import android.os.Looper;
+import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.StrictMode;
+import android.os.SystemClock;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.util.SimpleArrayMap;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.HapticFeedbackConstants;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.TextureView;
+import android.view.View;
 import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
 import android.webkit.MimeTypeMap;
+import android.widget.AbsoluteLayout;
 
 public class GeckoAppShell
 {
     private static final String LOGTAG = "GeckoAppShell";
 
     // We have static members only.
     private GeckoAppShell() { }
 
@@ -233,16 +256,18 @@ public class GeckoAppShell
 
     // helper methods
     @WrapForJNI
     /* package */ static native void reportJavaCrash(Throwable exc, String stackTrace);
 
     @WrapForJNI(dispatchTo = "gecko")
     public static native void notifyUriVisited(String uri);
 
+    private static Rect sScreenSize;
+
     @WrapForJNI(stubName = "NotifyObservers", dispatchTo = "gecko")
     private static native void nativeNotifyObservers(String topic, String data);
 
     @RobocopTarget
     public static void notifyObservers(final String topic, final String data) {
         notifyObservers(topic, data, GeckoThread.State.RUNNING);
     }
 
@@ -1832,22 +1857,29 @@ public class GeckoAppShell
             return 2;
         } else if (pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
             // 1 finger
             return 1;
         }
         return 0;
     }
 
+    public static synchronized void resetScreenSize() {
+        sScreenSize = null;
+    }
+
     @WrapForJNI(calledFrom = "gecko")
-    private static Rect getScreenSize() {
-        final WindowManager wm = (WindowManager)
-                getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
-        final Display disp = wm.getDefaultDisplay();
-        return new Rect(0, 0, disp.getWidth(), disp.getHeight());
+    private static synchronized Rect getScreenSize() {
+        if (sScreenSize == null) {
+            final WindowManager wm = (WindowManager)
+                    getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
+            final Display disp = wm.getDefaultDisplay();
+            sScreenSize = new Rect(0, 0, disp.getWidth(), disp.getHeight());
+        }
+        return sScreenSize;
     }
 
     @WrapForJNI(calledFrom = "any")
     public static int getAudioOutputFramesPerBuffer() {
         final int DEFAULT = 512;
 
         if (SysInfo.getVersion() < 17) {
             return DEFAULT;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java
@@ -9,17 +9,16 @@ import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.util.Log;
 import android.view.Surface;
 import android.view.WindowManager;
 
 import org.mozilla.gecko.annotation.WrapForJNI;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 /*
  * Updates, locks and unlocks the screen orientation.
  *
  * Note: Replaces the OnOrientationChangeListener to avoid redundant rotation
  * event handling.
@@ -60,48 +59,27 @@ public class GeckoScreenOrientation {
     private static GeckoScreenOrientation sInstance;
     // Default rotation, used when device rotation is unknown.
     private static final int DEFAULT_ROTATION = Surface.ROTATION_0;
     // Last updated screen orientation.
     private ScreenOrientation mScreenOrientation;
     // Whether the update should notify Gecko about screen orientation changes.
     private boolean mShouldNotify = true;
 
-    public interface OrientationChangeListener {
-        void onScreenOrientationChanged(ScreenOrientation newOrientation);
-    }
-
-    private final List<OrientationChangeListener> mListeners;
-
     public static GeckoScreenOrientation getInstance() {
         if (sInstance == null) {
             sInstance = new GeckoScreenOrientation();
         }
         return sInstance;
     }
 
     private GeckoScreenOrientation() {
-        mListeners = new ArrayList<>();
         update();
     }
 
-    /**
-     * Add a listener that will be notified when the screen orientation has changed.
-     */
-    public void addListener(OrientationChangeListener aListener) {
-        mListeners.add(aListener);
-    }
-
-    /**
-     * Remove a OrientationChangeListener again.
-     */
-    public void removeListener(OrientationChangeListener aListener) {
-        mListeners.remove(aListener);
-    }
-
     /*
      * Enable Gecko screen orientation events on update.
      */
     public void enableNotifications() {
         update();
         mShouldNotify = true;
     }
 
@@ -152,36 +130,33 @@ public class GeckoScreenOrientation {
      * @return Whether the screen orientation has changed.
      */
     public boolean update(ScreenOrientation aScreenOrientation) {
         if (mScreenOrientation == aScreenOrientation) {
             return false;
         }
         mScreenOrientation = aScreenOrientation;
         Log.d(LOGTAG, "updating to new orientation " + mScreenOrientation);
-        for (OrientationChangeListener listener : mListeners) {
-            listener.onScreenOrientationChanged(mScreenOrientation);
-        }
         if (mShouldNotify) {
             // Gecko expects a definite screen orientation, so we default to the
             // primary orientations.
             if (aScreenOrientation == ScreenOrientation.PORTRAIT) {
                 aScreenOrientation = ScreenOrientation.PORTRAIT_PRIMARY;
             } else if (aScreenOrientation == ScreenOrientation.LANDSCAPE) {
                 aScreenOrientation = ScreenOrientation.LANDSCAPE_PRIMARY;
             }
 
             if (GeckoThread.isRunning()) {
                 onOrientationChange(aScreenOrientation.value, getAngle());
             } else {
                 GeckoThread.queueNativeCall(GeckoScreenOrientation.class, "onOrientationChange",
                                             aScreenOrientation.value, getAngle());
             }
         }
-        ScreenManagerHelper.refreshScreenInfo();
+        GeckoAppShell.resetScreenSize();
         return true;
     }
 
     /*
      * @return The Android orientation (Configuration.orientation).
      */
     public int getAndroidOrientation() {
         return screenOrientationToAndroidOrientation(getScreenOrientation());
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/ScreenManagerHelper.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/ScreenManagerHelper.java
@@ -13,30 +13,16 @@ class ScreenManagerHelper {
     /**
      * The following display types use the same definition in nsIScreen.idl
      */
     final static int DISPLAY_PRIMARY  = 0; // primary screen
     final static int DISPLAY_EXTERNAL = 1; // wired displays, such as HDMI, DisplayPort, etc.
     final static int DISPLAY_VIRTUAL  = 2; // wireless displays, such as Chromecast, WiFi-Display, etc.
 
     /**
-     * Trigger a refresh of the cached screen information held by Gecko.
-     */
-    public static void refreshScreenInfo() {
-        // Screen data is initialised automatically on startup, so no need to queue the call if
-        // Gecko isn't running yet.
-        if (GeckoThread.isRunning()) {
-            nativeRefreshScreenInfo();
-        }
-    }
-
-    @WrapForJNI(stubName = "RefreshScreenInfo", dispatchTo = "gecko")
-    private native static void nativeRefreshScreenInfo();
-
-    /**
      * Add a new nsScreen when a new display in Android is available.
      *
      * @param displayType the display type of the nsScreen would be added
      * @param width       the width of the new nsScreen
      * @param height      the height of the new nsScreen
      * @param density     the density of the new nsScreen
      *
      * @return            return the ID of the added nsScreen
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
@@ -1,26 +1,27 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * vim: ts=4 sw=4 expandtab:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.geckoview;
 
+import android.content.SharedPreferences;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.content.Context;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.util.Log;
 
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoScreenOrientation;
+import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.GeckoThread;
 import org.mozilla.gecko.PrefsHelper;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import java.io.File;
@@ -252,32 +253,16 @@ public final class GeckoRuntime implemen
      * internal data.
      *
      * @return Profile directory
      */
     @NonNull public File getProfileDir() {
         return GeckoThread.getActiveProfile().getDir();
     }
 
-    /**
-     * Notify Gecko that the screen orientation has changed.
-     */
-    public void orientationChanged() {
-        GeckoScreenOrientation.getInstance().update();
-    }
-
-    /**
-     * Notify Gecko that the screen orientation has changed.
-     * @param newOrientation The new screen orientation, as retrieved e.g. from the current
-     *                       {@link android.content.res.Configuration}.
-     */
-    public void orientationChanged(int newOrientation) {
-        GeckoScreenOrientation.getInstance().update(newOrientation);
-    }
-
     @Override // Parcelable
     public int describeContents() {
         return 0;
     }
 
     @Override // Parcelable
     public void writeToParcel(Parcel out, int flags) {
         out.writeParcelable(mSettings, flags);
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
@@ -11,30 +11,30 @@ import org.mozilla.gecko.EventDispatcher
 import org.mozilla.gecko.gfx.DynamicToolbarAnimator;
 import org.mozilla.gecko.gfx.PanZoomController;
 import org.mozilla.gecko.gfx.GeckoDisplay;
 import org.mozilla.gecko.InputMethods;
 import org.mozilla.gecko.util.ActivityUtils;
 
 import android.app.Activity;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.support.annotation.Nullable;
 import android.support.annotation.NonNull;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
+import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
@@ -337,17 +337,16 @@ public class GeckoView extends FrameLayo
     public void onAttachedToWindow() {
         if (mSession == null) {
             setSession(new GeckoSession(), GeckoRuntime.getDefault(getContext()));
         }
 
         if (!mSession.isOpen()) {
             mSession.open(mRuntime);
         }
-        mRuntime.orientationChanged();
 
         super.onAttachedToWindow();
     }
 
     @Override
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
@@ -357,28 +356,16 @@ public class GeckoView extends FrameLayo
 
         // If we saved state earlier, we don't want to close the window.
         if (!mStateSaved && mSession.isOpen()) {
             mSession.close();
         }
     }
 
     @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-
-        if (mRuntime != null) {
-            // onConfigurationChanged is not called for 180 degree orientation changes,
-            // we will miss such rotations and the screen orientation will not be
-            // updated.
-            mRuntime.orientationChanged(newConfig.orientation);
-        }
-    }
-
-    @Override
     public boolean gatherTransparentRegion(final Region region) {
         // For detecting changes in SurfaceView layout, we take a shortcut here and
         // override gatherTransparentRegion, instead of registering a layout listener,
         // which is more expensive.
         if (mSurfaceView != null) {
             mDisplay.onGlobalLayout();
         }
         return super.gatherTransparentRegion(region);
@@ -401,17 +388,17 @@ public class GeckoView extends FrameLayo
 
         final SavedState ss = (SavedState) state;
         super.onRestoreInstanceState(ss.getSuperState());
 
         if (mSession == null && ss.session != null) {
             setSession(ss.session, ss.session.getRuntime());
         } else if (ss.session != null) {
             mSession.transferFrom(ss.session);
-            mRuntime = mSession.getRuntime();
+            mRuntime = ss.session.getRuntime();
         }
     }
 
     @Override
     public void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
 
         if (!gainFocus || mIsResettingFocus) {
--- a/widget/android/ScreenHelperAndroid.cpp
+++ b/widget/android/ScreenHelperAndroid.cpp
@@ -21,20 +21,16 @@ using namespace mozilla::widget;
 static ScreenHelperAndroid* gHelper = nullptr;
 
 class ScreenHelperAndroid::ScreenHelperSupport final
     : public ScreenManagerHelper::Natives<ScreenHelperSupport>
 {
 public:
     typedef ScreenManagerHelper::Natives<ScreenHelperSupport> Base;
 
-    static void RefreshScreenInfo() {
-      gHelper->Refresh();
-    }
-
     static int32_t AddDisplay(int32_t aDisplayType, int32_t aWidth, int32_t aHeight, float aDensity) {
         static Atomic<uint32_t> nextId;
 
         uint32_t screenId = ++nextId;
         NS_DispatchToMainThread(NS_NewRunnableFunction(
             "ScreenHelperAndroid::ScreenHelperSupport::AddDisplay",
             [aDisplayType, aWidth, aHeight, aDensity, screenId] {
                 MOZ_ASSERT(NS_IsMainThread());