Make party shuffle use the history too, making it less random, but more like
users expect.
http://b/2535828

Change-Id: I1fd71b578120a4e280074a6b27292b1383c0612a
diff --git a/src/com/android/music/MediaPlaybackService.java b/src/com/android/music/MediaPlaybackService.java
index e43af1f..e4432be 100644
--- a/src/com/android/music/MediaPlaybackService.java
+++ b/src/com/android/music/MediaPlaybackService.java
@@ -1198,19 +1198,19 @@
                 return;
             }
 
-            // Store the current file in the history, but keep the history at a
-            // reasonable size
-            if (mPlayPos >= 0) {
-                mHistory.add(Integer.valueOf(mPlayPos));
-            }
-            if (mHistory.size() > MAX_HISTORY_SIZE) {
-                mHistory.removeElementAt(0);
-            }
-
             if (mShuffleMode == SHUFFLE_NORMAL) {
                 // Pick random next track from the not-yet-played ones
                 // TODO: make it work right after adding/removing items in the queue.
 
+                // Store the current file in the history, but keep the history at a
+                // reasonable size
+                if (mPlayPos >= 0) {
+                    mHistory.add(mPlayPos);
+                }
+                if (mHistory.size() > MAX_HISTORY_SIZE) {
+                    mHistory.removeElementAt(0);
+                }
+
                 int numTracks = mPlayListLen;
                 int[] tracks = new int[numTracks];
                 for (int i=0;i < numTracks; i++) {
@@ -1325,6 +1325,7 @@
     // and no more than 10 items before.
     private void doAutoShuffleUpdate() {
         boolean notify = false;
+
         // remove old entries
         if (mPlayPos > 10) {
             removeTracks(0, mPlayPos - 9);
@@ -1334,10 +1335,22 @@
         int to_add = 7 - (mPlayListLen - (mPlayPos < 0 ? -1 : mPlayPos));
         for (int i = 0; i < to_add; i++) {
             // pick something at random from the list
-            int idx = mRand.nextInt(mAutoShuffleList.length);
-            long which = mAutoShuffleList[idx];
+
+            int lookback = mHistory.size();
+            int idx = -1;
+            while(true) {
+                idx = mRand.nextInt(mAutoShuffleList.length);
+                if (!wasRecentlyUsed(idx, lookback)) {
+                    break;
+                }
+                lookback /= 2;
+            }
+            mHistory.add(idx);
+            if (mHistory.size() > MAX_HISTORY_SIZE) {
+                mHistory.remove(0);
+            }
             ensurePlayListCapacity(mPlayListLen + 1);
-            mPlayList[mPlayListLen++] = which;
+            mPlayList[mPlayListLen++] = mAutoShuffleList[idx];
             notify = true;
         }
         if (notify) {
@@ -1345,6 +1358,30 @@
         }
     }
 
+    // check that the specified idx is not in the history (but only look at at
+    // most lookbacksize entries in the history)
+    private boolean wasRecentlyUsed(int idx, int lookbacksize) {
+
+        // early exit to prevent infinite loops in case idx == mPlayPos
+        if (lookbacksize == 0) {
+            return false;
+        }
+
+        int histsize = mHistory.size();
+        if (histsize < lookbacksize) {
+            Log.d(LOGTAG, "lookback too big");
+            lookbacksize = histsize;
+        }
+        int maxidx = histsize - 1;
+        for (int i = 0; i < lookbacksize; i++) {
+            long entry = mHistory.get(maxidx - i);
+            if (entry == idx) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     // A simple variation of Random that makes sure that the
     // value it returns is not equal to the value it returned
     // previously, unless the interval is 1.