Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/ScreenOrientationListener.java

Issue 179783003: Create ScreenOrientationListener and make it SDK-dependant. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/public/android/java/src/org/chromium/content/browser/ScreenOrientationListener.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/ScreenOrientationListener.java b/content/public/android/java/src/org/chromium/content/browser/ScreenOrientationListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e12861b129d8745c3025f5efc9c841fa0009e3a
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/ScreenOrientationListener.java
@@ -0,0 +1,286 @@
+// Copyright 2014 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.content.ComponentCallbacks;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.Build;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import org.chromium.base.ObserverList;
+import org.chromium.base.ThreadUtils;
+
+/**
+ * ScreenOrientationListener is a class that informs its observers when the
+ * screen orientation changes.
+ */
+class ScreenOrientationListener {
+
+ /**
+ * Observes changes in screen orientation.
+ */
+ public interface ScreenOrientationObserver {
+ /**
+ * Called whenever the screen orientation changes.
+ *
+ * @param orientation The orientation angle of the screen.
+ */
+ void onScreenOrientationChanged(int orientation);
+ }
+
+ /**
+ * ScreenOrientationListenerBackend is an interface that abstract the
+ * mechanism used for the actual screen orientation listening. The reason
+ * being that from Android API Level 17 DisplayListener will be used. Before
+ * that, an unreliable solution based on onConfigurationChanged has to be
+ * used.
+ */
+ private interface ScreenOrientationListenerBackend {
+
+ /**
+ * Starts to listen for screen orientation changes. This will be called
+ * when the first observer is added.
+ */
+ void startListening();
+
+ /**
+ * Stops to listen for screen orientation changes. This will be called
+ * when the last observer is removed.
+ */
+ void stopListening();
+ }
+
+ /**
+ * ScreenOrientationConfigurationListener implements ScreenOrientationListenerBackend
+ * to use ComponentCallbacks in order to listen for screen orientation
+ * changes.
+ *
+ * This method is known to not correctly detect 180 degrees changes but it
+ * is the only method that will work before API Level 17 (excluding polling).
+ */
+ private class ScreenOrientationConfigurationListener
+ implements ScreenOrientationListenerBackend, ComponentCallbacks {
+
+ // ScreenOrientationListenerBackend implementation:
+
+ @Override
+ public void startListening() {
+ mAppContext.registerComponentCallbacks(this);
+ }
+
+ @Override
+ public void stopListening() {
+ mAppContext.unregisterComponentCallbacks(this);
+ }
+
+ // ComponentCallbacks implementation:
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ notifyObservers();
+ }
+
+ @Override
+ public void onLowMemory() {
+ }
+ }
+
+ /**
+ * ScreenOrientationDisplayListener implements ScreenOrientationListenerBackend
+ * to use DisplayListener in order to listen for screen orientation changes.
+ *
+ * This method is reliable but DisplayListener is only available for API Level 17+.
+ */
+ private class ScreenOrientationDisplayListener
+ implements ScreenOrientationListenerBackend, DisplayListener {
+
+ // ScreenOrientationListenerBackend implementation:
+
+ @Override
+ public void startListening() {
+ DisplayManager displayManager =
+ (DisplayManager) mAppContext.getSystemService(Context.DISPLAY_SERVICE);
+ displayManager.registerDisplayListener(this, null);
+ }
+
+ @Override
+ public void stopListening() {
+ DisplayManager displayManager =
+ (DisplayManager) mAppContext.getSystemService(Context.DISPLAY_SERVICE);
+ displayManager.unregisterDisplayListener(this);
+ }
+
+ // DisplayListener implementation:
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ notifyObservers();
+ }
+
+ }
+
+ private static final String TAG = "ScreenOrientationListener";
+
+ // List of observers to notify when the screen orientation changes.
+ private final ObserverList<ScreenOrientationObserver> mObservers =
+ new ObserverList<ScreenOrientationObserver>();
+
+ // Number of observers currently in |mObservers|.
+ // TODO(mlamouri): hopefully, we can get ObserverList to provide that,
+ // http://crbug.com/347558
+ private int mObserverCount;
+
+ // mOrientation will be updated every time the orientation changes. When not
+ // listening for changes, the value will be invalid and will be updated when
+ // starting to listen again.
+ private int mOrientation;
+
+ // Current application context derived from the first context being received.
+ private Context mAppContext;
+
+ private ScreenOrientationListenerBackend mBackend;
+
+ private static ScreenOrientationListener sInstance;
+
+ /**
+ * Returns a ScreenOrientationListener implementation based on the device's
+ * supported API level.
+ */
+ public static ScreenOrientationListener getInstance() {
+ ThreadUtils.assertOnUiThread();
+
+ if (sInstance == null) {
+ sInstance = new ScreenOrientationListener();
+ }
+
+ return sInstance;
+ }
+
+ private ScreenOrientationListener() {
+ mBackend = Build.VERSION.SDK_INT >= 17 ?
+ new ScreenOrientationDisplayListener() :
+ new ScreenOrientationConfigurationListener();
+ }
+
+ /**
+ * Add |observer| in the ScreenOrientationListener observer list and
+ * immediately call |onScreenOrientationChanged| on it with the current
+ * orientation value.
+ *
+ * @param observer The observer that will get notified.
+ * @param context The context associated with this observer.
+ */
+ public void addObserver(ScreenOrientationObserver observer, Context context) {
+ if (mAppContext == null) {
+ mAppContext = context.getApplicationContext();
+ }
+
+ assert mAppContext == context.getApplicationContext();
+ assert mAppContext != null;
+
+ // TODO(mlamouri): we should check if the observer was really added,
+ // http://crbug.com/347557
+ if (mObservers.hasObserver(observer)) {
+ return;
+ }
+ mObservers.addObserver(observer);
+ mObserverCount++;
+
+ // If we got our first observer, we should start listening.
+ if (mObserverCount == 1) {
+ updateOrientation();
+ mBackend.startListening();
+ }
+
+ // We need to send the current value to the added observer as soon as
+ // possible but outside of the current stack.
+ final ScreenOrientationObserver obs = observer;
+ ThreadUtils.assertOnUiThread();
+ ThreadUtils.postOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ obs.onScreenOrientationChanged(mOrientation);
+ }
+ });
+ }
+
+ /**
+ * Remove the |observer| from the ScreenOrientationListener observer list.
+ *
+ * @param observer The observer that will no longer receive notification.
+ */
+ public void removeObserver(ScreenOrientationObserver observer) {
+ // TODO(mlamouri): we should check if the observer was really removed,
+ // http://crbug.com/347557
+ if (!mObservers.hasObserver(observer)) {
+ return;
+ }
+ mObservers.removeObserver(observer);
+ mObserverCount--;
+
+ if (mObserverCount == 0) {
+ // The last observer was removed, we should just stop listening.
+ mBackend.stopListening();
+ }
+
+ assert mObserverCount >= 0;
+ }
+
+ /**
+ * This should be called by classes extending ScreenOrientationListener when
+ * it is possible that there is a screen orientation change. If there is an
+ * actual change, the observers will get notified.
+ */
+ private void notifyObservers() {
+ int previousOrientation = mOrientation;
+ updateOrientation();
+
+ if (mOrientation == previousOrientation) {
+ return;
+ }
+
+ for (ScreenOrientationObserver observer : mObservers) {
+ observer.onScreenOrientationChanged(mOrientation);
+ }
+ }
+
+ /**
+ * Updates |mOrientation| based on the default display rotation.
+ */
+ private void updateOrientation() {
+ WindowManager windowManager =
+ (WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE);
+
+ switch (windowManager.getDefaultDisplay().getRotation()) {
+ case Surface.ROTATION_0:
+ mOrientation = 0;
+ break;
+ case Surface.ROTATION_90:
+ mOrientation = 90;
+ break;
+ case Surface.ROTATION_180:
+ mOrientation = 180;
+ break;
+ case Surface.ROTATION_270:
+ mOrientation = -90;
+ break;
+ default:
+ throw new IllegalStateException(
+ "Display.getRotation() shouldn't return that value");
+ }
+ }
+}
« no previous file with comments | « content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698