Switch music player to live data for syncing state

Test: build and run the app
Change-Id: I2e7a1ce5663464e82b131f76dfe5b452336457c2
diff --git a/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/BaseActivity.java b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/BaseActivity.java
new file mode 100644
index 0000000..88b95e7
--- /dev/null
+++ b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/BaseActivity.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.sample.musicplayer;
+
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+
+import com.android.support.lifecycle.ActivityLifecycleDispatcher;
+import com.android.support.lifecycle.Lifecycle;
+import com.android.support.lifecycle.LifecycleProvider;
+
+/**
+ * Temporary base activity that acts as lifecycle provider.
+ */
+public abstract class BaseActivity extends AppCompatActivity implements LifecycleProvider {
+    private final ActivityLifecycleDispatcher mDispatcher = new ActivityLifecycleDispatcher(this,
+            this);
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mDispatcher.onCreate();
+    }
+    @Override
+    protected void onResume() {
+        mDispatcher.onResume();
+        super.onResume();
+    }
+    @Override
+    protected void onPause() {
+        mDispatcher.onPause();
+        super.onPause();
+    }
+    @Override
+    protected void onStop() {
+        mDispatcher.onStop();
+        super.onStop();
+    }
+    @Override
+    protected void onDestroy() {
+        mDispatcher.onDestroy();
+        super.onDestroy();
+    }
+    @Override
+    public Lifecycle getLifecycle() {
+        return mDispatcher.getLifecycle();
+    }
+}
diff --git a/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MainActivity.java b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MainActivity.java
index a1529f6..83b90cb 100644
--- a/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MainActivity.java
+++ b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MainActivity.java
@@ -15,62 +15,35 @@
  */
 package com.android.sample.musicplayer;
 
-import android.content.BroadcastReceiver;
-import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.os.Bundle;
+import android.support.annotation.Nullable;
 import android.support.design.widget.FloatingActionButton;
-import android.support.v4.content.LocalBroadcastManager;
-import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.Adapter;
 import android.support.v7.widget.Toolbar;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
 
 import com.android.sample.musicplayer.MusicRepository.TrackMetadata;
+import com.android.sample.musicplayer.adapter.MusicTrackListAdapter;
+import com.android.support.lifecycle.LiveData;
+import com.android.support.lifecycle.Observer;
 
 import java.util.List;
 
 /**
  * Our main activity.
  */
-public class MainActivity extends AppCompatActivity {
-    private MusicRepository mMusicRepository;
-
+public class MainActivity extends BaseActivity {
     private RecyclerView mRecyclerView;
 
-    static class CustomViewHolder extends RecyclerView.ViewHolder {
-        private ViewGroup mContainerView;
-        private TextView mIndexView;
-        private TextView mTextView;
-        private TextView mArtistView;
-
-        CustomViewHolder(View view) {
-            super(view);
-            this.mContainerView = (ViewGroup) view;
-            this.mIndexView = (TextView) view.findViewById(R.id.index);
-            this.mTextView = (TextView) view.findViewById(R.id.title);
-            this.mArtistView = (TextView) view.findViewById(R.id.artist);
-        }
-    }
-
-    private class ProgressReceiver extends BroadcastReceiver {
-        public void onReceive(Context context, Intent intent) {
-            updateFab();
-            if (mRecyclerView != null) {
-                mRecyclerView.getAdapter().notifyDataSetChanged();
-            }
-        }
-    }
+    private MusicTrackListAdapter mMusicTrackListAdapter;
+    private int mCurrPlaybackState;
 
     private void updateFab() {
         final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
-        switch (mMusicRepository.getState()) {
+        switch (mCurrPlaybackState) {
             case MusicRepository.STATE_PLAYING:
                 fab.setImageResource(R.drawable.ic_pause_white_36dp);
                 break;
@@ -88,20 +61,37 @@
         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
 
-        mMusicRepository = MusicRepository.getInstance();
+        MusicRepository musicRepository = MusicRepository.getInstance();
+        LiveData<Integer> currentlyActiveTrackData = musicRepository.getCurrentlyActiveTrackData();
+        currentlyActiveTrackData.observe(this, new Observer<Integer>() {
+            @Override
+            public void onChanged(@Nullable Integer integer) {
+                if (mMusicTrackListAdapter != null) {
+                    mMusicTrackListAdapter.setActiveTrackIndex(integer);
+                }
+            }
+        });
+        LiveData<Integer> stateData = musicRepository.getStateData();
+        stateData.observe(this, new Observer<Integer>() {
+            @Override
+            public void onChanged(@Nullable Integer integer) {
+                mCurrPlaybackState = integer;
+                updateFab();
+            }
+        });
 
         startService(new Intent(MusicService.ACTION_INITIALIZE)
                 .setPackage("com.android.sample.musicplayer"));
 
         final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
-
         updateFab();
 
         fab.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                switch (mMusicRepository.getState()) {
+                switch (mCurrPlaybackState) {
                     case MusicRepository.STATE_STOPPED:
+                    case MusicRepository.STATE_PAUSED:
                         startService(new Intent(MusicService.ACTION_PLAY).setPackage(
                                 "com.android.sample.musicplayer"));
                         break;
@@ -109,49 +99,16 @@
                         startService(new Intent(MusicService.ACTION_PAUSE).setPackage(
                                 "com.android.sample.musicplayer"));
                         break;
-                    case MusicRepository.STATE_PAUSED:
-                        startService(new Intent(MusicService.ACTION_PLAY).setPackage(
-                                "com.android.sample.musicplayer"));
-                        break;
-
                 }
             }
         });
 
-        // The filter's action is BROADCAST_ACTION
-        IntentFilter statusIntentFilter = new IntentFilter(MusicService.BROADCAST_ACTION);
-        // Instantiates a new progress receiver
-        ProgressReceiver progressReceiver = new ProgressReceiver();
-        // Registers the receiver and its intent filters
-        LocalBroadcastManager.getInstance(this).registerReceiver(
-                progressReceiver, statusIntentFilter);
-
         final LayoutInflater inflater = LayoutInflater.from(this);
 
         mRecyclerView = (RecyclerView) findViewById(R.id.recycler);
         final List<TrackMetadata> tracks = MusicRepository.getInstance().getTracks();
-        mRecyclerView.setAdapter(new Adapter<CustomViewHolder>() {
-
-            @Override
-            public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-                View inflated = inflater.inflate(R.layout.main_row, parent, false);
-                return new CustomViewHolder(inflated);
-            }
-
-            @Override
-            public void onBindViewHolder(CustomViewHolder holder, final int position) {
-                holder.mContainerView.setSelected(
-                        position == mMusicRepository.getCurrentlyActiveTrack());
-                holder.mIndexView.setText(Integer.toString(position + 1));
-                holder.mTextView.setText(tracks.get(position).getTitle());
-                holder.mArtistView.setText(tracks.get(position).getArtist());
-            }
-
-            @Override
-            public int getItemCount() {
-                return tracks.size();
-            }
-        });
+        mMusicTrackListAdapter = new MusicTrackListAdapter(inflater, tracks);
+        mRecyclerView.setAdapter(mMusicTrackListAdapter);
         mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
     }
 }
diff --git a/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MusicRepository.java b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MusicRepository.java
index cb6de7e..2ef3898 100644
--- a/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MusicRepository.java
+++ b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MusicRepository.java
@@ -17,6 +17,8 @@
 
 import android.support.annotation.RawRes;
 
+import com.android.support.lifecycle.LiveData;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -60,9 +62,8 @@
 
     private List<TrackMetadata> mTracks;
 
-    private int mCurrentlyActiveTrack = -1;
-
-    private int mState = STATE_STOPPED;
+    private LiveData<Integer> mCurrentlyActiveTrackData;
+    private LiveData<Integer> mStateData;
 
     /**
      * Gets the repository instance.
@@ -85,6 +86,12 @@
         mTracks.add(new TrackMetadata("Cheap Deals", "Skia", R.raw.track_07));
         mTracks.add(new TrackMetadata("Don't Stop the Drilling", "Dusty Oilfield", R.raw.track_08));
         mTracks.add(new TrackMetadata("Million Regressions", "Lady BreakBuild", R.raw.track_09));
+
+        mCurrentlyActiveTrackData = new LiveData<>();
+        mCurrentlyActiveTrackData.setValue(-1);
+
+        mStateData = new LiveData<>();
+        mStateData.setValue(STATE_STOPPED);
     }
 
     public List<TrackMetadata> getTracks() {
@@ -92,18 +99,26 @@
     }
 
     public int getCurrentlyActiveTrack() {
-        return mCurrentlyActiveTrack;
+        return mCurrentlyActiveTrackData.getValue();
     }
 
     public void setCurrentlyActiveTrack(int currentlyActiveTrack) {
-        mCurrentlyActiveTrack = currentlyActiveTrack;
+        mCurrentlyActiveTrackData.setValue(currentlyActiveTrack);
     }
 
     public int getState() {
-        return mState;
+        return mStateData.getValue();
     }
 
     public void setState(int state) {
-        mState = state;
+        mStateData.setValue(state);
+    }
+
+    public LiveData<Integer> getCurrentlyActiveTrackData() {
+        return this.mCurrentlyActiveTrackData;
+    }
+
+    public LiveData<Integer> getStateData() {
+        return mStateData;
     }
 }
diff --git a/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MusicService.java b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MusicService.java
index bc2bc27..d2c724f 100644
--- a/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MusicService.java
+++ b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/MusicService.java
@@ -28,7 +28,6 @@
 import android.os.PowerManager;
 import android.support.annotation.Nullable;
 import android.support.v4.app.NotificationManagerCompat;
-import android.support.v4.content.LocalBroadcastManager;
 import android.support.v4.media.MediaMetadataCompat;
 import android.support.v4.media.session.MediaSessionCompat;
 import android.support.v7.app.NotificationCompat;
@@ -50,8 +49,6 @@
     public static final String ACTION_NEXT = "com.android.sample.musicplayer.action.NEXT";
     public static final String ACTION_PREV = "com.android.sample.musicplayer.action.PREV";
 
-    public static final String BROADCAST_ACTION = "com.android.sample.musicplayer.status.REPORT";
-
     private static final String RESOURCE_PREFIX =
             "android.resource://com.android.sample.musicplayer/";
 
@@ -168,7 +165,6 @@
 
     private void processInitializeRequest() {
         if (mMusicRepository.getCurrentlyActiveTrack() >= 0) {
-            sendBroadcast();
             return;
         }
         mMusicRepository.setCurrentlyActiveTrack(-1);
@@ -197,8 +193,6 @@
             updateNotification();
             //relaxResources(false); // while paused, we always retain the MediaPlayer
             // do not give up audio focus
-
-            sendBroadcast();
         }
     }
 
@@ -215,8 +209,6 @@
             relaxResources(true);
             // service is no longer necessary. Will be started again if needed.
             stopSelf();
-
-            sendBroadcast();
         }
     }
 
@@ -236,11 +228,6 @@
         }
     }
 
-    private void sendBroadcast() {
-        Intent localIntent = new Intent(BROADCAST_ACTION);
-        LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
-    }
-
     /**
      * Releases resources used by the service for playback. This includes the "foreground service"
      * status and notification, the wake locks and possibly the MediaPlayer.
@@ -271,7 +258,6 @@
         if (!mMediaPlayer.isPlaying()) {
             mMediaPlayer.start();
         }
-        sendBroadcast();
     }
 
     /**
@@ -393,6 +379,8 @@
     }
 
     private void updateNotification() {
+        // TODO - once b/33690035 is fixed, convert to have the service observe the LiveData
+        // object in our repository for the currently active track and update the notification.
         TrackMetadata currTrack = mTracks.get(mMusicRepository.getCurrentlyActiveTrack());
         populateNotificationBuilderContent(currTrack.getTitle()
                 + " by " + currTrack.getArtist());
diff --git a/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/adapter/MusicTrackListAdapter.java b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/adapter/MusicTrackListAdapter.java
new file mode 100644
index 0000000..de91560
--- /dev/null
+++ b/samples-flatfoot/MusicPlayer/app/src/main/java/com/android/sample/musicplayer/adapter/MusicTrackListAdapter.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.sample.musicplayer.adapter;
+
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.Adapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.android.sample.musicplayer.MusicRepository.TrackMetadata;
+import com.android.sample.musicplayer.R;
+
+import java.util.List;
+
+/**
+ * Adapter for the list of music tracks.
+ */
+public class MusicTrackListAdapter extends Adapter<MusicTrackListAdapter.CustomViewHolder> {
+    private final LayoutInflater mInflater;
+    private List<TrackMetadata> mTracks;
+    private int mActiveTrackIndex;
+
+    class CustomViewHolder extends RecyclerView.ViewHolder {
+        private ViewGroup mContainerView;
+        private TextView mIndexView;
+        private TextView mTextView;
+        private TextView mArtistView;
+
+        CustomViewHolder(View view) {
+            super(view);
+            this.mContainerView = (ViewGroup) view;
+            this.mIndexView = (TextView) view.findViewById(R.id.index);
+            this.mTextView = (TextView) view.findViewById(R.id.title);
+            this.mArtistView = (TextView) view.findViewById(R.id.artist);
+        }
+    }
+
+    public MusicTrackListAdapter(LayoutInflater inflater, List<TrackMetadata> tracks) {
+        mInflater = inflater;
+        mTracks = tracks;
+    }
+
+    @Override
+    public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        View inflated = mInflater.inflate(R.layout.main_row, parent, false);
+        return new CustomViewHolder(inflated);
+    }
+
+    @Override
+    public void onBindViewHolder(CustomViewHolder holder, final int position) {
+        holder.mContainerView.setSelected(position == mActiveTrackIndex);
+        holder.mIndexView.setText(Integer.toString(position + 1));
+        holder.mTextView.setText(mTracks.get(position).getTitle());
+        holder.mArtistView.setText(mTracks.get(position).getArtist());
+    }
+
+    @Override
+    public int getItemCount() {
+        return mTracks.size();
+    }
+
+    public void setActiveTrackIndex(int activeTrackIndex) {
+        if (mActiveTrackIndex != activeTrackIndex) {
+            mActiveTrackIndex = activeTrackIndex;
+            notifyDataSetChanged();
+        }
+    }
+}
diff --git a/samples-flatfoot/MusicPlayer/build.gradle b/samples-flatfoot/MusicPlayer/build.gradle
index 7bf44de..5d6aefc 100644
--- a/samples-flatfoot/MusicPlayer/build.gradle
+++ b/samples-flatfoot/MusicPlayer/build.gradle
@@ -19,10 +19,10 @@
     repositories {
         jcenter()
         maven {
-            url "file://Volumes/android/ub-supportlib-flatfoot-master/out/host/gradle/frameworks/support/build/flatfoot_repo/"
+            url "file://Volumes/android/appToolkitRepository/"
         }
         maven {
-            url "file://Volumes/android/ub-supportlib-flatfoot-master/prebuilts/fullsdk-darwin/extras/android/m2repository/"
+            url "file://Volumes/android/m2repository/"
         }
     }
 }