Media: enables MR2PS to update provider info

With this CL, MediaRoute2ProviderService can update its provider info
and publish its routes.

MediaRouter2Manager.Callback.onProviderUpdated(info) is alao added to
confirm whether correct provider info is sent.

Also, renamed the AIDLs such as
  IMediaRouter2ManagerClient -> IMediaRouter2Manager
  IMediaRoute2Callback -> IMediaRoute2ProviderClient

and changed on** to notify** in AIDLs.

Logics related to selecting/unselecting will be coverd by following CLs.

Test: atest mediaroutertest (after atest mediarouteprovider)

Change-Id: I5b119fbd0622a9422d3edf720b85e296ac4a5694
diff --git a/Android.bp b/Android.bp
index 65d16ac..18ac695 100644
--- a/Android.bp
+++ b/Android.bp
@@ -480,10 +480,10 @@
         "media/java/android/media/IMediaHTTPConnection.aidl",
         "media/java/android/media/IMediaHTTPService.aidl",
         "media/java/android/media/IMediaResourceMonitor.aidl",
-        "media/java/android/media/IMediaRoute2Callback.aidl",
         "media/java/android/media/IMediaRoute2Provider.aidl",
+        "media/java/android/media/IMediaRoute2ProviderClient.aidl",
         "media/java/android/media/IMediaRouterClient.aidl",
-        "media/java/android/media/IMediaRouter2ManagerClient.aidl",
+        "media/java/android/media/IMediaRouter2Manager.aidl",
         "media/java/android/media/IMediaRouterService.aidl",
         "media/java/android/media/IMediaScannerListener.aidl",
         "media/java/android/media/IMediaScannerService.aidl",
diff --git a/media/java/android/media/IMediaRoute2Provider.aidl b/media/java/android/media/IMediaRoute2Provider.aidl
index b97dcc5..b6fbf26 100644
--- a/media/java/android/media/IMediaRoute2Provider.aidl
+++ b/media/java/android/media/IMediaRoute2Provider.aidl
@@ -16,12 +16,12 @@
 
 package android.media;
 
-import android.media.IMediaRoute2Callback;
+import android.media.IMediaRoute2ProviderClient;
 
 /**
  * {@hide}
  */
 oneway interface IMediaRoute2Provider {
-    void setCallback(IMediaRoute2Callback callback);
+    void registerClient(IMediaRoute2ProviderClient client);
     void selectRoute(int uid, String id);
 }
diff --git a/media/java/android/media/IMediaRoute2Callback.aidl b/media/java/android/media/IMediaRoute2ProviderClient.aidl
similarity index 75%
copy from media/java/android/media/IMediaRoute2Callback.aidl
copy to media/java/android/media/IMediaRoute2ProviderClient.aidl
index f03c8ab..e849e19 100644
--- a/media/java/android/media/IMediaRoute2Callback.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderClient.aidl
@@ -16,9 +16,12 @@
 
 package android.media;
 
+import android.media.MediaRoute2ProviderInfo;
+
 /**
  * @hide
  */
-oneway interface IMediaRoute2Callback {
-    void onRouteSelected(int uid, String routeId);
+oneway interface IMediaRoute2ProviderClient {
+    void notifyRouteSelected(int uid, String routeId);
+    void notifyProviderInfoUpdated(in MediaRoute2ProviderInfo info);
 }
diff --git a/media/java/android/media/IMediaRouter2ManagerClient.aidl b/media/java/android/media/IMediaRouter2Manager.aidl
similarity index 69%
rename from media/java/android/media/IMediaRouter2ManagerClient.aidl
rename to media/java/android/media/IMediaRouter2Manager.aidl
index 234551b..950246a 100644
--- a/media/java/android/media/IMediaRouter2ManagerClient.aidl
+++ b/media/java/android/media/IMediaRouter2Manager.aidl
@@ -16,10 +16,13 @@
 
 package android.media;
 
+import android.media.MediaRoute2ProviderInfo;
+
 /**
  * {@hide}
  */
-oneway interface IMediaRouter2ManagerClient {
-    void onRouteSelected(int uid, String routeId);
-    void onControlCategoriesChanged(int uid, in List<String> categories);
+oneway interface IMediaRouter2Manager {
+    void notifyRouteSelected(int uid, String routeId);
+    void notifyControlCategoriesChanged(int uid, in List<String> categories);
+    void notifyProviderInfoUpdated(in MediaRoute2ProviderInfo info);
 }
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 59f1d0d..9e7bceb 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -17,7 +17,7 @@
 package android.media;
 
 import android.media.IMediaRouterClient;
-import android.media.IMediaRouter2ManagerClient;
+import android.media.IMediaRouter2Manager;
 import android.media.MediaRouterClientState;
 
 /**
@@ -36,9 +36,9 @@
     void requestSetVolume(IMediaRouterClient client, String routeId, int volume);
     void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction);
 
-    void registerManagerAsUser(IMediaRouter2ManagerClient callback,
+    void registerManagerAsUser(IMediaRouter2Manager manager,
             String packageName, int userId);
-    void unregisterManager(IMediaRouter2ManagerClient callback);
-    void setRemoteRoute(IMediaRouter2ManagerClient callback,
+    void unregisterManager(IMediaRouter2Manager manager);
+    void setRemoteRoute(IMediaRouter2Manager manager,
             int uid, String routeId, boolean explicit);
 }
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 9c8effb..f294b49 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -96,6 +96,16 @@
         dest.writeBundle(mExtras);
     }
 
+    @Override
+    public String toString() {
+        StringBuilder result = new StringBuilder()
+                .append("MediaRouteInfo{ ")
+                .append("id=").append(getId())
+                .append(", name=").append(getName())
+                .append(" }");
+        return result.toString();
+    }
+
     /**
      * Builder for {@link MediaRoute2Info media route info}.
      */
diff --git a/media/java/android/media/IMediaRoute2Callback.aidl b/media/java/android/media/MediaRoute2ProviderInfo.aidl
similarity index 85%
rename from media/java/android/media/IMediaRoute2Callback.aidl
rename to media/java/android/media/MediaRoute2ProviderInfo.aidl
index f03c8ab..4785877 100644
--- a/media/java/android/media/IMediaRoute2Callback.aidl
+++ b/media/java/android/media/MediaRoute2ProviderInfo.aidl
@@ -16,9 +16,4 @@
 
 package android.media;
 
-/**
- * @hide
- */
-oneway interface IMediaRoute2Callback {
-    void onRouteSelected(int uid, String routeId);
-}
+parcelable MediaRoute2ProviderInfo;
diff --git a/media/java/android/media/MediaRoute2ProviderInfo.java b/media/java/android/media/MediaRoute2ProviderInfo.java
index 51365a1..584eb83 100644
--- a/media/java/android/media/MediaRoute2ProviderInfo.java
+++ b/media/java/android/media/MediaRoute2ProviderInfo.java
@@ -22,6 +22,7 @@
 import android.os.Parcelable;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -72,6 +73,15 @@
         dest.writeTypedList(mRoutes);
     }
 
+    @Override
+    public String toString() {
+        StringBuilder result = new StringBuilder()
+                .append("MediaRouteProviderInfo { ")
+                .append("routes=").append(Arrays.toString(getRoutes().toArray()))
+                .append(" }");
+        return result.toString();
+    }
+
     /**
      * Builder for {@link MediaRoute2ProviderInfo media route provider info}.
      */
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 04ddc30..fcd90b2 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -36,7 +36,9 @@
 
     private final Handler mHandler;
     private ProviderStub mStub;
-    private IMediaRoute2Callback mCallback;
+    //TODO: Should allow multiple clients
+    private IMediaRoute2ProviderClient mClient;
+    private MediaRoute2ProviderInfo mProviderInfo;
 
     public MediaRoute2ProviderService() {
         mHandler = new Handler(Looper.getMainLooper());
@@ -70,10 +72,10 @@
      * @param routeId
      */
     public void updateProvider(int uid, String routeId) {
-        if (mCallback != null) {
+        if (mClient != null) {
             try {
                 //TODO: After publishState() is fully implemented, delete this.
-                mCallback.onRouteSelected(uid, routeId);
+                mClient.notifyRouteSelected(uid, routeId);
             } catch (RemoteException ex) {
                 Log.d(TAG, "Failed to update provider");
             }
@@ -81,22 +83,37 @@
         publishState();
     }
 
-    void setCallback(IMediaRoute2Callback callback) {
-        mCallback = callback;
+    /**
+     * Updates provider info and publish routes
+     */
+    public final void setProviderInfo(MediaRoute2ProviderInfo info) {
+        mProviderInfo = info;
+        publishState();
+    }
+
+    void registerClient(IMediaRoute2ProviderClient client) {
+        mClient = client;
         publishState();
     }
 
     void publishState() {
-        //TODO: Send provider descriptor to the MediaRouterService
+        if (mClient == null) {
+            return;
+        }
+        try {
+            mClient.notifyProviderInfoUpdated(mProviderInfo);
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Failed to send onProviderInfoUpdated");
+        }
     }
 
     final class ProviderStub extends IMediaRoute2Provider.Stub {
         ProviderStub() { }
 
         @Override
-        public void setCallback(IMediaRoute2Callback callback) {
-            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::setCallback,
-                    MediaRoute2ProviderService.this, callback));
+        public void registerClient(IMediaRoute2ProviderClient client) {
+            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::registerClient,
+                    MediaRoute2ProviderService.this, client));
         }
 
         @Override
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index ac5958e..9f72e1b 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -183,6 +183,13 @@
         }
     }
 
+    void notifyProviderUpdated(MediaRoute2ProviderInfo info) {
+        //TODO: should call back properly
+        for (CallbackRecord record : mCallbacks) {
+            record.mExecutor.execute(() -> record.mCallback.onProviderInfoUpdated(info));
+        }
+    }
+
     void notifyRouteSelected(int uid, String routeId) {
         for (CallbackRecord record : mCallbacks) {
             record.mExecutor.execute(() -> record.mCallback.onRouteSelected(uid, routeId));
@@ -213,6 +220,12 @@
          * @param categories the changed categories
          */
         public abstract void onControlCategoriesChanged(int uid, List<String> categories);
+
+        /**
+         * Called when the provider updates its information
+         * @param info the changed provider information
+         */
+        public void onProviderInfoUpdated(MediaRoute2ProviderInfo info) {}
     }
 
     final class CallbackRecord {
@@ -225,17 +238,23 @@
         }
     }
 
-    class Client extends IMediaRouter2ManagerClient.Stub {
+    class Client extends IMediaRouter2Manager.Stub {
         @Override
-        public void onRouteSelected(int uid, String routeId) {
+        public void notifyRouteSelected(int uid, String routeId) {
             mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyRouteSelected,
                     MediaRouter2Manager.this, uid, routeId));
         }
 
         @Override
-        public void onControlCategoriesChanged(int uid, List<String> categories) {
+        public void notifyControlCategoriesChanged(int uid, List<String> categories) {
             mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyControlCategoriesChanged,
                     MediaRouter2Manager.this, uid, categories));
         }
+
+        @Override
+        public void notifyProviderInfoUpdated(MediaRoute2ProviderInfo info) {
+            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyProviderUpdated,
+                    MediaRouter2Manager.this, info));
+        }
     }
 }
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index 22fbd85..c3c0c11 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -17,17 +17,50 @@
 package com.android.mediarouteprovider.example;
 
 import android.content.Intent;
+import android.media.MediaRoute2Info;
+import android.media.MediaRoute2ProviderInfo;
 import android.media.MediaRoute2ProviderService;
 import android.os.IBinder;
 
+import java.util.HashMap;
+import java.util.Map;
+
 public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService {
+    private static final String TAG = "SampleMediaRoute2Serv";
+
+    public static final String ROUTE_ID1 = "route_id";
+    public static final String ROUTE_NAME1 = "route_name";
+
+    Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
+
+    private void initializeRoutes() {
+        MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1)
+                .build();
+
+        mRoutes.put(route1.getId(), route1);
+    }
+
+    @Override
+    public void onCreate() {
+        initializeRoutes();
+    }
+
     @Override
     public IBinder onBind(Intent intent) {
+        publishRoutes();
         return super.onBind(intent);
     }
 
     @Override
     public void onSelect(int uid, String routeId) {
         updateProvider(uid, routeId);
+        publishRoutes();
+    }
+
+    void publishRoutes() {
+        MediaRoute2ProviderInfo info = new MediaRoute2ProviderInfo.Builder()
+                .addRoutes(mRoutes.values())
+                .build();
+        setProviderInfo(info);
     }
 }
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index a4bde65..a816b98 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -18,12 +18,14 @@
 
 import static org.mockito.Mockito.after;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.argThat;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.media.MediaRoute2ProviderInfo;
 import android.media.MediaRouter;
 import android.media.MediaRouter2Manager;
 import android.support.test.InstrumentationRegistry;
@@ -76,17 +78,15 @@
     }
 
     @Test
-    public void transferTest() throws Exception {
+    public void providerTest() {
         MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
 
         mManager.addCallback(mExecutor, mockCallback);
 
-        verify(mockCallback, after(AWAIT_MS).never())
-            .onRouteSelected(eq(TARGET_UID), any(String.class));
-
-        mManager.selectRoute(TARGET_UID, ROUTE_1);
-        verify(mockCallback, timeout(TIMEOUT_MS)).onRouteSelected(TARGET_UID, ROUTE_1);
-
+        //TODO: should be changed to onRouteAdded
+        verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
+                .onProviderInfoUpdated(argThat(
+                        (MediaRoute2ProviderInfo info) -> info.getRoutes().size() == 1));
         mManager.removeCallback(mockCallback);
     }
 
@@ -106,5 +106,4 @@
 
         mManager.removeCallback(mockCallback);
     }
-
 }
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index d284c60..ba9ff6a 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -20,8 +20,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.media.IMediaRoute2Callback;
 import android.media.IMediaRoute2Provider;
+import android.media.IMediaRoute2ProviderClient;
+import android.media.MediaRoute2ProviderInfo;
 import android.media.MediaRoute2ProviderService;
 import android.os.Handler;
 import android.os.IBinder;
@@ -48,9 +49,8 @@
 
     private Callback mCallback;
 
-    // Selected Route info
-    public int mSelectedUid;
-    public String mSelectedRouteId;
+    //TODO: make it nonnull
+    private MediaRoute2ProviderInfo mProviderInfo;
 
     // Connection state
     private boolean mRunning;
@@ -85,6 +85,10 @@
         }
     }
 
+    public MediaRoute2ProviderInfo getProviderInfo() {
+        return mProviderInfo;
+    }
+
     public boolean hasComponentName(String packageName, String className) {
         return mComponentName.getPackageName().equals(packageName)
                 && mComponentName.getClassName().equals(className);
@@ -223,15 +227,25 @@
     }
 
     private void onRouteSelected(Connection connection, int uid, String routeId) {
-        mSelectedUid = uid;
-        mSelectedRouteId = routeId;
-
-        if (mActiveConnection == connection) {
-            if (DEBUG) {
-                Slog.d(TAG, this + ": State changed ");
-            }
-            mHandler.post(mStateChanged);
+        if (mActiveConnection != connection) {
+            return;
         }
+
+        if (DEBUG) {
+            Slog.d(TAG, this + ": State changed ");
+        }
+        mHandler.post(mStateChanged);
+    }
+
+    private void onProviderInfoUpdated(Connection connection, MediaRoute2ProviderInfo info) {
+        if (mActiveConnection != connection) {
+            return;
+        }
+        mProviderInfo = info;
+        if (DEBUG) {
+            Slog.d(TAG, this + ": State changed ");
+        }
+        mHandler.post(mStateChanged);
     }
 
     private void disconnect() {
@@ -262,23 +276,18 @@
 
     private final class Connection implements DeathRecipient {
         private final IMediaRoute2Provider mProvider;
-        private final ProviderCallback mCallback;
+        private final ProviderClient mClient;
 
         Connection(IMediaRoute2Provider provider) {
             mProvider = provider;
-            mCallback = new ProviderCallback(this);
+            mClient = new ProviderClient(this);
         }
 
         public boolean register() {
             try {
                 mProvider.asBinder().linkToDeath(this, 0);
-                mProvider.setCallback(mCallback);
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        onConnectionReady(Connection.this);
-                    }
-                });
+                mProvider.registerClient(mClient);
+                mHandler.post((Runnable) () -> onConnectionReady(Connection.this));
                 return true;
             } catch (RemoteException ex) {
                 binderDied();
@@ -288,7 +297,7 @@
 
         public void dispose() {
             mProvider.asBinder().unlinkToDeath(this, 0);
-            mCallback.dispose();
+            mClient.dispose();
         }
 
         public void selectRoute(int uid, String id) {
@@ -301,29 +310,23 @@
 
         @Override
         public void binderDied() {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    onConnectionDied(Connection.this);
-                }
-            });
+            mHandler.post(() -> onConnectionDied(Connection.this));
         }
 
         void postRouteSelected(int uid, String routeId) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    onRouteSelected(Connection.this, uid, routeId);
-                }
-            });
+            mHandler.post(() -> onRouteSelected(Connection.this, uid, routeId));
+        }
+
+        void postProviderUpdated(MediaRoute2ProviderInfo info) {
+            mHandler.post(() -> onProviderInfoUpdated(Connection.this, info));
         }
     }
 
-    private static final class ProviderCallback extends IMediaRoute2Callback.Stub  {
+    private static final class ProviderClient extends IMediaRoute2ProviderClient.Stub  {
         private final WeakReference<Connection> mConnectionRef;
 
-        ProviderCallback(Connection connection) {
-            mConnectionRef = new WeakReference<Connection>(connection);
+        ProviderClient(Connection connection) {
+            mConnectionRef = new WeakReference<>(connection);
         }
 
         public void dispose() {
@@ -331,11 +334,19 @@
         }
 
         @Override
-        public void onRouteSelected(int uid, String routeId) throws RemoteException {
+        public void notifyRouteSelected(int uid, String routeId) throws RemoteException {
             Connection connection = mConnectionRef.get();
             if (connection != null) {
                 connection.postRouteSelected(uid, routeId);
             }
         }
+
+        @Override
+        public void notifyProviderInfoUpdated(MediaRoute2ProviderInfo info) {
+            Connection connection = mConnectionRef.get();
+            if (connection != null) {
+                connection.postProviderUpdated(info);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java b/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
index 08d8c58..194015d 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
@@ -120,7 +120,7 @@
                             mUserId);
                     provider.start();
                     mProviders.add(targetIndex++, provider);
-                    mCallback.addProvider(provider);
+                    mCallback.onAddProvider(provider);
                 } else if (sourceIndex >= targetIndex) {
                     MediaRoute2ProviderProxy provider = mProviders.get(sourceIndex);
                     provider.start(); // restart the provider if needed
@@ -134,7 +134,7 @@
         if (targetIndex < mProviders.size()) {
             for (int i = mProviders.size() - 1; i >= targetIndex; i--) {
                 MediaRoute2ProviderProxy provider = mProviders.get(i);
-                mCallback.removeProvider(provider);
+                mCallback.onRemoveProvider(provider);
                 mProviders.remove(provider);
                 provider.stop();
             }
@@ -170,7 +170,7 @@
     };
 
     public interface Callback {
-        void addProvider(MediaRoute2ProviderProxy provider);
-        void removeProvider(MediaRoute2ProviderProxy provider);
+        void onAddProvider(MediaRoute2ProviderProxy provider);
+        void onRemoveProvider(MediaRoute2ProviderProxy provider);
     }
 }
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 735df33..5d89a9d 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -18,8 +18,9 @@
 
 import android.app.ActivityManager;
 import android.content.Context;
-import android.media.IMediaRouter2ManagerClient;
+import android.media.IMediaRouter2Manager;
 import android.media.IMediaRouterClient;
+import android.media.MediaRoute2ProviderInfo;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -54,7 +55,7 @@
         mContext = context;
     }
 
-    public void registerManagerAsUser(IMediaRouter2ManagerClient client,
+    public void registerManagerAsUser(IMediaRouter2Manager client,
             String packageName, int userId) {
         if (client == null) {
             throw new IllegalArgumentException("client must not be null");
@@ -76,7 +77,7 @@
         }
     }
 
-    public void unregisterManager(IMediaRouter2ManagerClient client) {
+    public void unregisterManager(IMediaRouter2Manager client) {
         if (client == null) {
             throw new IllegalArgumentException("client must not be null");
         }
@@ -105,7 +106,7 @@
         }
     }
 
-    public void setRemoteRoute(IMediaRouter2ManagerClient client,
+    public void setRemoteRoute(IMediaRouter2Manager client,
             int uid, String routeId, boolean explicit) {
         final long token = Binder.clearCallingIdentity();
         try {
@@ -123,7 +124,7 @@
         }
     }
 
-    private void registerManagerLocked(IMediaRouter2ManagerClient client,
+    private void registerManagerLocked(IMediaRouter2Manager client,
             int uid, int pid, String packageName, int userId, boolean trusted) {
         final IBinder binder = client.asBinder();
         ManagerRecord managerRecord = mAllManagerRecords.get(binder);
@@ -149,11 +150,13 @@
             userRecord.mManagerRecords.add(managerRecord);
             mAllManagerRecords.put(binder, managerRecord);
 
-            //TODO: send client's info to manager
+            //TODO: remove this when it's unnecessary
+            // Sends published routes to newly added manager
+            userRecord.mHandler.scheduleUpdateManagerState();
         }
     }
 
-    private void unregisterManagerLocked(IMediaRouter2ManagerClient client, boolean died) {
+    private void unregisterManagerLocked(IMediaRouter2Manager client, boolean died) {
         ManagerRecord clientRecord = mAllManagerRecords.remove(client.asBinder());
         if (clientRecord != null) {
             UserRecord userRecord = clientRecord.mUserRecord;
@@ -163,7 +166,7 @@
         }
     }
 
-    private void setRemoteRouteLocked(IMediaRouter2ManagerClient client,
+    private void setRemoteRouteLocked(IMediaRouter2Manager client,
             int uid, String routeId, boolean explicit) {
         ManagerRecord managerRecord = mAllManagerRecords.get(client.asBinder());
         if (managerRecord != null) {
@@ -224,13 +227,13 @@
 
     final class ManagerRecord implements IBinder.DeathRecipient {
         public final UserRecord mUserRecord;
-        public final IMediaRouter2ManagerClient mClient;
+        public final IMediaRouter2Manager mClient;
         public final int mUid;
         public final int mPid;
         public final String mPackageName;
         public final boolean mTrusted;
 
-        ManagerRecord(UserRecord userRecord, IMediaRouter2ManagerClient client,
+        ManagerRecord(UserRecord userRecord, IMediaRouter2Manager client,
                 int uid, int pid, String packageName, boolean trusted) {
             mUserRecord = userRecord;
             mClient = client;
@@ -270,21 +273,20 @@
         public static final int MSG_START = 1;
         public static final int MSG_STOP = 2;
 
-        private static final int MSG_UPDATE_CLIENT_STATE = 8;
-
         private static final int MSG_SELECT_REMOTE_ROUTE = 10;
         private static final int MSG_UPDATE_CLIENT_USAGE = 11;
+        private static final int MSG_UPDATE_MANAGER_STATE = 12;
 
         private final WeakReference<MediaRouter2ServiceImpl> mServiceRef;
         private final UserRecord mUserRecord;
         private final MediaRoute2ProviderWatcher mWatcher;
-        private final ArrayList<IMediaRouter2ManagerClient> mTempManagers = new ArrayList<>();
+        private final ArrayList<IMediaRouter2Manager> mTempManagers = new ArrayList<>();
 
         private final ArrayList<MediaRoute2ProviderProxy> mMediaProviders =
                 new ArrayList<>();
 
         private boolean mRunning;
-        private boolean mClientStateUpdateScheduled;
+        private boolean mManagerStateUpdateScheduled;
 
         UserHandler(MediaRouter2ServiceImpl service, UserRecord userRecord) {
             mServiceRef = new WeakReference<>(service);
@@ -304,10 +306,6 @@
                     stop();
                     break;
                 }
-                case MSG_UPDATE_CLIENT_STATE: {
-                    updateClientState();
-                    break;
-                }
                 case MSG_SELECT_REMOTE_ROUTE: {
                     Pair<Integer, String> obj = (Pair<Integer, String>) msg.obj;
                     selectRemoteRoute(obj.first, obj.second);
@@ -317,6 +315,10 @@
                     updateClientUsage();
                     break;
                 }
+                case MSG_UPDATE_MANAGER_STATE: {
+                    updateManagerState();
+                    break;
+                }
             }
         }
 
@@ -336,13 +338,13 @@
         }
 
         @Override
-        public void addProvider(MediaRoute2ProviderProxy provider) {
+        public void onAddProvider(MediaRoute2ProviderProxy provider) {
             provider.setCallback(this);
             mMediaProviders.add(provider);
         }
 
         @Override
-        public void removeProvider(MediaRoute2ProviderProxy provider) {
+        public void onRemoveProvider(MediaRoute2ProviderProxy provider) {
             mMediaProviders.remove(provider);
         }
 
@@ -352,7 +354,7 @@
         }
 
         private void updateProvider(MediaRoute2ProviderProxy provider) {
-            scheduleUpdateClientState();
+            scheduleUpdateManagerState();
         }
 
 
@@ -367,15 +369,15 @@
             }
         }
 
-        private void scheduleUpdateClientState() {
-            if (!mClientStateUpdateScheduled) {
-                mClientStateUpdateScheduled = true;
-                sendEmptyMessage(MSG_UPDATE_CLIENT_STATE);
+        private void scheduleUpdateManagerState() {
+            if (!mManagerStateUpdateScheduled) {
+                mManagerStateUpdateScheduled = true;
+                sendEmptyMessage(MSG_UPDATE_MANAGER_STATE);
             }
         }
 
-        private void updateClientState() {
-            mClientStateUpdateScheduled = false;
+        private void updateManagerState() {
+            mManagerStateUpdateScheduled = false;
 
             MediaRouter2ServiceImpl service = mServiceRef.get();
             if (service == null) {
@@ -383,12 +385,12 @@
             }
 
             //TODO: send provider info
+            MediaRoute2ProviderInfo providerInfo = null;
             int selectedUid = 0;
             String selectedRouteId = null;
             final int mediaCount = mMediaProviders.size();
             for (int i = 0; i < mediaCount; i++) {
-                selectedUid = mMediaProviders.get(i).mSelectedUid;
-                selectedRouteId = mMediaProviders.get(i).mSelectedRouteId;
+                providerInfo = mMediaProviders.get(i).getProviderInfo();
             }
 
             try {
@@ -400,15 +402,19 @@
                 }
 
                 //TODO: Call proper callbacks when provider descriptor is implemented.
-                final int count = mTempManagers.size();
-                for (int i = 0; i < count; i++) {
-                    try {
-                        mTempManagers.get(i).onRouteSelected(selectedUid, selectedRouteId);
-                    } catch (RemoteException ex) {
-                        Slog.w(TAG, "Failed to call onStateChanged. Manager probably died.", ex);
+                if (providerInfo != null) {
+                    final int count = mTempManagers.size();
+                    for (int i = 0; i < count; i++) {
+                        try {
+                            mTempManagers.get(i).notifyProviderInfoUpdated(providerInfo);
+                        } catch (RemoteException ex) {
+                            Slog.w(TAG, "Failed to call onStateChanged. Manager probably died.",
+                                    ex);
+                        }
                     }
                 }
             } finally {
+                // Clear the list in preparation for the next time.
                 mTempManagers.clear();
             }
         }
@@ -416,7 +422,7 @@
         private void updateClientUsage() {
             //TODO: merge these code to updateClientState()
 
-//            List<IMediaRouter2ManagerClient> managers = new ArrayList<>();
+//            List<IMediaRouter2Manager> managers = new ArrayList<>();
 //            synchronized (mService.mLock) {
 //                final int count = mUserRecord.mManagerRecords.size();
 //                for (int i = 0; i < count; i++) {
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 05dae46..69d1255 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -30,7 +30,7 @@
 import android.media.AudioSystem;
 import android.media.IAudioRoutesObserver;
 import android.media.IAudioService;
-import android.media.IMediaRouter2ManagerClient;
+import android.media.IMediaRouter2Manager;
 import android.media.IMediaRouterClient;
 import android.media.IMediaRouterService;
 import android.media.MediaRouter;
@@ -416,7 +416,7 @@
 
     // Binder call
     @Override
-    public void registerManagerAsUser(IMediaRouter2ManagerClient client,
+    public void registerManagerAsUser(IMediaRouter2Manager client,
             String packageName, int userId) {
         final int uid = Binder.getCallingUid();
         if (!validatePackageName(uid, packageName)) {
@@ -427,13 +427,13 @@
 
     // Binder call
     @Override
-    public void unregisterManager(IMediaRouter2ManagerClient client) {
+    public void unregisterManager(IMediaRouter2Manager client) {
         mService2.unregisterManager(client);
     }
 
     // Binder call
     @Override
-    public void setRemoteRoute(IMediaRouter2ManagerClient client,
+    public void setRemoteRoute(IMediaRouter2Manager client,
             int uid, String routeId, boolean explicit) {
         mService2.setRemoteRoute(client, uid, routeId, explicit);
     }