1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/metrics/thread_watcher_android.h"
6
7#include "base/android/application_status_listener.h"
8#include "base/command_line.h"
9#include "base/lazy_instance.h"
10#include "chrome/browser/metrics/thread_watcher.h"
11
12namespace {
13
14// For most of the activities, the C++ side is initialized asynchronously
15// and the very first APPLICATION_STATE_HAS_RUNNING_ACTIVITIES is never received
16// whilst the ThreadWatcherList is initiated higher up in the stack.
17// However, some activities are initialized synchronously, and it'll receive
18// an APPLICATION_STATE_HAS_RUNNING_ACTIVITIES here as well.
19// Protect against this case, and only let
20// APPLICATION_STATE_HAS_RUNNING_ACTIVITIES turn on the
21// watchdog if it was previously handled by an
22// APPLICATION_STATE_HAS_STOPPED_ACTIVITIES (which is always handled here).
23bool g_application_has_stopped = false;
24
25void OnApplicationStateChange(
26    base::android::ApplicationState application_state) {
27  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
28  if (application_state ==
29      base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) {
30    g_application_has_stopped = true;
31    ThreadWatcherList::StopWatchingAll();
32  } else if (application_state ==
33             base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES &&
34             g_application_has_stopped) {
35    g_application_has_stopped = false;
36    ThreadWatcherList::StartWatchingAll(*CommandLine::ForCurrentProcess());
37  }
38}
39
40struct LeakyApplicationStatusListenerTraits {
41  static const bool kRegisterOnExit = false;
42#ifndef NDEBUG
43  static const bool kAllowedToAccessOnNonjoinableThread = true;
44#endif
45
46  static base::android::ApplicationStatusListener* New(void* instance) {
47    ANNOTATE_SCOPED_MEMORY_LEAK;
48    return new (instance) base::android::ApplicationStatusListener(
49            base::Bind(&OnApplicationStateChange));
50  }
51
52  static void Delete(base::android::ApplicationStatusListener* instance) {
53  }
54};
55
56base::LazyInstance<base::android::ApplicationStatusListener,
57                   LeakyApplicationStatusListenerTraits>
58    g_application_status_listener = LAZY_INSTANCE_INITIALIZER;
59
60}  // namespace
61
62void ThreadWatcherAndroid::RegisterApplicationStatusListener() {
63  // Leaky.
64  g_application_status_listener.Get();
65}
66