1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129

base / android / application_status_listener.cc [blame]

// Copyright 2014 The Chromium Authors
// 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/functional/callback.h"
#include "base/lazy_instance.h"
#include "base/metrics/user_metrics.h"
#include "base/observer_list_threadsafe.h"
#include "base/trace_event/base_tracing.h"

#if BUILDFLAG(ENABLE_BASE_TRACING)
#include "base/trace_event/application_state_proto_android.h"  // no-presubmit-check
#endif  // BUILDFLAG(ENABLE_BASE_TRACING)

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "base/tasks_jni/ApplicationStatus_jni.h"

namespace base {
namespace android {

namespace {

class ApplicationStatusListenerImpl;

struct LeakyLazyObserverListTraits
    : base::internal::LeakyLazyInstanceTraits<
          ObserverListThreadSafe<ApplicationStatusListenerImpl>> {
  static ObserverListThreadSafe<ApplicationStatusListenerImpl>* New(
      void* instance) {
    ObserverListThreadSafe<ApplicationStatusListenerImpl>* ret =
        base::internal::LeakyLazyInstanceTraits<ObserverListThreadSafe<
            ApplicationStatusListenerImpl>>::New(instance);
    // Leaky.
    ret->AddRef();
    return ret;
  }
};

LazyInstance<ObserverListThreadSafe<ApplicationStatusListenerImpl>,
             LeakyLazyObserverListTraits>
    g_observers = LAZY_INSTANCE_INITIALIZER;

class ApplicationStatusListenerImpl : public ApplicationStatusListener {
 public:
  ApplicationStatusListenerImpl(
      const ApplicationStateChangeCallback& callback) {
    SetCallback(callback);
    g_observers.Get().AddObserver(this);

    Java_ApplicationStatus_registerThreadSafeNativeApplicationStateListener(
        AttachCurrentThread());
  }

  ~ApplicationStatusListenerImpl() override {
    g_observers.Get().RemoveObserver(this);
  }

  void SetCallback(const ApplicationStateChangeCallback& callback) override {
    DCHECK(!callback_);
    DCHECK(callback);
    callback_ = callback;
  }

  void Notify(ApplicationState state) override {
    if (callback_)
      callback_.Run(state);
  }

 private:
  ApplicationStateChangeCallback callback_;
};

}  // namespace

ApplicationStatusListener::ApplicationStatusListener() = default;
ApplicationStatusListener::~ApplicationStatusListener() = default;

// static
std::unique_ptr<ApplicationStatusListener> ApplicationStatusListener::New(
    const ApplicationStateChangeCallback& callback) {
  return std::make_unique<ApplicationStatusListenerImpl>(callback);
}

// static
void ApplicationStatusListener::NotifyApplicationStateChange(
    ApplicationState state) {
  TRACE_APPLICATION_STATE(state);
  switch (state) {
    case APPLICATION_STATE_UNKNOWN:
    case APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES:
      break;
    case APPLICATION_STATE_HAS_RUNNING_ACTIVITIES:
      RecordAction(UserMetricsAction("Android.LifeCycle.HasRunningActivities"));
      break;
    case APPLICATION_STATE_HAS_PAUSED_ACTIVITIES:
      RecordAction(UserMetricsAction("Android.LifeCycle.HasPausedActivities"));
      break;
    case APPLICATION_STATE_HAS_STOPPED_ACTIVITIES:
      RecordAction(UserMetricsAction("Android.LifeCycle.HasStoppedActivities"));
      break;
  }
  g_observers.Get().Notify(FROM_HERE, &ApplicationStatusListenerImpl::Notify,
                           state);
}

// static
ApplicationState ApplicationStatusListener::GetState() {
  return static_cast<ApplicationState>(
      Java_ApplicationStatus_getStateForApplication(AttachCurrentThread()));
}

static void JNI_ApplicationStatus_OnApplicationStateChange(
    JNIEnv* env,
    jint new_state) {
  ApplicationState application_state = static_cast<ApplicationState>(new_state);
  ApplicationStatusListener::NotifyApplicationStateChange(application_state);
}

// static
bool ApplicationStatusListener::HasVisibleActivities() {
  return Java_ApplicationStatus_hasVisibleActivities(AttachCurrentThread());
}

}  // namespace android
}  // namespace base