• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.bluetooth;
18 
19 import android.content.Context;
20 import android.os.Binder;
21 import android.os.IBinder;
22 import android.os.RemoteException;
23 import android.util.Log;
24 
25 import java.util.ArrayList;
26 import java.util.List;
27 
28 /**
29  * This class provides the public APIs to control the Bluetooth AVRCP Controller. It currently
30  * supports player information, playback support and track metadata.
31  *
32  * <p>BluetoothAvrcpController is a proxy object for controlling the Bluetooth AVRCP
33  * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
34  * the BluetoothAvrcpController proxy object.
35  *
36  * {@hide}
37  */
38 public final class BluetoothAvrcpController implements BluetoothProfile {
39     private static final String TAG = "BluetoothAvrcpController";
40     private static final boolean DBG = false;
41     private static final boolean VDBG = false;
42 
43     /**
44      * Intent used to broadcast the change in connection state of the AVRCP Controller
45      * profile.
46      *
47      * <p>This intent will have 3 extras:
48      * <ul>
49      * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
50      * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
51      * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
52      * </ul>
53      *
54      * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
55      * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
56      * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
57      *
58      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
59      * receive.
60      */
61     public static final String ACTION_CONNECTION_STATE_CHANGED =
62             "android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED";
63 
64     /**
65      * Intent used to broadcast the change in player application setting state on AVRCP AG.
66      *
67      * <p>This intent will have the following extras:
68      * <ul>
69      * <li> {@link #EXTRA_PLAYER_SETTING} - {@link BluetoothAvrcpPlayerSettings} containing the
70      * most recent player setting. </li>
71      * </ul>
72      */
73     public static final String ACTION_PLAYER_SETTING =
74             "android.bluetooth.avrcp-controller.profile.action.PLAYER_SETTING";
75 
76     public static final String EXTRA_PLAYER_SETTING =
77             "android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING";
78 
79     private BluetoothAdapter mAdapter;
80     private final BluetoothProfileConnector<IBluetoothAvrcpController> mProfileConnector =
81             new BluetoothProfileConnector(this, BluetoothProfile.AVRCP_CONTROLLER,
82                     "BluetoothAvrcpController", IBluetoothAvrcpController.class.getName()) {
83                 @Override
84                 public IBluetoothAvrcpController getServiceInterface(IBinder service) {
85                     return IBluetoothAvrcpController.Stub.asInterface(
86                             Binder.allowBlocking(service));
87                 }
88     };
89 
90     /**
91      * Create a BluetoothAvrcpController proxy object for interacting with the local
92      * Bluetooth AVRCP service.
93      */
BluetoothAvrcpController(Context context, ServiceListener listener)94     /*package*/ BluetoothAvrcpController(Context context, ServiceListener listener) {
95         mAdapter = BluetoothAdapter.getDefaultAdapter();
96         mProfileConnector.connect(context, listener);
97     }
98 
close()99     /*package*/ void close() {
100         mProfileConnector.disconnect();
101     }
102 
getService()103     private IBluetoothAvrcpController getService() {
104         return mProfileConnector.getService();
105     }
106 
107     @Override
finalize()108     public void finalize() {
109         close();
110     }
111 
112     /**
113      * {@inheritDoc}
114      */
115     @Override
getConnectedDevices()116     public List<BluetoothDevice> getConnectedDevices() {
117         if (VDBG) log("getConnectedDevices()");
118         final IBluetoothAvrcpController service =
119                 getService();
120         if (service != null && isEnabled()) {
121             try {
122                 return service.getConnectedDevices();
123             } catch (RemoteException e) {
124                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
125                 return new ArrayList<BluetoothDevice>();
126             }
127         }
128         if (service == null) Log.w(TAG, "Proxy not attached to service");
129         return new ArrayList<BluetoothDevice>();
130     }
131 
132     /**
133      * {@inheritDoc}
134      */
135     @Override
getDevicesMatchingConnectionStates(int[] states)136     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
137         if (VDBG) log("getDevicesMatchingStates()");
138         final IBluetoothAvrcpController service =
139                 getService();
140         if (service != null && isEnabled()) {
141             try {
142                 return service.getDevicesMatchingConnectionStates(states);
143             } catch (RemoteException e) {
144                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
145                 return new ArrayList<BluetoothDevice>();
146             }
147         }
148         if (service == null) Log.w(TAG, "Proxy not attached to service");
149         return new ArrayList<BluetoothDevice>();
150     }
151 
152     /**
153      * {@inheritDoc}
154      */
155     @Override
getConnectionState(BluetoothDevice device)156     public int getConnectionState(BluetoothDevice device) {
157         if (VDBG) log("getState(" + device + ")");
158         final IBluetoothAvrcpController service =
159                 getService();
160         if (service != null && isEnabled() && isValidDevice(device)) {
161             try {
162                 return service.getConnectionState(device);
163             } catch (RemoteException e) {
164                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
165                 return BluetoothProfile.STATE_DISCONNECTED;
166             }
167         }
168         if (service == null) Log.w(TAG, "Proxy not attached to service");
169         return BluetoothProfile.STATE_DISCONNECTED;
170     }
171 
172     /**
173      * Gets the player application settings.
174      *
175      * @return the {@link BluetoothAvrcpPlayerSettings} or {@link null} if there is an error.
176      */
getPlayerSettings(BluetoothDevice device)177     public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
178         if (DBG) Log.d(TAG, "getPlayerSettings");
179         BluetoothAvrcpPlayerSettings settings = null;
180         final IBluetoothAvrcpController service =
181                 getService();
182         if (service != null && isEnabled()) {
183             try {
184                 settings = service.getPlayerSettings(device);
185             } catch (RemoteException e) {
186                 Log.e(TAG, "Error talking to BT service in getMetadata() " + e);
187                 return null;
188             }
189         }
190         return settings;
191     }
192 
193     /**
194      * Sets the player app setting for current player.
195      * returns true in case setting is supported by remote, false otherwise
196      */
setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting)197     public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
198         if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
199         final IBluetoothAvrcpController service =
200                 getService();
201         if (service != null && isEnabled()) {
202             try {
203                 return service.setPlayerApplicationSetting(plAppSetting);
204             } catch (RemoteException e) {
205                 Log.e(TAG, "Error talking to BT service in setPlayerApplicationSetting() " + e);
206                 return false;
207             }
208         }
209         if (service == null) Log.w(TAG, "Proxy not attached to service");
210         return false;
211     }
212 
213     /**
214      * Send Group Navigation Command to Remote.
215      * possible keycode values: next_grp, previous_grp defined above
216      */
sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState)217     public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
218         Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
219                 + keyState);
220         final IBluetoothAvrcpController service =
221                 getService();
222         if (service != null && isEnabled()) {
223             try {
224                 service.sendGroupNavigationCmd(device, keyCode, keyState);
225                 return;
226             } catch (RemoteException e) {
227                 Log.e(TAG, "Error talking to BT service in sendGroupNavigationCmd()", e);
228                 return;
229             }
230         }
231         if (service == null) Log.w(TAG, "Proxy not attached to service");
232     }
233 
isEnabled()234     private boolean isEnabled() {
235         return mAdapter.getState() == BluetoothAdapter.STATE_ON;
236     }
237 
isValidDevice(BluetoothDevice device)238     private static boolean isValidDevice(BluetoothDevice device) {
239         return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
240     }
241 
log(String msg)242     private static void log(String msg) {
243         Log.d(TAG, msg);
244     }
245 }
246