MediaRouteProviderService.java revision 129abf73ce9be1bc172b945263c7975ad1a3006f
1fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown/*
2fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Copyright (C) 2013 The Android Open Source Project
3fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *
4fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * you may not use this file except in compliance with the License.
6fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * You may obtain a copy of the License at
7fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *
8fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *
10fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Unless required by applicable law or agreed to in writing, software
11fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * See the License for the specific language governing permissions and
14fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * limitations under the License.
15fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */
16fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
17b507e525a61ed761eecfc2eaaf19af7e8db5dca5Jeff Brownpackage android.support.v7.media;
18fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
19fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.app.Service;
20fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.Intent;
21fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.Handler;
22fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.IBinder;
23fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.IBinder.DeathRecipient;
24fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.Bundle;
25fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.DeadObjectException;
26fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.Message;
27fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.Messenger;
28fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.RemoteException;
29b507e525a61ed761eecfc2eaaf19af7e8db5dca5Jeff Brownimport android.support.v7.media.MediaRouteProvider.ProviderDescriptor;
30fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.util.Log;
31fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.util.SparseArray;
32fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
33fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport java.lang.ref.WeakReference;
34fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport java.util.ArrayList;
35fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
36fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown/**
37fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Base class for media route provider services.
38fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p>
39fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * To implement your own media route provider service, extend this class and
40fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * override the {@link #onCreateMediaRouteProvider} method to return an
41fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * instance of your {@link MediaRouteProvider}.
42fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p>
43fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Declare your media route provider service in your application manifest
44fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * like this:
45fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p>
46fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <pre>
47fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *   &lt;service android:name=".MyMediaRouteProviderService"
48fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *           android:label="@string/my_media_route_provider_service">
49fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *       &lt;intent-filter>
50fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *           &lt;action android:name="android.media.MediaRouteProviderService" />
51fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *       &lt;/intent-filter>
52fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown *   &lt;/service>
53fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </pre>
54fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */
55fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownpublic abstract class MediaRouteProviderService extends Service {
56fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private static final String TAG = "MediaRouteProviderService";
57fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private static final boolean DEBUG = true;
58fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
59fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private final ArrayList<ClientRecord> mClients = new ArrayList<ClientRecord>();
60fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private final ReceiveHandler mReceiveHandler;
61fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private final Messenger mReceiveMessenger;
62fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private final PrivateHandler mPrivateHandler;
63fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private final ProviderCallback mProviderCallback;
64fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
65fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private MediaRouteProvider mProvider;
66fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
67fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /**
68fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * The {@link Intent} that must be declared as handled by the service.
69fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Put this in your manifest.
70fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
71fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    public static final String SERVICE_INTERFACE =
72fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            "android.media.MediaRouteProviderService";
73fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
74fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /*
75fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Messages sent from the client to the service.
76fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * DO NOT RENUMBER THESE!
77fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
78fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
79fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (client v1)
80fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Register client.
81fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - replyTo : client messenger
82fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
83fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : client version
84fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
85fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_MSG_REGISTER = 1;
86fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
87fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (client v1)
88fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Unregister client.
89fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - replyTo : client messenger
90fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
91fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
92fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_MSG_UNREGISTER = 2;
93fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
94fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (client v1)
95fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Create route controller.
96fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - replyTo : client messenger
97fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
98fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : route controller id
99fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - CLIENT_DATA_ROUTE_ID : route id string
100fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
101fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_MSG_CREATE_ROUTE_CONTROLLER = 3;
102fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
103fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (client v1)
104fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Release route controller.
105fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - replyTo : client messenger
106fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
107fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : route controller id
108fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
109fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_MSG_RELEASE_ROUTE_CONTROLLER = 4;
110fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
111fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (client v1)
112fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Select route.
113fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - replyTo : client messenger
114fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
115fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : route controller id
116fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
117fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_MSG_SELECT_ROUTE = 5;
118fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
119fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (client v1)
120fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Unselect route.
121fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - replyTo : client messenger
122fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
123fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : route controller id
124fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
125fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_MSG_UNSELECT_ROUTE = 6;
126fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
127fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (client v1)
128fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Set route volume.
129fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - replyTo : client messenger
130fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
131fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : route controller id
132fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - CLIENT_DATA_VOLUME : volume integer
133fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
134fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_MSG_SET_ROUTE_VOLUME = 7;
135fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
136fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (client v1)
137fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Update route volume.
138fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - replyTo : client messenger
139fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
140fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : route controller id
141fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - CLIENT_DATA_VOLUME : volume delta integer
142fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
143fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_MSG_UPDATE_ROUTE_VOLUME = 8;
144fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
145fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (client v1)
146fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Route control request.
147fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - replyTo : client messenger
148fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
149fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : route controller id
150fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - obj     : media control intent
151fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
152fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_MSG_ROUTE_CONTROL_REQUEST = 9;
153fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
154fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final String CLIENT_DATA_ROUTE_ID = "routeId";
155fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final String CLIENT_DATA_VOLUME = "volume";
156fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
157fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /*
158fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Messages sent from the service to the client.
159fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * DO NOT RENUMBER THESE!
160fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
161fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
162fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (service v1)
163fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Generic failure sent in response to any unrecognized or malformed request.
164fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
165fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
166fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int SERVICE_MSG_GENERIC_FAILURE = 0;
167fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
168fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (service v1)
169fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Generic failure sent in response to a successful message.
170fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
171fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
172fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int SERVICE_MSG_GENERIC_SUCCESS = 1;
173fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
174fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (service v1)
175fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Registration succeeded.
176fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
177fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : server version
178fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - obj     : route provider descriptor bundle, or null
179fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
180fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int SERVICE_MSG_REGISTERED = 2;
181fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
182fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (service v1)
183fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Route control request result.
184fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : request id
185fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg2    : result code
186fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - obj     : result data bundle, or null
187fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
188fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int SERVICE_MSG_CONTROL_RESULT = 3;
189fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
190fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /** (service v1)
191fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Route provider descriptor changed.  (unsolicited event)
192fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - arg1    : reserved (0)
193fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * - obj     : route provider descriptor bundle, or null
194fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
195fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int SERVICE_MSG_DESCRIPTOR_CHANGED = 4;
196fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
197fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /*
198fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Recognized client version numbers.  (Reserved for future use.)
199fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * DO NOT RENUMBER THESE!
200fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
201fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
202fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_VERSION_1 = 1;
203fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int CLIENT_VERSION_CURRENT = CLIENT_VERSION_1;
204fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
205fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /*
206fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Recognized server version numbers.  (Reserved for future use.)
207fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * DO NOT RENUMBER THESE!
208fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
209fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
210fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int SERVICE_VERSION_1 = 1;
211fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static final int SERVICE_VERSION_CURRENT = SERVICE_VERSION_1;
212fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
213fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /*
214fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Private messages used internally.  (Yes, you can renumber these.)
215fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
216fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
217fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private static final int PRIVATE_MSG_CLIENT_DIED = 1;
218fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
219fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /**
220fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Creates a media route provider service.
221fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
222fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    public MediaRouteProviderService() {
223fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        mReceiveHandler = new ReceiveHandler(this);
224fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        mReceiveMessenger = new Messenger(mReceiveHandler);
225fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        mPrivateHandler = new PrivateHandler();
226fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        mProviderCallback = new ProviderCallback();
227fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
228fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
229fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /**
230fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Called by the system when it is time to create the media route provider.
231fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     *
232fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * @return The media route provider offered by this service, or null if
233fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * this service has decided not to offer a media route provider.
234fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
235fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    public abstract MediaRouteProvider onCreateMediaRouteProvider();
236fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
237fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /**
238fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Gets the media route provider offered by this service.
239fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     *
240fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * @return The media route provider offered by this service, or null if
241fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * it has not yet been created.
242fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     *
243fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * @see #onCreateMediaRouteProvider()
244fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
245fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    public MediaRouteProvider getMediaRouteProvider() {
246fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return mProvider;
247fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
248fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
249fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    @Override
250fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    public IBinder onBind(Intent intent) {
251fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (intent.getAction().equals(SERVICE_INTERFACE)) {
252fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (mProvider == null) {
253fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                MediaRouteProvider provider = onCreateMediaRouteProvider();
254fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (provider != null) {
255fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    String providerPackage = provider.getMetadata().getPackageName();
256fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    if (!providerPackage.equals(getPackageName())) {
257fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        throw new IllegalStateException("onCreateMediaRouteProvider() returned "
258fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                + "a provider whose package name does not match the package "
259fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                + "name of the service.  A media route provider service can "
260fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                + "only export its own media route providers.  "
261fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                + "Provider package name: " + providerPackage
262fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                + ".  Service package name: " + getPackageName() + ".");
263fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    }
264350ba6e4a1b5ec28721a098e50eaf6a508eb28f0Jeff Brown                    mProvider = provider;
265350ba6e4a1b5ec28721a098e50eaf6a508eb28f0Jeff Brown                    mProvider.addCallback(mProviderCallback);
266fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
267fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
268fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (mProvider != null) {
269fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return mReceiveMessenger.getBinder();
270fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
271fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
272fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return null;
273fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
274fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
275fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private boolean onRegisterClient(Messenger messenger, int requestId, int version) {
276fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (version >= CLIENT_VERSION_1) {
277fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            int index = findClient(messenger);
278fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (index < 0) {
279fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                ClientRecord client = new ClientRecord(messenger, version);
280fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (client.register()) {
281fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    mClients.add(client);
282fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    if (DEBUG) {
283fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        Log.d(TAG, client + ": Registered, version=" + version);
284fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    }
285fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    if (requestId != 0) {
286fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        ProviderDescriptor descriptor = mProvider.getDescriptor();
287fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        sendReply(messenger, SERVICE_MSG_REGISTERED,
288fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                requestId, SERVICE_VERSION_CURRENT,
289fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                descriptor != null ? descriptor.asBundle() : null, null);
290fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    }
291fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    return true;
292fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
293fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
294fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
295fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return false;
296fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
297fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
298fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private boolean onUnregisterClient(Messenger messenger, int requestId) {
299fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        int index = findClient(messenger);
300fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (index >= 0) {
301fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            ClientRecord client = mClients.remove(index);
302fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (DEBUG) {
303fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                Log.d(TAG, client + ": Unregistered");
304fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
305fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            client.dispose();
306fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            sendGenericSuccess(messenger, requestId);
307fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return true;
308fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
309fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return false;
310fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
311fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
312fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private void onBinderDied(Messenger messenger) {
313fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        int index = findClient(messenger);
314fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (index >= 0) {
315fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            ClientRecord client = mClients.remove(index);
316fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (DEBUG) {
317fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                Log.d(TAG, client + ": Binder died");
318fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
319fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            client.dispose();
320fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
321fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
322fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
323fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private boolean onCreateRouteController(Messenger messenger, int requestId,
324fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            int controllerId, String routeId) {
325fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        ClientRecord client = getClient(messenger);
326fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (client != null) {
327fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (client.createRouteController(routeId, controllerId)) {
328fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (DEBUG) {
329fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    Log.d(TAG, client + ": Route controller created"
330fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            + ", controllerId=" + controllerId + ", routeId=" + routeId);
331fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
332fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                sendGenericSuccess(messenger, requestId);
333fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return true;
334fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
335fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
336fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return false;
337fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
338fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
339fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private boolean onReleaseRouteController(Messenger messenger, int requestId,
340fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            int controllerId) {
341fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        ClientRecord client = getClient(messenger);
342fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (client != null) {
343fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (client.releaseRouteController(controllerId)) {
344fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (DEBUG) {
345fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    Log.d(TAG, client + ": Route controller released"
346fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            + ", controllerId=" + controllerId);
347fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
348fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                sendGenericSuccess(messenger, requestId);
349fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return true;
350fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
351fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
352fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return false;
353fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
354fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
355fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private boolean onSelectRoute(Messenger messenger, int requestId,
356fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            int controllerId) {
357fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        ClientRecord client = getClient(messenger);
358fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (client != null) {
359fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            MediaRouteProvider.RouteController controller =
360fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    client.getRouteController(controllerId);
361fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (controller != null) {
362129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown                controller.onSelect();
363fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (DEBUG) {
364fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    Log.d(TAG, client + ": Route selected"
365fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            + ", controllerId=" + controllerId);
366fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
367fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                sendGenericSuccess(messenger, requestId);
368fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return true;
369fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
370fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
371fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return false;
372fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
373fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
374fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private boolean onUnselectRoute(Messenger messenger, int requestId,
375fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            int controllerId) {
376fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        ClientRecord client = getClient(messenger);
377fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (client != null) {
378fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            MediaRouteProvider.RouteController controller =
379fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    client.getRouteController(controllerId);
380fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (controller != null) {
381129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown                controller.onUnselect();
382fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (DEBUG) {
383fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    Log.d(TAG, client + ": Route unselected"
384fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            + ", controllerId=" + controllerId);
385fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
386fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                sendGenericSuccess(messenger, requestId);
387fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return true;
388fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
389fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
390fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return false;
391fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
392fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
393fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private boolean onSetRouteVolume(Messenger messenger, int requestId,
394fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            int controllerId, int volume) {
395fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        ClientRecord client = getClient(messenger);
396fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (client != null) {
397fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            MediaRouteProvider.RouteController controller =
398fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    client.getRouteController(controllerId);
399fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (controller != null) {
400129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown                controller.onSetVolume(volume);
401fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (DEBUG) {
402fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    Log.d(TAG, client + ": Route volume changed"
403fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            + ", controllerId=" + controllerId + ", volume=" + volume);
404fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
405fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                sendGenericSuccess(messenger, requestId);
406fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return true;
407fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
408fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
409fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return false;
410fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
411fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
412fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private boolean onUpdateRouteVolume(Messenger messenger, int requestId,
413fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            int controllerId, int delta) {
414fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        ClientRecord client = getClient(messenger);
415fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (client != null) {
416fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            MediaRouteProvider.RouteController controller =
417fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    client.getRouteController(controllerId);
418fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (controller != null) {
419129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown                controller.onUpdateVolume(delta);
420fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (DEBUG) {
421fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    Log.d(TAG, client + ": Route volume updated"
422fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            + ", controllerId=" + controllerId + ", delta=" + delta);
423fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
424fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                sendGenericSuccess(messenger, requestId);
425fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return true;
426fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
427fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
428fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return false;
429fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
430fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
431fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private boolean onRouteControlRequest(final Messenger messenger, final int requestId,
432fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            final int controllerId, final Intent intent) {
433fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        final ClientRecord client = getClient(messenger);
434fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (client != null) {
435fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            MediaRouteProvider.RouteController controller =
436fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    client.getRouteController(controllerId);
437fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (controller != null) {
438fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                MediaRouter.ControlRequestCallback callback = null;
439fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (requestId != 0) {
440fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    callback = new MediaRouter.ControlRequestCallback() {
441fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        @Override
442fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        public void onResult(int result, Bundle data) {
443fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            if (DEBUG) {
444fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                Log.d(TAG, client + ": Route control request finished"
445fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                        + ", controllerId=" + controllerId
446fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                        + ", intent=" + intent
447fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                        + ", result=" + result + ", data=" + data);
448fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            }
449fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            if (findClient(messenger) >= 0) {
450fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                sendReply(messenger, SERVICE_MSG_CONTROL_RESULT,
451fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                        requestId, result, data, null);
452fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            }
453fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        }
454fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    };
455fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
456129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown                if (controller.onControlRequest(intent, callback)) {
457fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    if (DEBUG) {
458fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        Log.d(TAG, client + ": Route control request delivered"
459fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                + ", controllerId=" + controllerId + ", intent=" + intent);
460fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    }
461fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    return true;
462fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
463fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
464fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
465fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return false;
466fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
467fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
468fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private void sendDescriptorChanged(MediaRouteProvider.ProviderDescriptor descriptor) {
469fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        Bundle descriptorBundle = descriptor != null ? descriptor.asBundle() : null;
470fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        final int count = mClients.size();
471fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        for (int i = 0; i < count; i++) {
472fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            ClientRecord client = mClients.get(i);
473fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            sendReply(client.mMessenger, SERVICE_MSG_DESCRIPTOR_CHANGED, 0, 0,
474fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    descriptorBundle, null);
475fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (DEBUG) {
476fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                Log.d(TAG, client + ": Sent descriptor change event, descriptor=" + descriptor);
477fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
478fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
479fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
480fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
481fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private ClientRecord getClient(Messenger messenger) {
482fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        int index = findClient(messenger);
483fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return index >= 0 ? mClients.get(index) : null;
484fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
485fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
486fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private int findClient(Messenger messenger) {
487fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        final int count = mClients.size();
488fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        for (int i = 0; i < count; i++) {
489fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            ClientRecord client = mClients.get(i);
490fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (client.hasMessenger(messenger)) {
491fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return i;
492fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
493fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
494fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return -1;
495fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
496fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
497fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private static void sendGenericFailure(Messenger messenger, int requestId) {
498fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (requestId != 0) {
499fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            sendReply(messenger, SERVICE_MSG_GENERIC_FAILURE, requestId, 0, null, null);
500fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
501fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
502fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
503fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private static void sendGenericSuccess(Messenger messenger, int requestId) {
504fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        if (requestId != 0) {
505fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            sendReply(messenger, SERVICE_MSG_GENERIC_SUCCESS, requestId, 0, null, null);
506fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
507fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
508fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
509fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private static void sendReply(Messenger messenger, int what,
510fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            int requestId, int arg, Object obj, Bundle data) {
511fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        Message msg = Message.obtain();
512fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        msg.what = what;
513fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        msg.arg1 = requestId;
514fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        msg.arg2 = arg;
515fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        msg.obj = obj;
516fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        msg.setData(data);
517fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        try {
518fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            messenger.send(msg);
519fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        } catch (DeadObjectException ex) {
520fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            // The client died.
521fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        } catch (RemoteException ex) {
522fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            Log.e(TAG, "Could not send message to " + getClientId(messenger), ex);
523fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
524fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
525fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
526fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private static String getClientId(Messenger messenger) {
527fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        return "Client connection " + messenger.getBinder().toString();
528fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
529fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
530fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /**
531fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Returns true if the messenger object is valid.
532fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * <p>
533fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * The messenger contructor and unparceling code does not check whether the
534fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * provided IBinder is a valid IMessenger object.  As a result, it's possible
535fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * for a peer to send an invalid IBinder that will result in crashes downstream.
536fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * This method checks that the messenger is in a valid state.
537fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * </p>
538fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
539fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    static boolean isValidRemoteMessenger(Messenger messenger) {
540fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        try {
541fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return messenger != null && messenger.getBinder() != null;
542fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        } catch (NullPointerException ex) {
543fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            // If the messenger was constructed with a binder interface other than
544fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            // IMessenger then the call to getBinder() will crash with an NPE.
545fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return false;
546fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
547fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
548fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
549fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private final class PrivateHandler extends Handler {
550fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        @Override
551fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public void handleMessage(Message msg) {
552fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            switch (msg.what) {
553fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                case PRIVATE_MSG_CLIENT_DIED:
554fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    onBinderDied((Messenger)msg.obj);
555fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    break;
556fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
557fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
558fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
559fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
560fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private final class ProviderCallback extends MediaRouteProvider.Callback {
561fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        @Override
562fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public void onDescriptorChanged(MediaRouteProvider provider,
563fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                ProviderDescriptor descriptor) {
564fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            sendDescriptorChanged(descriptor);
565fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
566fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
567fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
568fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private final class ClientRecord implements DeathRecipient {
569fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public final Messenger mMessenger;
570fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public final int mVersion;
571fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
572fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        private final SparseArray<MediaRouteProvider.RouteController> mControllers =
573fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                new SparseArray<MediaRouteProvider.RouteController>();
574fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
575fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public ClientRecord(Messenger messenger, int version) {
576fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            mMessenger = messenger;
577fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            mVersion = version;
578fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
579fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
580fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public boolean register() {
581fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            try {
582fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                mMessenger.getBinder().linkToDeath(this, 0);
583fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return true;
584fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            } catch (RemoteException ex) {
585fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                binderDied();
586fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
587fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return false;
588fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
589fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
590fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public void dispose() {
591fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            int count = mControllers.size();
592fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            for (int i = 0; i < count; i++) {
593129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown                mControllers.valueAt(i).onRelease();
594fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
595fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            mControllers.clear();
596fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
597fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            mMessenger.getBinder().unlinkToDeath(this, 0);
598fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
599fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
600fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public boolean hasMessenger(Messenger other) {
601fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return mMessenger.getBinder() == other.getBinder();
602fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
603fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
604fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public boolean createRouteController(String routeId, int controllerId) {
605fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (mControllers.indexOfKey(controllerId) < 0) {
606fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                MediaRouteProvider.RouteController controller =
607fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        mProvider.onCreateRouteController(routeId);
608fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                mControllers.put(controllerId, controller);
609fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return true;
610fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
611fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return false;
612fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
613fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
614fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public boolean releaseRouteController(int controllerId) {
615fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            MediaRouteProvider.RouteController controller = mControllers.get(controllerId);
616fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (controller != null) {
617fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                mControllers.remove(controllerId);
618129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown                controller.onRelease();
619fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                return true;
620fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
621fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return false;
622fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
623fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
624fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public MediaRouteProvider.RouteController getRouteController(int controllerId) {
625fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return mControllers.get(controllerId);
626fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
627fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
628fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        @Override
629fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public void binderDied() {
630fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            mPrivateHandler.obtainMessage(PRIVATE_MSG_CLIENT_DIED, mMessenger).sendToTarget();
631fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
632fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
633fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        @Override
634fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public String toString() {
635fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return getClientId(mMessenger);
636fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
637fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
638fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
639fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    /**
640fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * Handler that receives messages from clients.
641fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * <p>
642fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * This inner class is static and only retains a weak reference to the service
643fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * to prevent the service from being leaked in case one of the clients is holding an
644fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * active reference to the server's messenger.
645fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * </p><p>
646fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * This handler should not be used to handle any messages other than those
647fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * that come from the client.
648fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     * </p>
649fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown     */
650fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    private static final class ReceiveHandler extends Handler {
651fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        private final WeakReference<MediaRouteProviderService> mServiceRef;
652fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
653fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public ReceiveHandler(MediaRouteProviderService service) {
654fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            mServiceRef = new WeakReference<MediaRouteProviderService>(service);
655fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
656fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
657fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        @Override
658fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        public void handleMessage(Message msg) {
659fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            final Messenger messenger = msg.replyTo;
660fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (isValidRemoteMessenger(messenger)) {
661fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                final int what = msg.what;
662fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                final int requestId = msg.arg1;
663fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                final int arg = msg.arg2;
664fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                final Object obj = msg.obj;
665fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                final Bundle data = msg.peekData();
666fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (!processMessage(what, messenger, requestId, arg, obj, data)) {
667fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    if (DEBUG) {
668fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        Log.d(TAG, getClientId(messenger) + ": Message failed, what=" + what
669fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                + ", requestId=" + requestId + ", arg=" + arg
670fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                + ", obj=" + obj + ", data=" + data);
671fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    }
672fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    sendGenericFailure(messenger, requestId);
673fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
674fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            } else {
675fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                if (DEBUG) {
676fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    Log.d(TAG, "Ignoring message without valid reply messenger.");
677fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
678fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
679fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
680fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
681fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        private boolean processMessage(int what,
682fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                Messenger messenger, int requestId, int arg, Object obj, Bundle data) {
683fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            MediaRouteProviderService service = mServiceRef.get();
684fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            if (service != null) {
685fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                switch (what) {
686fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    case CLIENT_MSG_REGISTER:
687fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        return service.onRegisterClient(messenger, requestId, arg);
688fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
689fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    case CLIENT_MSG_UNREGISTER:
690fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        return service.onUnregisterClient(messenger, requestId);
691fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
692fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    case CLIENT_MSG_CREATE_ROUTE_CONTROLLER: {
693fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        String routeId = data.getString(CLIENT_DATA_ROUTE_ID);
694fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        if (routeId != null) {
695fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            return service.onCreateRouteController(
696fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                    messenger, requestId, arg, routeId);
697fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        }
698fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        break;
699fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    }
700fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
701fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    case CLIENT_MSG_RELEASE_ROUTE_CONTROLLER:
702fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        return service.onReleaseRouteController(messenger, requestId, arg);
703fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
704fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    case CLIENT_MSG_SELECT_ROUTE:
705fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        return service.onSelectRoute(messenger, requestId, arg);
706fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
707fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    case CLIENT_MSG_UNSELECT_ROUTE:
708fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        return service.onUnselectRoute(messenger, requestId, arg);
709fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
710fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    case CLIENT_MSG_SET_ROUTE_VOLUME: {
711fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        int volume = data.getInt(CLIENT_DATA_VOLUME, -1);
712fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        if (volume >= 0) {
713fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            return service.onSetRouteVolume(
714fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                    messenger, requestId, arg, volume);
715fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        }
716fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        break;
717fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    }
718fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
719fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    case CLIENT_MSG_UPDATE_ROUTE_VOLUME: {
720fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        int delta = data.getInt(CLIENT_DATA_VOLUME, 0);
721fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        if (delta != 0) {
722fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            return service.onUpdateRouteVolume(
723fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                    messenger, requestId, arg, delta);
724fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        }
725fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        break;
726fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    }
727fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown
728fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                    case CLIENT_MSG_ROUTE_CONTROL_REQUEST:
729fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        if (obj instanceof Intent) {
730fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                            return service.onRouteControlRequest(
731fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                                    messenger, requestId, arg, (Intent)obj);
732fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        }
733fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                        break;
734fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown                }
735fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            }
736fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown            return false;
737fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown        }
738fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown    }
739fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown}
740