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 12 namespace { 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). 23 bool g_application_has_stopped = false; 24 25 void 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 40 struct 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 56 base::LazyInstance<base::android::ApplicationStatusListener, 57 LeakyApplicationStatusListenerTraits> 58 g_application_status_listener = LAZY_INSTANCE_INITIALIZER; 59 60 } // namespace 61 62 void ThreadWatcherAndroid::RegisterApplicationStatusListener() { 63 // Leaky. 64 g_application_status_listener.Get(); 65 } 66