MediaRouteProviderService.java revision ae161a4d000a10dafd844d17145de631933f21f3
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; 29fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.util.Log; 30fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.util.SparseArray; 31fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 32fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport java.lang.ref.WeakReference; 33fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport java.util.ArrayList; 34fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 35fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown/** 36fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Base class for media route provider services. 37fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p> 38fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * To implement your own media route provider service, extend this class and 39fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * override the {@link #onCreateMediaRouteProvider} method to return an 40fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * instance of your {@link MediaRouteProvider}. 41fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p> 42fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Declare your media route provider service in your application manifest 43fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * like this: 44fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 45fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <pre> 46fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <service android:name=".MyMediaRouteProviderService" 47fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * android:label="@string/my_media_route_provider_service"> 48fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <intent-filter> 49fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <action android:name="android.media.MediaRouteProviderService" /> 50fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </intent-filter> 51fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </service> 52fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </pre> 53fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 54fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownpublic abstract class MediaRouteProviderService extends Service { 55f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown private static final String TAG = "MediaRouteProviderSrv"; // max. 23 chars 56f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 57fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 58fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ArrayList<ClientRecord> mClients = new ArrayList<ClientRecord>(); 59fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ReceiveHandler mReceiveHandler; 60fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final Messenger mReceiveMessenger; 61fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final PrivateHandler mPrivateHandler; 62fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ProviderCallback mProviderCallback; 63fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 64fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private MediaRouteProvider mProvider; 6511417b1cfde8f1749905f2d735623af9214148afJeff Brown private MediaRouteDiscoveryRequest mCompositeDiscoveryRequest; 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 15428520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown /** (client v1) 15511417b1cfde8f1749905f2d735623af9214148afJeff Brown * Sets the discovery request. 15628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown * - replyTo : client messenger 15728520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown * - arg1 : request id 15811417b1cfde8f1749905f2d735623af9214148afJeff Brown * - obj : discovery request bundle, or null if none 15928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown */ 16011417b1cfde8f1749905f2d735623af9214148afJeff Brown static final int CLIENT_MSG_SET_DISCOVERY_REQUEST = 10; 16128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 162fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static final String CLIENT_DATA_ROUTE_ID = "routeId"; 163fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static final String CLIENT_DATA_VOLUME = "volume"; 164fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 165fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /* 166fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Messages sent from the service to the client. 167fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * DO NOT RENUMBER THESE! 168fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 169fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 170fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** (service v1) 171fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Generic failure sent in response to any unrecognized or malformed request. 172fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * - arg1 : request id 173fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 174fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static final int SERVICE_MSG_GENERIC_FAILURE = 0; 175fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 176fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** (service v1) 177fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Generic failure sent in response to a successful message. 178fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * - arg1 : request id 179fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 180fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static final int SERVICE_MSG_GENERIC_SUCCESS = 1; 181fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 182fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** (service v1) 183fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Registration succeeded. 184fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * - arg1 : request id 185fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * - arg2 : server version 186fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * - obj : route provider descriptor bundle, or null 187fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 188fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static final int SERVICE_MSG_REGISTERED = 2; 189fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 190fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** (service v1) 1913d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown * Route control request success result. 192fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * - arg1 : request id 193fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * - obj : result data bundle, or null 194fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 1953d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown static final int SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED = 3; 1963d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown 1973d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown /** (service v1) 1983d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown * Route control request failure result. 1993d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown * - arg1 : request id 2003d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown * - obj : result data bundle, or null 2013d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown * - SERVICE_DATA_ERROR: error message 2023d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown */ 2033d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown static final int SERVICE_MSG_CONTROL_REQUEST_FAILED = 4; 204fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 205fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** (service v1) 206fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Route provider descriptor changed. (unsolicited event) 207fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * - arg1 : reserved (0) 208fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * - obj : route provider descriptor bundle, or null 209fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 2103d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown static final int SERVICE_MSG_DESCRIPTOR_CHANGED = 5; 2113d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown 2123d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown static final String SERVICE_DATA_ERROR = "error"; 213fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 214fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /* 215fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Recognized client version numbers. (Reserved for future use.) 216fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * DO NOT RENUMBER THESE! 217fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 218fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 219fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static final int CLIENT_VERSION_1 = 1; 220fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static final int CLIENT_VERSION_CURRENT = CLIENT_VERSION_1; 221fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 222fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /* 223fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Recognized server version numbers. (Reserved for future use.) 224fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * DO NOT RENUMBER THESE! 225fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 226fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 227fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static final int SERVICE_VERSION_1 = 1; 228fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static final int SERVICE_VERSION_CURRENT = SERVICE_VERSION_1; 229fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 230fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /* 231fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Private messages used internally. (Yes, you can renumber these.) 232fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 233fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 234fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static final int PRIVATE_MSG_CLIENT_DIED = 1; 235fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 236fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 237fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Creates a media route provider service. 238fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 239fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProviderService() { 240fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mReceiveHandler = new ReceiveHandler(this); 241fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mReceiveMessenger = new Messenger(mReceiveHandler); 242fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPrivateHandler = new PrivateHandler(); 243fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mProviderCallback = new ProviderCallback(); 244fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 245fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 246fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 247fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Called by the system when it is time to create the media route provider. 248fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 249fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @return The media route provider offered by this service, or null if 250fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * this service has decided not to offer a media route provider. 251fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 252fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public abstract MediaRouteProvider onCreateMediaRouteProvider(); 253fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 254fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 255fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Gets the media route provider offered by this service. 256fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 257fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @return The media route provider offered by this service, or null if 258fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * it has not yet been created. 259fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 260fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @see #onCreateMediaRouteProvider() 261fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 262fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProvider getMediaRouteProvider() { 263fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mProvider; 264fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 265fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 266fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 267fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public IBinder onBind(Intent intent) { 268fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (intent.getAction().equals(SERVICE_INTERFACE)) { 269fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mProvider == null) { 270fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider provider = onCreateMediaRouteProvider(); 271fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (provider != null) { 272fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown String providerPackage = provider.getMetadata().getPackageName(); 273fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (!providerPackage.equals(getPackageName())) { 274fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown throw new IllegalStateException("onCreateMediaRouteProvider() returned " 275fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "a provider whose package name does not match the package " 276fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "name of the service. A media route provider service can " 277fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "only export its own media route providers. " 278fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "Provider package name: " + providerPackage 279fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ". Service package name: " + getPackageName() + "."); 280fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 281350ba6e4a1b5ec28721a098e50eaf6a508eb28f0Jeff Brown mProvider = provider; 28211417b1cfde8f1749905f2d735623af9214148afJeff Brown mProvider.setCallback(mProviderCallback); 283fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 284fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 285fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mProvider != null) { 286fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mReceiveMessenger.getBinder(); 287fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 288fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 289fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return null; 290fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 291fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 292fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onRegisterClient(Messenger messenger, int requestId, int version) { 293fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (version >= CLIENT_VERSION_1) { 294fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 295fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index < 0) { 296fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = new ClientRecord(messenger, version); 297fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.register()) { 298fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mClients.add(client); 299fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 300fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Registered, version=" + version); 301fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 302fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 30311417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteProviderDescriptor descriptor = mProvider.getDescriptor(); 304fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_REGISTERED, 305fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown requestId, SERVICE_VERSION_CURRENT, 306fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown descriptor != null ? descriptor.asBundle() : null, null); 307fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 308fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 309fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 310fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 311fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 312fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 313fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 314fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 315fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onUnregisterClient(Messenger messenger, int requestId) { 316fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 317fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index >= 0) { 318fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.remove(index); 319fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 320fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Unregistered"); 321fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 322fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.dispose(); 323fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 324fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 325fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 326fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 327fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 328fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 329fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private void onBinderDied(Messenger messenger) { 330fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 331fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index >= 0) { 332fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.remove(index); 333fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 334fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Binder died"); 335fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 336fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.dispose(); 337fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 338fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 339fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 340fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onCreateRouteController(Messenger messenger, int requestId, 341fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, String routeId) { 342fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 343fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 344fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.createRouteController(routeId, controllerId)) { 345fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 346fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route controller created" 347fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", routeId=" + routeId); 348fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 349fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 350fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 351fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 352fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 353fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 354fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 355fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 356fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onReleaseRouteController(Messenger messenger, int requestId, 357fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId) { 358fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 359fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 360fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.releaseRouteController(controllerId)) { 361fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 362fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route controller released" 363fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 364fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 365fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 366fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 367fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 368fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 369fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 370fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 371fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 372fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onSelectRoute(Messenger messenger, int requestId, 373fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId) { 374fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 375fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 376fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 377fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 378fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 379129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onSelect(); 380fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 381fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route selected" 382fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 383fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 384fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 385fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 386fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 387fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 388fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 389fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 390fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 391fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onUnselectRoute(Messenger messenger, int requestId, 392fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId) { 393fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 394fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 395fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 396fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 397fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 398129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onUnselect(); 399fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 400fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route unselected" 401fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 402fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 403fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 404fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 405fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 406fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 407fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 408fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 409fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 410fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onSetRouteVolume(Messenger messenger, int requestId, 411fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, int volume) { 412fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 413fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 414fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 415fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 416fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 417129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onSetVolume(volume); 418fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 419fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route volume changed" 420fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", volume=" + volume); 421fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 422fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 423fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 424fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 425fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 426fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 427fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 428fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 429fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onUpdateRouteVolume(Messenger messenger, int requestId, 430fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, int delta) { 431fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 432fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 433fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 434fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 435fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 436129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onUpdateVolume(delta); 437fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 438fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route volume updated" 439fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", delta=" + delta); 440fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 441fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 442fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 443fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 444fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 445fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 446fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 447fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 448fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onRouteControlRequest(final Messenger messenger, final int requestId, 449fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int controllerId, final Intent intent) { 450fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final ClientRecord client = getClient(messenger); 451fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 452fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 453fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 454fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 455fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouter.ControlRequestCallback callback = null; 456fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 457fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown callback = new MediaRouter.ControlRequestCallback() { 458fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 4593d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown public void onResult(Bundle data) { 4603d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (DEBUG) { 4613d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Log.d(TAG, client + ": Route control request succeeded" 4623d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", controllerId=" + controllerId 4633d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", intent=" + intent 4643d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", data=" + data); 4653d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 4663d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (findClient(messenger) >= 0) { 4673d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED, 4683d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, null); 4693d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 4703d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 4713d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown 4723d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown @Override 4733d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown public void onError(String error, Bundle data) { 474fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 4753d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Log.d(TAG, client + ": Route control request failed" 476fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId 477fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", intent=" + intent 4783d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", error=" + error + ", data=" + data); 479fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 480fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (findClient(messenger) >= 0) { 4813d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (error != null) { 4823d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Bundle bundle = new Bundle(); 4833d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown bundle.putString(SERVICE_DATA_ERROR, error); 4843d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED, 4853d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, bundle); 4863d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } else { 4873d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED, 4883d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, null); 4893d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 490fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 491fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 492fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown }; 493fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 494129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown if (controller.onControlRequest(intent, callback)) { 495fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 496fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route control request delivered" 497fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", intent=" + intent); 498fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 499fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 500fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 501fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 502fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 503fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 504fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 505fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 50611417b1cfde8f1749905f2d735623af9214148afJeff Brown private boolean onSetDiscoveryRequest(Messenger messenger, int requestId, 50711417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request) { 50828520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown ClientRecord client = getClient(messenger); 50928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown if (client != null) { 51011417b1cfde8f1749905f2d735623af9214148afJeff Brown boolean actuallyChanged = client.setDiscoveryRequest(request); 51128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown if (DEBUG) { 51211417b1cfde8f1749905f2d735623af9214148afJeff Brown Log.d(TAG, client + ": Set discovery request, request=" + request 51311417b1cfde8f1749905f2d735623af9214148afJeff Brown + ", actuallyChanged=" + actuallyChanged 51411417b1cfde8f1749905f2d735623af9214148afJeff Brown + ", compositeDiscoveryRequest=" + mCompositeDiscoveryRequest); 51528520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 51628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown sendGenericSuccess(messenger, requestId); 51728520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return true; 51828520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 51928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return false; 52028520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 52128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 52211417b1cfde8f1749905f2d735623af9214148afJeff Brown private void sendDescriptorChanged(MediaRouteProviderDescriptor descriptor) { 523fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Bundle descriptorBundle = descriptor != null ? descriptor.asBundle() : null; 524fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int count = mClients.size(); 525fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 526fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.get(i); 527fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(client.mMessenger, SERVICE_MSG_DESCRIPTOR_CHANGED, 0, 0, 528fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown descriptorBundle, null); 529fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 530fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Sent descriptor change event, descriptor=" + descriptor); 531fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 532fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 533fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 534fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 53511417b1cfde8f1749905f2d735623af9214148afJeff Brown private boolean updateCompositeDiscoveryRequest() { 53611417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest composite = null; 53711417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteSelector.Builder selectorBuilder = null; 53811417b1cfde8f1749905f2d735623af9214148afJeff Brown boolean activeScan = false; 53911417b1cfde8f1749905f2d735623af9214148afJeff Brown final int count = mClients.size(); 54011417b1cfde8f1749905f2d735623af9214148afJeff Brown for (int i = 0; i < count; i++) { 54111417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request = mClients.get(i).mDiscoveryRequest; 54211417b1cfde8f1749905f2d735623af9214148afJeff Brown if (request != null 54311417b1cfde8f1749905f2d735623af9214148afJeff Brown && (!request.getSelector().isEmpty() || request.isActiveScan())) { 54411417b1cfde8f1749905f2d735623af9214148afJeff Brown activeScan |= request.isActiveScan(); 54511417b1cfde8f1749905f2d735623af9214148afJeff Brown if (composite == null) { 54611417b1cfde8f1749905f2d735623af9214148afJeff Brown composite = request; 54711417b1cfde8f1749905f2d735623af9214148afJeff Brown } else { 54811417b1cfde8f1749905f2d735623af9214148afJeff Brown if (selectorBuilder == null) { 54911417b1cfde8f1749905f2d735623af9214148afJeff Brown selectorBuilder = new MediaRouteSelector.Builder(composite.getSelector()); 55011417b1cfde8f1749905f2d735623af9214148afJeff Brown } 55111417b1cfde8f1749905f2d735623af9214148afJeff Brown selectorBuilder.addSelector(request.getSelector()); 55211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 55311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 55411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 55511417b1cfde8f1749905f2d735623af9214148afJeff Brown if (selectorBuilder != null) { 55611417b1cfde8f1749905f2d735623af9214148afJeff Brown composite = new MediaRouteDiscoveryRequest(selectorBuilder.build(), activeScan); 55711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 55811417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mCompositeDiscoveryRequest != composite 55911417b1cfde8f1749905f2d735623af9214148afJeff Brown && (mCompositeDiscoveryRequest == null 56011417b1cfde8f1749905f2d735623af9214148afJeff Brown || !mCompositeDiscoveryRequest.equals(composite))) { 56111417b1cfde8f1749905f2d735623af9214148afJeff Brown mCompositeDiscoveryRequest = composite; 56211417b1cfde8f1749905f2d735623af9214148afJeff Brown mProvider.setDiscoveryRequest(composite); 56311417b1cfde8f1749905f2d735623af9214148afJeff Brown return true; 56411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 56511417b1cfde8f1749905f2d735623af9214148afJeff Brown return false; 56611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 56711417b1cfde8f1749905f2d735623af9214148afJeff Brown 568fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private ClientRecord getClient(Messenger messenger) { 569fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 570fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return index >= 0 ? mClients.get(index) : null; 571fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 572fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 573fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private int findClient(Messenger messenger) { 574fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int count = mClients.size(); 575fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 576fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.get(i); 577fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.hasMessenger(messenger)) { 578fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return i; 579fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 580fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 581fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return -1; 582fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 583fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 584fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendGenericFailure(Messenger messenger, int requestId) { 585fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 586fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_GENERIC_FAILURE, requestId, 0, null, null); 587fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 588fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 589fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 590fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendGenericSuccess(Messenger messenger, int requestId) { 591fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 592fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_GENERIC_SUCCESS, requestId, 0, null, null); 593fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 594fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 595fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 596fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendReply(Messenger messenger, int what, 597fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int requestId, int arg, Object obj, Bundle data) { 598fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Message msg = Message.obtain(); 599fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.what = what; 600fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.arg1 = requestId; 601fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.arg2 = arg; 602fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.obj = obj; 603fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.setData(data); 604fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown try { 605fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger.send(msg); 606fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (DeadObjectException ex) { 607fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown // The client died. 608fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (RemoteException ex) { 609fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.e(TAG, "Could not send message to " + getClientId(messenger), ex); 610fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 611fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 612fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 613fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static String getClientId(Messenger messenger) { 614fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return "Client connection " + messenger.getBinder().toString(); 615fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 616fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 617fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 618fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Returns true if the messenger object is valid. 619fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p> 62011417b1cfde8f1749905f2d735623af9214148afJeff Brown * The messenger constructor and unparceling code does not check whether the 621fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * provided IBinder is a valid IMessenger object. As a result, it's possible 622fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * for a peer to send an invalid IBinder that will result in crashes downstream. 623fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * This method checks that the messenger is in a valid state. 624fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 625fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 626fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown static boolean isValidRemoteMessenger(Messenger messenger) { 627fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown try { 628fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return messenger != null && messenger.getBinder() != null; 629fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (NullPointerException ex) { 630fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown // If the messenger was constructed with a binder interface other than 631fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown // IMessenger then the call to getBinder() will crash with an NPE. 632fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 633fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 634fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 635fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 636fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class PrivateHandler extends Handler { 637fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 638fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void handleMessage(Message msg) { 639fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown switch (msg.what) { 640fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case PRIVATE_MSG_CLIENT_DIED: 641fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown onBinderDied((Messenger)msg.obj); 642fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 643fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 644fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 645fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 646fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 647fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class ProviderCallback extends MediaRouteProvider.Callback { 648fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 649fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void onDescriptorChanged(MediaRouteProvider provider, 65011417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteProviderDescriptor descriptor) { 651fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendDescriptorChanged(descriptor); 652fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 653fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 654fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 655fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class ClientRecord implements DeathRecipient { 656fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public final Messenger mMessenger; 657fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public final int mVersion; 65811417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteDiscoveryRequest mDiscoveryRequest; 659fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 660fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final SparseArray<MediaRouteProvider.RouteController> mControllers = 661fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown new SparseArray<MediaRouteProvider.RouteController>(); 662fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 663fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public ClientRecord(Messenger messenger, int version) { 664fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger = messenger; 665fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mVersion = version; 666fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 667fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 668fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean register() { 669fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown try { 670fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger.getBinder().linkToDeath(this, 0); 671fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 672fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (RemoteException ex) { 673fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown binderDied(); 674fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 675fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 676fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 677fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 678fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void dispose() { 679fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int count = mControllers.size(); 680fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 681129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown mControllers.valueAt(i).onRelease(); 682fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 683fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mControllers.clear(); 684fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 685fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger.getBinder().unlinkToDeath(this, 0); 68628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 68711417b1cfde8f1749905f2d735623af9214148afJeff Brown setDiscoveryRequest(null); 688fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 689fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 690fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean hasMessenger(Messenger other) { 691fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mMessenger.getBinder() == other.getBinder(); 692fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 693fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 694fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean createRouteController(String routeId, int controllerId) { 695fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mControllers.indexOfKey(controllerId) < 0) { 696fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 697fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mProvider.onCreateRouteController(routeId); 698ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown if (controller != null) { 699ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown mControllers.put(controllerId, controller); 700ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown return true; 701ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown } 702fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 703fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 704fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 705fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 706fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean releaseRouteController(int controllerId) { 707fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = mControllers.get(controllerId); 708fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 709fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mControllers.remove(controllerId); 710129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onRelease(); 711fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 712fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 713fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 714fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 715fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 716fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProvider.RouteController getRouteController(int controllerId) { 717fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mControllers.get(controllerId); 718fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 719fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 72011417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean setDiscoveryRequest(MediaRouteDiscoveryRequest request) { 72111417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mDiscoveryRequest != request 72211417b1cfde8f1749905f2d735623af9214148afJeff Brown && (mDiscoveryRequest == null || !mDiscoveryRequest.equals(request))) { 72311417b1cfde8f1749905f2d735623af9214148afJeff Brown mDiscoveryRequest = request; 72411417b1cfde8f1749905f2d735623af9214148afJeff Brown return updateCompositeDiscoveryRequest(); 72528520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 72628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return false; 72728520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 72828520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 72928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown // Runs on a binder thread. 730fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 731fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void binderDied() { 732fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPrivateHandler.obtainMessage(PRIVATE_MSG_CLIENT_DIED, mMessenger).sendToTarget(); 733fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 734fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 735fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 736fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public String toString() { 737fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return getClientId(mMessenger); 738fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 739fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 740fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 741fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 742fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Handler that receives messages from clients. 743fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p> 744fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * This inner class is static and only retains a weak reference to the service 745fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * to prevent the service from being leaked in case one of the clients is holding an 746fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * active reference to the server's messenger. 747fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p> 748fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * This handler should not be used to handle any messages other than those 749fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * that come from the client. 750fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 751fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 752fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static final class ReceiveHandler extends Handler { 753fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final WeakReference<MediaRouteProviderService> mServiceRef; 754fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 755fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public ReceiveHandler(MediaRouteProviderService service) { 756fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mServiceRef = new WeakReference<MediaRouteProviderService>(service); 757fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 758fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 759fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 760fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void handleMessage(Message msg) { 761fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Messenger messenger = msg.replyTo; 762fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (isValidRemoteMessenger(messenger)) { 763fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int what = msg.what; 764fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int requestId = msg.arg1; 765fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int arg = msg.arg2; 766fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Object obj = msg.obj; 767fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Bundle data = msg.peekData(); 768fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (!processMessage(what, messenger, requestId, arg, obj, data)) { 769fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 770fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, getClientId(messenger) + ": Message failed, what=" + what 771fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", requestId=" + requestId + ", arg=" + arg 772fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", obj=" + obj + ", data=" + data); 773fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 774fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericFailure(messenger, requestId); 775fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 776fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } else { 777fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 778fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, "Ignoring message without valid reply messenger."); 779fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 780fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 781fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 782fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 783fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean processMessage(int what, 784fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Messenger messenger, int requestId, int arg, Object obj, Bundle data) { 785fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProviderService service = mServiceRef.get(); 786fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (service != null) { 787fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown switch (what) { 788fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_REGISTER: 789fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onRegisterClient(messenger, requestId, arg); 790fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 791fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UNREGISTER: 792fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onUnregisterClient(messenger, requestId); 793fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 794fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_CREATE_ROUTE_CONTROLLER: { 795fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown String routeId = data.getString(CLIENT_DATA_ROUTE_ID); 796fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (routeId != null) { 797fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onCreateRouteController( 798fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, routeId); 799fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 800fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 801fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 802fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 803fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_RELEASE_ROUTE_CONTROLLER: 804fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onReleaseRouteController(messenger, requestId, arg); 805fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 806fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_SELECT_ROUTE: 807fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onSelectRoute(messenger, requestId, arg); 808fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 809fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UNSELECT_ROUTE: 810fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onUnselectRoute(messenger, requestId, arg); 811fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 812fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_SET_ROUTE_VOLUME: { 813fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int volume = data.getInt(CLIENT_DATA_VOLUME, -1); 814fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (volume >= 0) { 815fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onSetRouteVolume( 816fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, volume); 817fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 818fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 819fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 820fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 821fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UPDATE_ROUTE_VOLUME: { 822fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int delta = data.getInt(CLIENT_DATA_VOLUME, 0); 823fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (delta != 0) { 824fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onUpdateRouteVolume( 825fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, delta); 826fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 827fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 828fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 829fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 830fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_ROUTE_CONTROL_REQUEST: 831fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (obj instanceof Intent) { 832fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onRouteControlRequest( 833fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, (Intent)obj); 834fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 835fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 83628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 83711417b1cfde8f1749905f2d735623af9214148afJeff Brown case CLIENT_MSG_SET_DISCOVERY_REQUEST: { 838f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown if (obj == null || obj instanceof Bundle) { 83911417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request = 84011417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest.fromBundle((Bundle)obj); 84111417b1cfde8f1749905f2d735623af9214148afJeff Brown return service.onSetDiscoveryRequest( 842f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown messenger, requestId, 843f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown request != null && request.isValid() ? request : null); 84411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 84511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 846fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 847fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 848fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 849fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 850fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 851fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown} 852