Add interface for updating process state.

Called from activity manager to let the heap know when it should
perform compaction and trimming.
Bug: 8981901

Change-Id: Ib8ea48d2dc9d6901c3f2e0554391721d6691e726
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 5e62729..1e3689b 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -107,9 +107,8 @@
       activity_thread_(NULL),
       application_thread_(NULL),
       last_process_state_id_(NULL),
-      // Initially care about pauses in case we never get notified of process states, or if the JNI
-      // code becomes broken.
-      care_about_pause_times_(true),
+      // Initially assume we perceive jank in case the process state is never updated.
+      process_state_(kProcessStateJankPerceptible),
       concurrent_start_bytes_(concurrent_gc_ ? initial_size - kMinConcurrentRemainingBytes
           :  std::numeric_limits<size_t>::max()),
       total_bytes_freed_ever_(0),
@@ -325,6 +324,10 @@
   --gc_disable_count_;
 }
 
+void Heap::UpdateProcessState(ProcessState process_state) {
+  process_state_ = process_state;
+}
+
 void Heap::CreateThreadPool() {
   const size_t num_threads = std::max(parallel_gc_threads_, conc_gc_threads_);
   if (num_threads != 0) {
@@ -373,124 +376,6 @@
   thread_pool_.reset(nullptr);
 }
 
-static bool ReadStaticInt(JNIEnvExt* env, jclass clz, const char* name, int* out_value) {
-  DCHECK(out_value != NULL);
-  jfieldID field = env->GetStaticFieldID(clz, name, "I");
-  if (field == NULL) {
-    env->ExceptionClear();
-    return false;
-  }
-  *out_value = env->GetStaticIntField(clz, field);
-  return true;
-}
-
-void Heap::ListenForProcessStateChange() {
-  VLOG(heap) << "Heap notified of process state change";
-
-  Thread* self = Thread::Current();
-  JNIEnvExt* env = self->GetJniEnv();
-
-  if (!have_zygote_space_) {
-    return;
-  }
-
-  if (activity_thread_class_ == NULL) {
-    jclass clz = env->FindClass("android/app/ActivityThread");
-    if (clz == NULL) {
-      env->ExceptionClear();
-      LOG(WARNING) << "Could not find activity thread class in process state change";
-      return;
-    }
-    activity_thread_class_ = reinterpret_cast<jclass>(env->NewGlobalRef(clz));
-  }
-
-  if (activity_thread_class_ != NULL && activity_thread_ == NULL) {
-    jmethodID current_activity_method = env->GetStaticMethodID(activity_thread_class_,
-                                                               "currentActivityThread",
-                                                               "()Landroid/app/ActivityThread;");
-    if (current_activity_method == NULL) {
-      env->ExceptionClear();
-      LOG(WARNING) << "Could not get method for currentActivityThread";
-      return;
-    }
-
-    jobject obj = env->CallStaticObjectMethod(activity_thread_class_, current_activity_method);
-    if (obj == NULL) {
-      env->ExceptionClear();
-      LOG(WARNING) << "Could not get current activity";
-      return;
-    }
-    activity_thread_ = env->NewGlobalRef(obj);
-  }
-
-  if (process_state_cares_about_pause_time_.empty()) {
-    // Just attempt to do this the first time.
-    jclass clz = env->FindClass("android/app/ActivityManager");
-    if (clz == NULL) {
-      LOG(WARNING) << "Activity manager class is null";
-      return;
-    }
-    ScopedLocalRef<jclass> activity_manager(env, clz);
-    std::vector<const char*> care_about_pauses;
-    care_about_pauses.push_back("PROCESS_STATE_TOP");
-    care_about_pauses.push_back("PROCESS_STATE_IMPORTANT_BACKGROUND");
-    // Attempt to read the constants and classify them as whether or not we care about pause times.
-    for (size_t i = 0; i < care_about_pauses.size(); ++i) {
-      int process_state = 0;
-      if (ReadStaticInt(env, activity_manager.get(), care_about_pauses[i], &process_state)) {
-        process_state_cares_about_pause_time_.insert(process_state);
-        VLOG(heap) << "Adding process state " << process_state
-                   << " to set of states which care about pause time";
-      }
-    }
-  }
-
-  if (application_thread_class_ == NULL) {
-    jclass clz = env->FindClass("android/app/ActivityThread$ApplicationThread");
-    if (clz == NULL) {
-      env->ExceptionClear();
-      LOG(WARNING) << "Could not get application thread class";
-      return;
-    }
-    application_thread_class_ = reinterpret_cast<jclass>(env->NewGlobalRef(clz));
-    last_process_state_id_ = env->GetFieldID(application_thread_class_, "mLastProcessState", "I");
-    if (last_process_state_id_ == NULL) {
-      env->ExceptionClear();
-      LOG(WARNING) << "Could not get last process state member";
-      return;
-    }
-  }
-
-  if (application_thread_class_ != NULL && application_thread_ == NULL) {
-    jmethodID get_application_thread =
-        env->GetMethodID(activity_thread_class_, "getApplicationThread",
-                         "()Landroid/app/ActivityThread$ApplicationThread;");
-    if (get_application_thread == NULL) {
-      LOG(WARNING) << "Could not get method ID for get application thread";
-      return;
-    }
-
-    jobject obj = env->CallObjectMethod(activity_thread_, get_application_thread);
-    if (obj == NULL) {
-      LOG(WARNING) << "Could not get application thread";
-      return;
-    }
-
-    application_thread_ = env->NewGlobalRef(obj);
-  }
-
-  if (application_thread_ != NULL && last_process_state_id_ != NULL) {
-    int process_state = env->GetIntField(application_thread_, last_process_state_id_);
-    env->ExceptionClear();
-
-    care_about_pause_times_ = process_state_cares_about_pause_time_.find(process_state) !=
-        process_state_cares_about_pause_time_.end();
-
-    VLOG(heap) << "New process state " << process_state
-               << " care about pauses " << care_about_pause_times_;
-  }
-}
-
 void Heap::AddSpace(space::Space* space) {
   DCHECK(space != NULL);
   WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
@@ -1426,7 +1311,7 @@
   // Grow the heap so that we know when to perform the next GC.
   GrowForUtilization(gc_type, collector->GetDurationNs());
 
-  if (care_about_pause_times_) {
+  if (CareAboutPauseTimes()) {
     const size_t duration = collector->GetDurationNs();
     std::vector<uint64_t> pauses = collector->GetPauseTimes();
     // GC for alloc pauses the allocating thread, so consider it as a pause.
@@ -2143,10 +2028,9 @@
   }
 
   last_trim_time_ms_ = ms_time;
-  ListenForProcessStateChange();
 
   // Trim only if we do not currently care about pause times.
-  if (!care_about_pause_times_) {
+  if (!CareAboutPauseTimes()) {
     JNIEnv* env = self->GetJniEnv();
     DCHECK(WellKnownClasses::java_lang_Daemons != NULL);
     DCHECK(WellKnownClasses::java_lang_Daemons_requestHeapTrim != NULL);