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