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