MediaSession: Improve MediaSessionStack logic

There was an issue that media button events (play / pause) didn’t go
to the expected media session. If an app creates a media session during
all media sessions are paused, the next coming media play event is
consumed by the newly created media session. It makes sense in general,
but if the media session is created in a background process without any
visible UI, it causes unexpected results.

This patch resolves the issue by checking if a newly added session comes
from the most recent user-facing app.

Bug: 24990104
Change-Id: Ic9632bced37bffd28260afe3523d9a20ea4d3c21
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 611718e..61c320b 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -16,13 +16,17 @@
 
 package com.android.server.media;
 
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
 import android.media.session.MediaController.PlaybackInfo;
 import android.media.session.PlaybackState;
 import android.media.session.MediaSession;
+import android.os.RemoteException;
 import android.os.UserHandle;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Keeps track of media sessions and their priority for notifications, media
@@ -61,6 +65,36 @@
     private ArrayList<MediaSessionRecord> mCachedTransportControlList;
 
     /**
+     * Checks if a media session is created from the most recent app.
+     *
+     * @param record A media session record to be examined.
+     * @return true if the media session's package name equals to the most recent app, false
+     * otherwise.
+     */
+    private static boolean isFromMostRecentApp(MediaSessionRecord record) {
+        if (ActivityManager.getCurrentUser() != record.getUserId()) {
+            return false;
+        }
+        try {
+            List<ActivityManager.RecentTaskInfo> tasks =
+                    ActivityManagerNative.getDefault().getRecentTasks(1,
+                            ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
+                            ActivityManager.RECENT_IGNORE_UNAVAILABLE |
+                            ActivityManager.RECENT_INCLUDE_PROFILES |
+                            ActivityManager.RECENT_WITH_EXCLUDED, record.getUserId());
+            if (tasks != null && !tasks.isEmpty()) {
+                ActivityManager.RecentTaskInfo recentTask = tasks.get(0);
+                if (recentTask.baseIntent != null)
+                    return recentTask.baseIntent.getComponent().getPackageName()
+                            .equals(record.getPackageName());
+            }
+        } catch (RemoteException e) {
+            return false;
+        }
+        return false;
+    }
+
+    /**
      * Add a record to the priority tracker.
      *
      * @param record The record to add.
@@ -68,7 +102,9 @@
     public void addSession(MediaSessionRecord record) {
         mSessions.add(record);
         clearCache();
-        mLastInterestingRecord = record;
+        if (isFromMostRecentApp(record)) {
+            mLastInterestingRecord = record;
+        }
     }
 
     /**