summaryrefslogtreecommitdiffstats
path: root/base/android
diff options
context:
space:
mode:
authordtrainor@chromium.org <dtrainor@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-21 23:04:08 +0000
committerdtrainor@chromium.org <dtrainor@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-21 23:04:08 +0000
commite5c934a20f125922bbe2916402648fbd532c73d7 (patch)
tree79e2ea2042f10f7bb4716f5efb59b23f0faa0937 /base/android
parent675a5a9f1a77c17ee0f26bc72be4a926796dfe95 (diff)
downloadchromium_src-e5c934a20f125922bbe2916402648fbd532c73d7.zip
chromium_src-e5c934a20f125922bbe2916402648fbd532c73d7.tar.gz
chromium_src-e5c934a20f125922bbe2916402648fbd532c73d7.tar.bz2
Refactor ActivityStatus to not store current
- Refactor ActivityStatus to expose application level visibility over activity visbility. - Add a listener for the visibility of the Application (are any Activities visible?) BUG=341231 NOTRY=true Review URL: https://codereview.chromium.org/159173002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@252679 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/android')
-rw-r--r--base/android/activity_state_list.h16
-rw-r--r--base/android/activity_status.cc66
-rw-r--r--base/android/activity_status.h98
-rw-r--r--base/android/application_state_list.h17
-rw-r--r--base/android/application_status_listener.cc74
-rw-r--r--base/android/application_status_listener.h79
-rw-r--r--base/android/application_status_listener_unittest.cc (renamed from base/android/activity_status_unittest.cc)56
-rw-r--r--base/android/base_jni_registrar.cc5
-rw-r--r--base/android/java/src/org/chromium/base/ActivityState.java40
-rw-r--r--base/android/java/src/org/chromium/base/ActivityState.template14
-rw-r--r--base/android/java/src/org/chromium/base/ActivityStatus.java259
-rw-r--r--base/android/java/src/org/chromium/base/ApplicationState.template14
-rw-r--r--base/android/java/src/org/chromium/base/ApplicationStatus.java421
-rw-r--r--base/android/java/src/org/chromium/base/BaseChromiumApplication.java81
-rw-r--r--base/android/java/src/org/chromium/base/PowerMonitor.java10
-rw-r--r--base/android/java/src/org/chromium/base/WindowCallbackWrapper.java134
16 files changed, 896 insertions, 488 deletions
diff --git a/base/android/activity_state_list.h b/base/android/activity_state_list.h
deleted file mode 100644
index 43c0f80..0000000
--- a/base/android/activity_state_list.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2013 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.
-
-// This file intentionally does not have header guards, it's included
-// inside a macro to generate enum values.
-
-#ifndef DEFINE_ACTIVITY_STATE
-#error "DEFINE_ACTIVITY_STATE should be defined before including this file"
-#endif
-DEFINE_ACTIVITY_STATE(CREATED, 1)
-DEFINE_ACTIVITY_STATE(STARTED, 2)
-DEFINE_ACTIVITY_STATE(RESUMED, 3)
-DEFINE_ACTIVITY_STATE(PAUSED, 4)
-DEFINE_ACTIVITY_STATE(STOPPED, 5)
-DEFINE_ACTIVITY_STATE(DESTROYED, 6)
diff --git a/base/android/activity_status.cc b/base/android/activity_status.cc
deleted file mode 100644
index 4d0be32..0000000
--- a/base/android/activity_status.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 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.
-
-#include "base/android/activity_status.h"
-
-#include <jni.h>
-
-#include "base/memory/singleton.h"
-#include "jni/ActivityStatus_jni.h"
-
-namespace base {
-namespace android {
-
-ActivityStatus::Listener::Listener(
- const ActivityStatus::StateChangeCallback& callback)
- : callback_(callback) {
- ActivityStatus::GetInstance()->RegisterListener(this);
-}
-
-ActivityStatus::Listener::~Listener() {
- ActivityStatus::GetInstance()->UnregisterListener(this);
-}
-
-void ActivityStatus::Listener::Notify(ActivityState state) {
- callback_.Run(state);
-}
-
-// static
-ActivityStatus* ActivityStatus::GetInstance() {
- return Singleton<ActivityStatus,
- LeakySingletonTraits<ActivityStatus> >::get();
-}
-
-static void OnActivityStateChange(JNIEnv* env, jclass clazz, int new_state) {
- ActivityStatus* activity_status = ActivityStatus::GetInstance();
- ActivityState activity_state = static_cast<ActivityState>(new_state);
- activity_status->OnActivityStateChange(activity_state);
-}
-
-bool ActivityStatus::RegisterBindings(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-ActivityStatus::ActivityStatus()
- : observers_(new ObserverListThreadSafe<Listener>()) {
- Java_ActivityStatus_registerThreadSafeNativeStateListener(
- base::android::AttachCurrentThread());
-}
-
-ActivityStatus::~ActivityStatus() {}
-
-void ActivityStatus::RegisterListener(Listener* listener) {
- observers_->AddObserver(listener);
-}
-
-void ActivityStatus::UnregisterListener(Listener* listener) {
- observers_->RemoveObserver(listener);
-}
-
-void ActivityStatus::OnActivityStateChange(ActivityState new_state) {
- observers_->Notify(&ActivityStatus::Listener::Notify, new_state);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/activity_status.h b/base/android/activity_status.h
deleted file mode 100644
index 7975a78..0000000
--- a/base/android/activity_status.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_ANDROID_ACTIVITY_STATUS_H_
-#define BASE_ANDROID_ACTIVITY_STATUS_H_
-
-#include <jni.h>
-
-#include "base/android/jni_android.h"
-#include "base/base_export.h"
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/singleton.h"
-#include "base/observer_list_threadsafe.h"
-
-namespace base {
-namespace android {
-
-// Define activity state values like ACTIVITY_STATE_CREATED in a
-// way that ensures they're always the same than their Java counterpart.
-enum ActivityState {
-#define DEFINE_ACTIVITY_STATE(x, y) ACTIVITY_STATE_##x = y,
-#include "base/android/activity_state_list.h"
-#undef DEFINE_ACTIVITY_STATE
-};
-
-// A native helper class to listen to state changes of the current
-// Android Activity. This mirrors org.chromium.base.ActivityStatus.
-// any thread.
-//
-// To start listening, create a new instance, passing a callback to a
-// function that takes an ActivityState parameter. To stop listening,
-// simply delete the listener object. The implementation guarantees
-// that the callback will always be called on the thread that created
-// the listener.
-//
-// Example:
-//
-// void OnActivityStateChange(ActivityState state) {
-// ...
-// }
-//
-// // Start listening.
-// ActivityStatus::Listener* my_listener =
-// new ActivityStatus::Listener(base::Bind(&OnActivityStateChange));
-//
-// ...
-//
-// // Stop listening.
-// delete my_listener
-//
-class BASE_EXPORT ActivityStatus {
- public:
- typedef base::Callback<void(ActivityState)> StateChangeCallback;
-
- class Listener {
- public:
- explicit Listener(const StateChangeCallback& callback);
- ~Listener();
-
- private:
- friend class ActivityStatus;
-
- void Notify(ActivityState state);
-
- StateChangeCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(Listener);
- };
-
- // NOTE: The Java ActivityStatus is a singleton too.
- static ActivityStatus* GetInstance();
-
- // Internal use: must be public to be called from base_jni_registrar.cc
- static bool RegisterBindings(JNIEnv* env);
-
- // Internal use only: must be public to be called from JNI and unit tests.
- void OnActivityStateChange(ActivityState new_state);
-
- private:
- friend struct DefaultSingletonTraits<ActivityStatus>;
-
- ActivityStatus();
- ~ActivityStatus();
-
- void RegisterListener(Listener* listener);
- void UnregisterListener(Listener* listener);
-
- scoped_refptr<ObserverListThreadSafe<Listener> > observers_;
-
- DISALLOW_COPY_AND_ASSIGN(ActivityStatus);
-};
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_ACTIVITY_STATUS_H_
diff --git a/base/android/application_state_list.h b/base/android/application_state_list.h
new file mode 100644
index 0000000..cbc833e
--- /dev/null
+++ b/base/android/application_state_list.h
@@ -0,0 +1,17 @@
+// 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.
+
+// This file intentionally does not have header guards, it's included
+// inside a macro to generate enum values.
+
+// Note that these states represent the most visible Activity state.
+// If there are activities with states paused and stopped, only
+// HAS_PAUSED_ACTIVITIES should be returned.
+#ifndef DEFINE_APPLICATION_STATE
+#error "DEFINE_APPLICATION_STATE should be defined before including this file"
+#endif
+DEFINE_APPLICATION_STATE(HAS_RUNNING_ACTIVITIES, 1)
+DEFINE_APPLICATION_STATE(HAS_PAUSED_ACTIVITIES, 2)
+DEFINE_APPLICATION_STATE(HAS_STOPPED_ACTIVITIES, 3)
+DEFINE_APPLICATION_STATE(HAS_DESTROYED_ACTIVITIES, 4)
diff --git a/base/android/application_status_listener.cc b/base/android/application_status_listener.cc
new file mode 100644
index 0000000..26365d3
--- /dev/null
+++ b/base/android/application_status_listener.cc
@@ -0,0 +1,74 @@
+// 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.
+
+#include "base/android/application_status_listener.h"
+
+#include <jni.h>
+
+#include "base/lazy_instance.h"
+#include "base/observer_list_threadsafe.h"
+#include "jni/ApplicationStatus_jni.h"
+
+namespace {
+struct LeakyLazyObserverListTraits :
+ base::internal::LeakyLazyInstanceTraits<
+ ObserverListThreadSafe<base::android::ApplicationStatusListener> > {
+ static ObserverListThreadSafe<base::android::ApplicationStatusListener>*
+ New(void* instance) {
+ ObserverListThreadSafe<base::android::ApplicationStatusListener>* ret =
+ base::internal::LeakyLazyInstanceTraits<ObserverListThreadSafe<
+ base::android::ApplicationStatusListener> >::New(instance);
+ // Leaky.
+ ret->AddRef();
+ return ret;
+ }
+};
+
+base::LazyInstance<ObserverListThreadSafe<
+ base::android::ApplicationStatusListener>,
+ LeakyLazyObserverListTraits> g_observers = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+namespace base {
+namespace android {
+
+ApplicationStatusListener::ApplicationStatusListener(
+ const ApplicationStatusListener::ApplicationStateChangeCallback& callback)
+ : callback_(callback) {
+ DCHECK(!callback_.is_null());
+ g_observers.Get().AddObserver(this);
+}
+
+ApplicationStatusListener::~ApplicationStatusListener() {
+ g_observers.Get().RemoveObserver(this);
+}
+
+void ApplicationStatusListener::Notify(ApplicationState state) {
+ callback_.Run(state);
+}
+
+// static
+bool ApplicationStatusListener::RegisterBindings(JNIEnv* env) {
+ bool result = RegisterNativesImpl(env);
+ if (result)
+ Java_ApplicationStatus_registerThreadSafeNativeApplicationStateListener(env);
+ return result;
+}
+
+// static
+void ApplicationStatusListener::NotifyApplicationStateChange(
+ ApplicationState state) {
+ g_observers.Get().Notify(&ApplicationStatusListener::Notify, state);
+}
+
+static void OnApplicationStateChange(JNIEnv* env,
+ jclass clazz,
+ jint new_state) {
+ ApplicationState application_state = static_cast<ApplicationState>(new_state);
+ ApplicationStatusListener::NotifyApplicationStateChange(application_state);
+}
+
+} // namespace android
+} // namespace base
diff --git a/base/android/application_status_listener.h b/base/android/application_status_listener.h
new file mode 100644
index 0000000..ef98985
--- /dev/null
+++ b/base/android/application_status_listener.h
@@ -0,0 +1,79 @@
+// 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.
+
+#ifndef BASE_ANDROID_APPLICATION_STATUS_LISTENER_H_
+#define BASE_ANDROID_APPLICATION_STATUS_LISTENER_H_
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "base/observer_list_threadsafe.h"
+
+namespace base {
+namespace android {
+
+// Define application state values like APPLICATION_STATE_VISIBLE in a
+// way that ensures they're always the same than their Java counterpart.
+enum ApplicationState {
+#define DEFINE_APPLICATION_STATE(x, y) APPLICATION_STATE_##x = y,
+#include "base/android/application_state_list.h"
+#undef DEFINE_APPLICATION_STATE
+};
+
+// A native helper class to listen to state changes of the Android
+// Application. This mirrors org.chromium.base.ApplicationStatus.
+// any thread.
+//
+// To start listening, create a new instance, passing a callback to a
+// function that takes an ApplicationState parameter. To stop listening,
+// simply delete the listener object. The implementation guarantees
+// that the callback will always be called on the thread that created
+// the listener.
+//
+// Example:
+//
+// void OnApplicationStateChange(ApplicationState state) {
+// ...
+// }
+//
+// // Start listening.
+// ApplicationStatusListener* my_listener =
+// new ApplicationStatusListener(
+// base::Bind(&OnApplicationStateChange));
+//
+// ...
+//
+// // Stop listening.
+// delete my_listener
+//
+class BASE_EXPORT ApplicationStatusListener {
+ public:
+ typedef base::Callback<void(ApplicationState)> ApplicationStateChangeCallback;
+
+ explicit ApplicationStatusListener(
+ const ApplicationStateChangeCallback& callback);
+ ~ApplicationStatusListener();
+
+ // Internal use: must be public to be called from base_jni_registrar.cc
+ static bool RegisterBindings(JNIEnv* env);
+
+ // Internal use only: must be public to be called from JNI and unit tests.
+ static void NotifyApplicationStateChange(ApplicationState state);
+
+ private:
+ void Notify(ApplicationState state);
+
+ ApplicationStateChangeCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(ApplicationStatusListener);
+};
+
+} // namespace android
+} // namespace base
+
+#endif // BASE_ANDROID_APPLICATION_STATUS_LISTENER_H_
diff --git a/base/android/activity_status_unittest.cc b/base/android/application_status_listener_unittest.cc
index 3eb0d10..1049628 100644
--- a/base/android/activity_status_unittest.cc
+++ b/base/android/application_status_listener_unittest.cc
@@ -1,8 +1,8 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// 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.
-#include "base/android/activity_status.h"
+#include "base/android/application_status_listener.h"
#include "base/bind.h"
#include "base/callback_forward.h"
#include "base/logging.h"
@@ -20,11 +20,12 @@ namespace {
using base::android::ScopedJavaLocalRef;
-// An invalid ActivityState value.
-const ActivityState kInvalidActivityState = static_cast<ActivityState>(100);
+// An invalid ApplicationState value.
+const ApplicationState kInvalidApplicationState =
+ static_cast<ApplicationState>(100);
// Used to generate a callback that stores the new state at a given location.
-void StoreStateTo(ActivityState* target, ActivityState state) {
+void StoreStateTo(ApplicationState* target, ApplicationState state) {
*target = state;
}
@@ -39,10 +40,9 @@ void RunTasksUntilIdle() {
class MultiThreadedTest {
public:
MultiThreadedTest()
- : activity_status_(ActivityStatus::GetInstance()),
- state_(kInvalidActivityState),
+ : state_(kInvalidApplicationState),
event_(false, false),
- thread_("ActivityStatusTest thread"),
+ thread_("ApplicationStatusTest thread"),
main_() {
}
@@ -58,14 +58,16 @@ class MultiThreadedTest {
event_.Wait();
// Change state, then wait for the thread to modify state.
- activity_status_->OnActivityStateChange(ACTIVITY_STATE_CREATED);
+ ApplicationStatusListener::NotifyApplicationStateChange(
+ APPLICATION_STATE_HAS_RUNNING_ACTIVITIES);
event_.Wait();
- EXPECT_EQ(ACTIVITY_STATE_CREATED, state_);
+ EXPECT_EQ(APPLICATION_STATE_HAS_RUNNING_ACTIVITIES, state_);
// Again
- activity_status_->OnActivityStateChange(ACTIVITY_STATE_DESTROYED);
+ ApplicationStatusListener::NotifyApplicationStateChange(
+ APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES);
event_.Wait();
- EXPECT_EQ(ACTIVITY_STATE_DESTROYED, state_);
+ EXPECT_EQ(APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES, state_);
}
private:
@@ -75,51 +77,51 @@ class MultiThreadedTest {
void RegisterThreadForEvents() {
ExpectOnThread();
- listener_.reset(new ActivityStatus::Listener(base::Bind(
+ listener_.reset(new ApplicationStatusListener(base::Bind(
&MultiThreadedTest::StoreStateAndSignal, base::Unretained(this))));
EXPECT_TRUE(listener_.get());
event_.Signal();
}
- void StoreStateAndSignal(ActivityState state) {
+ void StoreStateAndSignal(ApplicationState state) {
ExpectOnThread();
state_ = state;
event_.Signal();
}
- ActivityStatus* const activity_status_;
- ActivityState state_;
+ ApplicationState state_;
base::WaitableEvent event_;
base::Thread thread_;
base::MessageLoop main_;
- scoped_ptr<ActivityStatus::Listener> listener_;
+ scoped_ptr<ApplicationStatusListener> listener_;
};
} // namespace
-TEST(ActivityStatusTest, SingleThread) {
+TEST(ApplicationStatusListenerTest, SingleThread) {
MessageLoop message_loop;
- ActivityState result = kInvalidActivityState;
+ ApplicationState result = kInvalidApplicationState;
// Create a new listener that stores the new state into |result| on every
// state change.
- ActivityStatus::Listener listener(
+ ApplicationStatusListener listener(
base::Bind(&StoreStateTo, base::Unretained(&result)));
- EXPECT_EQ(kInvalidActivityState, result);
+ EXPECT_EQ(kInvalidApplicationState, result);
- ActivityStatus* const activity_status = ActivityStatus::GetInstance();
- activity_status->OnActivityStateChange(ACTIVITY_STATE_CREATED);
+ ApplicationStatusListener::NotifyApplicationStateChange(
+ APPLICATION_STATE_HAS_RUNNING_ACTIVITIES);
RunTasksUntilIdle();
- EXPECT_EQ(ACTIVITY_STATE_CREATED, result);
+ EXPECT_EQ(APPLICATION_STATE_HAS_RUNNING_ACTIVITIES, result);
- activity_status->OnActivityStateChange(ACTIVITY_STATE_DESTROYED);
+ ApplicationStatusListener::NotifyApplicationStateChange(
+ APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES);
RunTasksUntilIdle();
- EXPECT_EQ(ACTIVITY_STATE_DESTROYED, result);
+ EXPECT_EQ(APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES, result);
}
-TEST(ActivityStatusTest, TwoThreads) {
+TEST(ApplicationStatusListenerTest, TwoThreads) {
MultiThreadedTest test;
test.Run();
}
diff --git a/base/android/base_jni_registrar.cc b/base/android/base_jni_registrar.cc
index c474375..e14fd44 100644
--- a/base/android/base_jni_registrar.cc
+++ b/base/android/base_jni_registrar.cc
@@ -4,7 +4,7 @@
#include "base/android/base_jni_registrar.h"
-#include "base/android/activity_status.h"
+#include "base/android/application_status_listener.h"
#include "base/android/build_info.h"
#include "base/android/command_line_android.h"
#include "base/android/content_uri_utils.h"
@@ -28,7 +28,8 @@ namespace base {
namespace android {
static RegistrationMethod kBaseRegisteredMethods[] = {
- { "ActivityStatus", base::android::ActivityStatus::RegisterBindings },
+ { "ApplicationStatusListener",
+ base::android::ApplicationStatusListener::RegisterBindings },
{ "BuildInfo", base::android::BuildInfo::RegisterBindings },
{ "CommandLine", base::android::RegisterCommandLine },
{ "ContentUriUtils", base::RegisterContentUriUtils },
diff --git a/base/android/java/src/org/chromium/base/ActivityState.java b/base/android/java/src/org/chromium/base/ActivityState.java
new file mode 100644
index 0000000..98aff62
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/ActivityState.java
@@ -0,0 +1,40 @@
+// 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.base;
+
+/**
+ * A set of states that represent the last state change of an Activity.
+ */
+public interface ActivityState {
+ /**
+ * Represents Activity#onCreate().
+ */
+ public final int CREATED = 1;
+
+ /**
+ * Represents Activity#onStart().
+ */
+ public final int STARTED = 2;
+
+ /**
+ * Represents Activity#onResume().
+ */
+ public final int RESUMED = 3;
+
+ /**
+ * Represents Activity#onPause().
+ */
+ public final int PAUSED = 4;
+
+ /**
+ * Represents Activity#onStop().
+ */
+ public final int STOPPED = 5;
+
+ /**
+ * Represents Activity#onDestroy(). This is also used when the state of an Activity is unknown.
+ */
+ public final int DESTROYED = 6;
+}
diff --git a/base/android/java/src/org/chromium/base/ActivityState.template b/base/android/java/src/org/chromium/base/ActivityState.template
deleted file mode 100644
index 5b3a9d0..0000000
--- a/base/android/java/src/org/chromium/base/ActivityState.template
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2013 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.base;
-
-// A simple auto-generated interface used to list the various
-// states of an activity as used by both org.chromium.base.ActivityStatus
-// and base/android/activity_status.h
-interface ActivityState {
-#define DEFINE_ACTIVITY_STATE(x,y) public final int x = y;
-#include "base/android/activity_state_list.h"
-#undef DEFINE_ACTIVITY_STATE
-}
diff --git a/base/android/java/src/org/chromium/base/ActivityStatus.java b/base/android/java/src/org/chromium/base/ActivityStatus.java
deleted file mode 100644
index df43dbe..0000000
--- a/base/android/java/src/org/chromium/base/ActivityStatus.java
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2012 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.base;
-
-import android.app.Activity;
-import android.app.Application;
-import android.app.Application.ActivityLifecycleCallbacks;
-import android.os.Bundle;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Provides information about the current activity's status, and a way
- * to register / unregister listeners for state changes.
- */
-@JNINamespace("base::android")
-public class ActivityStatus {
-
- // Constants matching activity states reported to StateListener.onStateChange
- // As an implementation detail, these are now defined in the auto-generated
- // ActivityState interface, to be shared with C++.
- public static final int CREATED = ActivityState.CREATED;
- public static final int STARTED = ActivityState.STARTED;
- public static final int RESUMED = ActivityState.RESUMED;
- public static final int PAUSED = ActivityState.PAUSED;
- public static final int STOPPED = ActivityState.STOPPED;
- public static final int DESTROYED = ActivityState.DESTROYED;
-
- // Last activity that was shown (or null if none or it was destroyed).
- private static Activity sActivity;
-
- private static final Map<Activity, Integer> sActivityStates =
- new HashMap<Activity, Integer>();
-
- private static final ObserverList<StateListener> sStateListeners =
- new ObserverList<StateListener>();
-
- /**
- * Interface to be implemented by listeners.
- */
- public interface StateListener {
- /**
- * Called when the activity's state changes.
- * @param newState New activity state.
- */
- public void onActivityStateChange(int newState);
- }
-
- private ActivityStatus() {}
-
- /**
- * Initializes the activity status for a specified application.
- *
- * @param application The application whose status you wish to monitor.
- */
- public static void initialize(Application application) {
- application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
- @Override
- public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
- onStateChange(activity, CREATED);
- }
-
- @Override
- public void onActivityDestroyed(Activity activity) {
- onStateChange(activity, DESTROYED);
- }
-
- @Override
- public void onActivityPaused(Activity activity) {
- onStateChange(activity, PAUSED);
- }
-
- @Override
- public void onActivityResumed(Activity activity) {
- onStateChange(activity, RESUMED);
- }
-
- @Override
- public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
-
- @Override
- public void onActivityStarted(Activity activity) {
- onStateChange(activity, STARTED);
- }
-
- @Override
- public void onActivityStopped(Activity activity) {
- onStateChange(activity, STOPPED);
- }
- });
- }
-
- /**
- * Must be called by the main activity when it changes state.
- *
- * @param activity Current activity.
- * @param newState New state value.
- */
- private static void onStateChange(Activity activity, int newState) {
- if (activity == null) throw new IllegalArgumentException("null activity is not supported");
-
- if (sActivity != activity) {
- // ActivityStatus is notified with the CREATED event very late during the main activity
- // creation to avoid making startup performance worse than it is by notifying observers
- // that could do some expensive work. This can lead to non-CREATED events being fired
- // before the CREATED event which is problematic.
- // TODO(pliard): fix http://crbug.com/176837.
- if (sActivity == null
- || newState == CREATED || newState == RESUMED || newState == STARTED) {
- sActivity = activity;
- }
- }
-
- if (newState != DESTROYED) {
- sActivityStates.put(activity, newState);
- } else {
- sActivityStates.remove(activity);
- }
-
- if (sActivity == activity) {
- for (StateListener listener : sStateListeners) {
- listener.onActivityStateChange(newState);
- }
- if (newState == DESTROYED) {
- sActivity = null;
- }
- }
- }
-
- /**
- * Testing method to update the state of the specified activity.
- */
- public static void onStateChangeForTesting(Activity activity, int newState) {
- onStateChange(activity, newState);
- }
-
- /**
- * @return The current activity.
- */
- public static Activity getActivity() {
- return sActivity;
- }
-
- /**
- * @return The current activity's state (if no activity is registered, then DESTROYED will
- * be returned).
- */
- public static int getState() {
- return getStateForActivity(sActivity);
- }
-
- /**
- * Query the state for a given activity. If the activity is not being tracked, this will
- * return {@link #DESTROYED}.
- *
- * <p>
- * When relying on this method, be familiar with the expected life cycle state
- * transitions:
- * <a href="http://developer.android.com/guide/components/activities.html#Lifecycle">
- * Activity Lifecycle
- * </a>
- *
- * <p>
- * During activity transitions (activity B launching in front of activity A), A will completely
- * paused before the creation of activity B begins.
- *
- * <p>
- * A basic flow for activity A starting, followed by activity B being opened and then closed:
- * <ul>
- * <li> -- Starting Activity A --
- * <li> Activity A - CREATED
- * <li> Activity A - STARTED
- * <li> Activity A - RESUMED
- * <li> -- Starting Activity B --
- * <li> Activity A - PAUSED
- * <li> Activity B - CREATED
- * <li> Activity B - STARTED
- * <li> Activity B - RESUMED
- * <li> Activity A - STOPPED
- * <li> -- Closing Activity B, Activity A regaining focus --
- * <li> Activity B - PAUSED
- * <li> Activity A - STARTED
- * <li> Activity A - RESUMED
- * <li> Activity B - STOPPED
- * <li> Activity B - DESTROYED
- * </ul>
- *
- * @param activity The activity whose state is to be returned.
- * @return The state of the specified activity.
- */
- public static int getStateForActivity(Activity activity) {
- Integer currentStatus = sActivityStates.get(activity);
- return currentStatus != null ? currentStatus.intValue() : DESTROYED;
- }
-
- /**
- * Registers the given listener to receive activity state changes.
- * @param listener Listener to receive state changes.
- */
- public static void registerStateListener(StateListener listener) {
- sStateListeners.addObserver(listener);
- }
-
- /**
- * Unregisters the given listener from receiving activity state changes.
- * @param listener Listener that doesn't want to receive state changes.
- */
- public static void unregisterStateListener(StateListener listener) {
- sStateListeners.removeObserver(listener);
- }
-
- /**
- * Registers the single thread-safe native activity status listener.
- * This handles the case where the caller is not on the main thread.
- * Note that this is used by a leaky singleton object from the native
- * side, hence lifecycle management is greatly simplified.
- */
- @CalledByNative
- private static void registerThreadSafeNativeStateListener() {
- ThreadUtils.runOnUiThread(new Runnable () {
- @Override
- public void run() {
- // Register a new listener that calls nativeOnActivityStateChange.
- sStateListeners.addObserver(new StateListener() {
- @Override
- public void onActivityStateChange(int newState) {
- nativeOnActivityStateChange(newState);
- }
- });
- }
- });
- }
-
- // Called to notify the native side of state changes.
- // IMPORTANT: This is always called on the main thread!
- private static native void nativeOnActivityStateChange(int newState);
-
- /**
- * Checks whether or not the Application's current Activity is visible to the user. Note that
- * this includes the PAUSED state, which can happen when the Activity is temporarily covered
- * by another Activity's Fragment (e.g.).
- * @return True if the Activity is visible, false otherwise.
- */
- public static boolean isApplicationVisible() {
- int state = getState();
- return state != STOPPED && state != DESTROYED;
- }
-
- /**
- * Checks to see if there are any active Activity instances being watched by ActivityStatus.
- * @return True if all Activities have been destroyed.
- */
- public static boolean isEveryActivityDestroyed() {
- return sActivityStates.isEmpty();
- }
-}
diff --git a/base/android/java/src/org/chromium/base/ApplicationState.template b/base/android/java/src/org/chromium/base/ApplicationState.template
new file mode 100644
index 0000000..892c055
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/ApplicationState.template
@@ -0,0 +1,14 @@
+// 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.base;
+
+// A simple auto-generated interface used to list the various
+// states of an application as used by both org.chromium.base.ApplicationStatus
+// and base/android/application_status.h
+public interface ApplicationState {
+#define DEFINE_APPLICATION_STATE(x,y) public final int x = y;
+#include "base/android/application_state_list.h"
+#undef DEFINE_APPLICATION_STATE
+}
diff --git a/base/android/java/src/org/chromium/base/ApplicationStatus.java b/base/android/java/src/org/chromium/base/ApplicationStatus.java
new file mode 100644
index 0000000..ce3cafe
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/ApplicationStatus.java
@@ -0,0 +1,421 @@
+// 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.base;
+
+import android.app.Activity;
+import android.app.Application;
+import android.app.Application.ActivityLifecycleCallbacks;
+import android.content.Context;
+import android.os.Bundle;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Provides information about the current activity's status, and a way
+ * to register / unregister listeners for state changes.
+ */
+@JNINamespace("base::android")
+public class ApplicationStatus {
+ private static class ActivityInfo {
+ private int mStatus = ActivityState.DESTROYED;
+ private ObserverList<ActivityStateListener> mListeners =
+ new ObserverList<ActivityStateListener>();
+
+ /**
+ * @return The current {@link ActivityState} of the activity.
+ */
+ public int getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * @param status The new {@link ActivityState} of the activity.
+ */
+ public void setStatus(int status) {
+ mStatus = status;
+ }
+
+ /**
+ * @return A list of {@link ActivityStateListener}s listening to this activity.
+ */
+ public ObserverList<ActivityStateListener> getListeners() {
+ return mListeners;
+ }
+ }
+
+ private static Application sApplication;
+
+ private static Integer sCachedApplicationState;
+
+ /** Last activity that was shown (or null if none or it was destroyed). */
+ private static Activity sActivity;
+
+ /**
+ *
+ */
+ private static final Map<Activity, ActivityInfo> sActivityInfo =
+ new HashMap<Activity, ActivityInfo>();
+
+ /**
+ *
+ */
+ private static final ObserverList<ActivityStateListener> sGeneralActivityStateListeners =
+ new ObserverList<ActivityStateListener>();
+
+ /**
+ * A list of observers to be notified when the visibility state of this {@link Application}
+ * changes. See {@link #getStateForApplication()}.
+ */
+ private static final ObserverList<ApplicationStateListener> sApplicationStateListeners =
+ new ObserverList<ApplicationStateListener>();
+
+ /**
+ * Interface to be implemented by listeners.
+ */
+ public interface ApplicationStateListener {
+ /**
+ * Called when the application's state changes.
+ * @param newState The application state.
+ */
+ public void onApplicationStateChange(int newState);
+ }
+
+ /**
+ * Interface to be implemented by listeners.
+ */
+ public interface ActivityStateListener {
+ /**
+ * Called when the activity's state changes.
+ * @param activity The activity that had a state change.
+ * @param newState New activity state.
+ */
+ public void onActivityStateChange(Activity activity, int newState);
+ }
+
+ private ApplicationStatus() {}
+
+ /**
+ * Initializes the activity status for a specified application.
+ *
+ * @param application The application whose status you wish to monitor.
+ */
+ public static void initialize(BaseChromiumApplication application) {
+ sApplication = application;
+
+ application.registerWindowFocusChangedListener(
+ new BaseChromiumApplication.WindowFocusChangedListener() {
+ @Override
+ public void onWindowFocusChanged(Activity activity, boolean hasFocus) {
+ if (!hasFocus || activity == sActivity) return;
+
+ int state = getStateForActivity(activity);
+
+ if (state != ActivityState.DESTROYED && state != ActivityState.STOPPED) {
+ sActivity = activity;
+ }
+
+ // TODO(dtrainor): Notify of active activity change?
+ }
+ });
+
+ application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
+ @Override
+ public void onActivityCreated(final Activity activity, Bundle savedInstanceState) {
+ onStateChange(activity, ActivityState.CREATED);
+ }
+
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ onStateChange(activity, ActivityState.DESTROYED);
+ }
+
+ @Override
+ public void onActivityPaused(Activity activity) {
+ onStateChange(activity, ActivityState.PAUSED);
+ }
+
+ @Override
+ public void onActivityResumed(Activity activity) {
+ onStateChange(activity, ActivityState.RESUMED);
+ }
+
+ @Override
+ public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
+
+ @Override
+ public void onActivityStarted(Activity activity) {
+ onStateChange(activity, ActivityState.STARTED);
+ }
+
+ @Override
+ public void onActivityStopped(Activity activity) {
+ onStateChange(activity, ActivityState.STOPPED);
+ }
+ });
+ }
+
+ /**
+ * Must be called by the main activity when it changes state.
+ *
+ * @param activity Current activity.
+ * @param newState New state value.
+ */
+ private static void onStateChange(Activity activity, int newState) {
+ if (activity == null) throw new IllegalArgumentException("null activity is not supported");
+
+ if (sActivity == null
+ || newState == ActivityState.CREATED
+ || newState == ActivityState.RESUMED
+ || newState == ActivityState.STARTED) {
+ sActivity = activity;
+ }
+
+ int oldApplicationState = getStateForApplication();
+
+ if (newState == ActivityState.CREATED) {
+ assert !sActivityInfo.containsKey(activity);
+ sActivityInfo.put(activity, new ActivityInfo());
+ }
+
+ // Invalidate the cached application state.
+ sCachedApplicationState = null;
+
+ ActivityInfo info = sActivityInfo.get(activity);
+ info.setStatus(newState);
+
+ // Notify all state observers that are specifically listening to this activity.
+ for (ActivityStateListener listener : info.getListeners()) {
+ listener.onActivityStateChange(activity, newState);
+ }
+
+ // Notify all state observers that are listening globally for all activity state
+ // changes.
+ for (ActivityStateListener listener : sGeneralActivityStateListeners) {
+ listener.onActivityStateChange(activity, newState);
+ }
+
+ int applicationState = getStateForApplication();
+ if (applicationState != oldApplicationState) {
+ for (ApplicationStateListener listener : sApplicationStateListeners) {
+ listener.onApplicationStateChange(applicationState);
+ }
+ }
+
+ if (newState == ActivityState.DESTROYED) {
+ sActivityInfo.remove(activity);
+ if (activity == sActivity) sActivity = null;
+ }
+ }
+
+ /**
+ * Testing method to update the state of the specified activity.
+ */
+ public static void onStateChangeForTesting(Activity activity, int newState) {
+ onStateChange(activity, newState);
+ }
+
+ /**
+ * @return The most recent focused {@link Activity} tracked by this class. Being focused means
+ * out of all the activities tracked here, it has most recently gained window focus.
+ */
+ public static Activity getLastTrackedFocusedActivity() {
+ return sActivity;
+ }
+
+ /**
+ * @return The {@link Context} for the {@link Application}.
+ */
+ public static Context getApplicationContext() {
+ return sApplication != null ? sApplication.getApplicationContext() : null;
+ }
+
+ /**
+ * Query the state for a given activity. If the activity is not being tracked, this will
+ * return {@link ActivityState#DESTROYED}.
+ *
+ * <p>
+ * Please note that Chrome can have multiple activities running simultaneously. Please also
+ * look at {@link #getStateForApplication()} for more details.
+ *
+ * <p>
+ * When relying on this method, be familiar with the expected life cycle state
+ * transitions:
+ * <a href="http://developer.android.com/guide/components/activities.html#Lifecycle">
+ * Activity Lifecycle
+ * </a>
+ *
+ * <p>
+ * During activity transitions (activity B launching in front of activity A), A will completely
+ * paused before the creation of activity B begins.
+ *
+ * <p>
+ * A basic flow for activity A starting, followed by activity B being opened and then closed:
+ * <ul>
+ * <li> -- Starting Activity A --
+ * <li> Activity A - ActivityState.CREATED
+ * <li> Activity A - ActivityState.STARTED
+ * <li> Activity A - ActivityState.RESUMED
+ * <li> -- Starting Activity B --
+ * <li> Activity A - ActivityState.PAUSED
+ * <li> Activity B - ActivityState.CREATED
+ * <li> Activity B - ActivityState.STARTED
+ * <li> Activity B - ActivityState.RESUMED
+ * <li> Activity A - ActivityState.STOPPED
+ * <li> -- Closing Activity B, Activity A regaining focus --
+ * <li> Activity B - ActivityState.PAUSED
+ * <li> Activity A - ActivityState.STARTED
+ * <li> Activity A - ActivityState.RESUMED
+ * <li> Activity B - ActivityState.STOPPED
+ * <li> Activity B - ActivityState.DESTROYED
+ * </ul>
+ *
+ * @param activity The activity whose state is to be returned.
+ * @return The state of the specified activity (see {@link ActivityState}).
+ */
+ public static int getStateForActivity(Activity activity) {
+ ActivityInfo info = sActivityInfo.get(activity);
+ return info != null ? info.getStatus() : ActivityState.DESTROYED;
+ }
+
+ /**
+ * @return The state of the application (see {@link ApplicationState}).
+ */
+ public static int getStateForApplication() {
+ if (sCachedApplicationState == null) sCachedApplicationState = determineApplicationState();
+
+ return sCachedApplicationState.intValue();
+ }
+
+ /**
+ * Checks whether or not any Activity in this Application is visible to the user. Note that
+ * this includes the PAUSED state, which can happen when the Activity is temporarily covered
+ * by another Activity's Fragment (e.g.).
+ * @return Whether any Activity under this Application is visible.
+ */
+ public static boolean hasVisibleActivities() {
+ int state = getStateForApplication();
+ return state == ApplicationState.HAS_RUNNING_ACTIVITIES
+ || state == ApplicationState.HAS_PAUSED_ACTIVITIES;
+ }
+
+ /**
+ * Checks to see if there are any active Activity instances being watched by ApplicationStatus.
+ * @return True if all Activities have been destroyed.
+ */
+ public static boolean isEveryActivityDestroyed() {
+ return sActivityInfo.isEmpty();
+ }
+
+ /**
+ * Registers the given listener to receive state changes for all activities.
+ * @param listener Listener to receive state changes.
+ */
+ public static void registerStateListenerForAllActivities(ActivityStateListener listener) {
+ sGeneralActivityStateListeners.addObserver(listener);
+ }
+
+ /**
+ * Registers the given listener to receive state changes for {@code activity}. After a call to
+ * {@link ActivityStateListener#onActivityStateChange(Activity, int)} with
+ * {@link ActivityState#DESTROYED} all listeners associated with that particular
+ * {@link Activity} are removed.
+ * @param listener Listener to receive state changes.
+ * @param activity Activity to track or {@code null} to track all activities.
+ */
+ public static void registerStateListenerForActivity(ActivityStateListener listener,
+ Activity activity) {
+ assert activity != null;
+
+ ActivityInfo info = sActivityInfo.get(activity);
+ assert info != null && info.getStatus() != ActivityState.DESTROYED;
+ info.getListeners().addObserver(listener);
+ }
+
+ /**
+ * Unregisters the given listener from receiving activity state changes.
+ * @param listener Listener that doesn't want to receive state changes.
+ */
+ public static void unregisterActivityStateListener(ActivityStateListener listener) {
+ sGeneralActivityStateListeners.removeObserver(listener);
+
+ // Loop through all observer lists for all activities and remove the listener.
+ for (ActivityInfo info : sActivityInfo.values()) {
+ info.getListeners().removeObserver(listener);
+ }
+ }
+
+ /**
+ * Registers the given listener to receive state changes for the application.
+ * @param listener Listener to receive state state changes.
+ */
+ public static void registerApplicationStateListener(ApplicationStateListener listener) {
+ sApplicationStateListeners.addObserver(listener);
+ }
+
+ /**
+ * Unregisters the given listener from receiving state changes.
+ * @param listener Listener that doesn't want to receive state changes.
+ */
+ public static void unregisterApplicationStateListener(ApplicationStateListener listener) {
+ sApplicationStateListeners.removeObserver(listener);
+ }
+
+ /**
+ * Registers the single thread-safe native activity status listener.
+ * This handles the case where the caller is not on the main thread.
+ * Note that this is used by a leaky singleton object from the native
+ * side, hence lifecycle management is greatly simplified.
+ */
+ @CalledByNative
+ private static void registerThreadSafeNativeApplicationStateListener() {
+ ThreadUtils.runOnUiThread(new Runnable () {
+ @Override
+ public void run() {
+ registerApplicationStateListener(new ApplicationStateListener() {
+ @Override
+ public void onApplicationStateChange(int newState) {
+ nativeOnApplicationStateChange(newState);
+ }
+ });
+ }
+ });
+ }
+
+ /**
+ * Determines the current application state as defined by {@link ApplicationState}. This will
+ * loop over all the activities and check their state to determine what the general application
+ * state should be.
+ * @return HAS_RUNNING_ACTIVITIES if any activity is not paused, stopped, or destroyed.
+ * HAS_PAUSED_ACTIVITIES if none are running and one is paused.
+ * HAS_STOPPED_ACTIVITIES if none are running/paused and one is stopped.
+ * HAS_DESTROYED_ACTIVITIES if none are running/paused/stopped.
+ */
+ private static int determineApplicationState() {
+ boolean hasPausedActivity = false;
+ boolean hasStoppedActivity = false;
+
+ for (ActivityInfo info : sActivityInfo.values()) {
+ int state = info.getStatus();
+ if (state != ActivityState.PAUSED
+ && state != ActivityState.STOPPED
+ && state != ActivityState.DESTROYED) {
+ return ApplicationState.HAS_RUNNING_ACTIVITIES;
+ } else if (state == ActivityState.PAUSED) {
+ hasPausedActivity = true;
+ } else if (state == ActivityState.STOPPED) {
+ hasStoppedActivity = true;
+ }
+ }
+
+ if (hasPausedActivity) return ApplicationState.HAS_PAUSED_ACTIVITIES;
+ if (hasStoppedActivity) return ApplicationState.HAS_STOPPED_ACTIVITIES;
+ return ApplicationState.HAS_DESTROYED_ACTIVITIES;
+ }
+
+ // Called to notify the native side of state changes.
+ // IMPORTANT: This is always called on the main thread!
+ private static native void nativeOnApplicationStateChange(int newState);
+}
diff --git a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
index 97b2ab4..c921dd9 100644
--- a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
+++ b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
@@ -4,17 +4,96 @@
package org.chromium.base;
+import android.app.Activity;
import android.app.Application;
+import android.os.Bundle;
+import android.view.Window;
/**
* Basic application functionality that should be shared among all browser applications.
*/
public class BaseChromiumApplication extends Application {
+ /**
+ * Interface to be implemented by listeners for window focus events.
+ */
+ public interface WindowFocusChangedListener {
+ /**
+ * Called when the window focus changes for {@code activity}.
+ * @param activity The {@link Activity} that has a window focus changed event.
+ * @param hasFocus Whether or not {@code activity} gained or lost focus.
+ */
+ public void onWindowFocusChanged(Activity activity, boolean hasFocus);
+ }
+
+ private ObserverList<WindowFocusChangedListener> sWindowFocusListeners =
+ new ObserverList<WindowFocusChangedListener>();
@Override
public void onCreate() {
super.onCreate();
- ActivityStatus.initialize(this);
+ ApplicationStatus.initialize(this);
+
+ registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
+ @Override
+ public void onActivityCreated(final Activity activity, Bundle savedInstanceState) {
+ Window.Callback callback = activity.getWindow().getCallback();
+ activity.getWindow().setCallback(new WindowCallbackWrapper(callback) {
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+
+ for (WindowFocusChangedListener listener : sWindowFocusListeners) {
+ listener.onWindowFocusChanged(activity, hasFocus);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
+ }
+
+ @Override
+ public void onActivityPaused(Activity activity) {
+ assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
+ }
+
+ @Override
+ public void onActivityResumed(Activity activity) {
+ assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
+ }
+
+ @Override
+ public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+ assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
+ }
+
+ @Override
+ public void onActivityStarted(Activity activity) {
+ assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
+ }
+
+ @Override
+ public void onActivityStopped(Activity activity) {
+ assert activity.getWindow().getCallback() instanceof WindowCallbackWrapper;
+ }
+ });
}
+ /**
+ * Registers a listener to receive window focus updates on activities in this application.
+ * @param listener Listener to receive window focus events.
+ */
+ public void registerWindowFocusChangedListener(WindowFocusChangedListener listener) {
+ sWindowFocusListeners.addObserver(listener);
+ }
+
+ /**
+ * Unregisters a listener from receiving window focus updates on activities in this application.
+ * @param listener Listener that doesn't want to receive window focus events.
+ */
+ public void unregisterWindowFocusChangedListener(WindowFocusChangedListener listener) {
+ sWindowFocusListeners.removeObserver(listener);
+ }
}
diff --git a/base/android/java/src/org/chromium/base/PowerMonitor.java b/base/android/java/src/org/chromium/base/PowerMonitor.java
index 3929398..b6d8cda 100644
--- a/base/android/java/src/org/chromium/base/PowerMonitor.java
+++ b/base/android/java/src/org/chromium/base/PowerMonitor.java
@@ -16,7 +16,7 @@ import android.os.Looper;
* Integrates native PowerMonitor with the java side.
*/
@JNINamespace("base::android")
-public class PowerMonitor implements ActivityStatus.StateListener {
+public class PowerMonitor implements ApplicationStatus.ApplicationStateListener {
private static final long SUSPEND_DELAY_MS = 1 * 60 * 1000; // 1 minute.
private static class LazyHolder {
private static final PowerMonitor INSTANCE = new PowerMonitor();
@@ -47,7 +47,7 @@ public class PowerMonitor implements ActivityStatus.StateListener {
public static void create(Context context) {
if (sInstance == null) {
sInstance = LazyHolder.INSTANCE;
- ActivityStatus.registerStateListener(sInstance);
+ ApplicationStatus.registerApplicationStateListener(sInstance);
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatusIntent = context.registerReceiver(null, ifilter);
onBatteryChargingChanged(batteryStatusIntent);
@@ -71,12 +71,12 @@ public class PowerMonitor implements ActivityStatus.StateListener {
}
@Override
- public void onActivityStateChange(int newState) {
- if (newState == ActivityStatus.RESUMED) {
+ public void onApplicationStateChange(int newState) {
+ if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) {
// Remove the callback from the message loop in case it hasn't been executed yet.
mHandler.removeCallbacks(sSuspendTask);
nativeOnMainActivityResumed();
- } else if (newState == ActivityStatus.PAUSED) {
+ } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) {
mHandler.postDelayed(sSuspendTask, SUSPEND_DELAY_MS);
}
}
diff --git a/base/android/java/src/org/chromium/base/WindowCallbackWrapper.java b/base/android/java/src/org/chromium/base/WindowCallbackWrapper.java
new file mode 100644
index 0000000..20b5c17
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/WindowCallbackWrapper.java
@@ -0,0 +1,134 @@
+// 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.base;
+
+import android.view.ActionMode;
+import android.view.ActionMode.Callback;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * A wrapper for a Window.Callback instance, allowing subclasses to listen to or override specific
+ * window messages.
+ */
+class WindowCallbackWrapper implements Window.Callback {
+ private final Window.Callback mCallback;
+
+ public WindowCallbackWrapper(Window.Callback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent event) {
+ return mCallback.dispatchGenericMotionEvent(event);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ return mCallback.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+ return mCallback.dispatchKeyShortcutEvent(event);
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ return mCallback.dispatchPopulateAccessibilityEvent(event);
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ return mCallback.dispatchTouchEvent(event);
+ }
+
+ @Override
+ public boolean dispatchTrackballEvent(MotionEvent event) {
+ return mCallback.dispatchTrackballEvent(event);
+ }
+
+ @Override
+ public void onActionModeFinished(ActionMode mode) {
+ mCallback.onActionModeFinished(mode);
+ }
+
+ @Override
+ public void onActionModeStarted(ActionMode mode) {
+ mCallback.onActionModeStarted(mode);
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ mCallback.onAttachedToWindow();
+ }
+
+ @Override
+ public void onContentChanged() {
+ mCallback.onContentChanged();
+ }
+
+ @Override
+ public boolean onCreatePanelMenu(int featureId, Menu menu) {
+ return mCallback.onCreatePanelMenu(featureId, menu);
+ }
+
+ @Override
+ public View onCreatePanelView(int featureId) {
+ return mCallback.onCreatePanelView(featureId);
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ mCallback.onDetachedFromWindow();
+ }
+
+ @Override
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {
+ return mCallback.onMenuItemSelected(featureId, item);
+ }
+
+ @Override
+ public boolean onMenuOpened(int featureId, Menu menu) {
+ return mCallback.onMenuOpened(featureId, menu);
+ }
+
+ @Override
+ public void onPanelClosed(int featureId, Menu menu) {
+ mCallback.onPanelClosed(featureId, menu);
+ }
+
+ @Override
+ public boolean onPreparePanel(int featureId, View view, Menu menu) {
+ return mCallback.onPreparePanel(featureId, view, menu);
+ }
+
+ @Override
+ public boolean onSearchRequested() {
+ return mCallback.onSearchRequested();
+ }
+
+ @Override
+ public void onWindowAttributesChanged(LayoutParams attrs) {
+ mCallback.onWindowAttributesChanged(attrs);
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ mCallback.onWindowFocusChanged(hasFocus);
+ }
+
+ @Override
+ public ActionMode onWindowStartingActionMode(Callback callback) {
+ return mCallback.onWindowStartingActionMode(callback);
+ }
+
+} \ No newline at end of file