蓝牙之十-avrcp代码调用关系

原址:http://blog.csdn.net/shichaog/article/details/52182987

由于需要实现avrcp的controller的get attr功能,所以看了下android6的代码调用关系。

app层

这里的app层是指用户编写的应用程序而不是谷歌Android中生成的一些app。如下是调试app的截屏。该app中出现了几个button用于控制targe。

app的代码简短罗列如下:

[java] view plaincopy 在CODE上查看代码片派生到我的代码片

  1. public class MyActivity extends Activity {  
  2.     private static final String TAG = "AndroidAvrcpControllerDemo";  
  3.   
  4. //BluetoothAvrcpController是要追踪的重点之一。  
  5.     private BluetoothAvrcpController mAvrcpController;  
  6.     private TextView mStatusView;  
  7.     private TextView mAttrsView;  
  8.   
  9.     @Override  
  10.     public void onCreateBundle savedInstanceState) {  
  11.         super.onCreatesavedInstanceState);  
  12.         setContentViewR.layout.main);  
  13.         mStatusView = TextView)findViewByIdR.id.status);  
  14.         mAttrsView = TextView)findViewByIdR.id.attrs);  
  15.   
  16.         BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter);  
  17.         bluetoothAdapter.getProfileProxythis, mAvrcpServiceListener, BluetoothProfile.AVRCP_CONTROLLER);  
  18.         mStatusView.setText"Connecting to the AVRCP_CONTROLLER service");  
  19.     }  
  20.   
  21.     @Override  
  22.     protected void onDestroy) {  
  23.         super.onDestroy);  
  24.         BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter);  
  25.         //mAvrcpController.removeCallback);  
  26.         bluetoothAdapter.closeProfileProxyBluetoothProfile.AVRCP_CONTROLLER, mAvrcpController);  
  27.     }  
  28.   
  29.     private BluetoothProfile.ServiceListener mAvrcpServiceListener = new BluetoothProfile.ServiceListener){  
  30.         @Override  
  31.         public void onServiceConnectedint profile, BluetoothProfile proxy) {  
  32.             if profile == BluetoothProfile.AVRCP_CONTROLLER){  
  33.                 mStatusView.setText"AVRCP_CONTROLLER connected");  
  34.                 Log.dTAG, "AvrcpControllerService connected");  
  35.   
  36.                 mAvrcpController = BluetoothAvrcpController) proxy;  
  37. //                mAvrcpController.setCallbacknew AvrcpControllerCallback));  
  38.   
  39.                 mStatusView.append"\r\nAvrcp devices: \r\n");  
  40.                 List<BluetoothDevice> devices = mAvrcpController.getConnectedDevices);  
  41.                 for BluetoothDevice device : devices)  
  42.                     mStatusView.append" – " + device.getName) + " " + device.getAddress)+"\r\n");  
  43.             }  
  44.         }  
  45.   
  46.         @Override  
  47.         public void onServiceDisconnectedint profile) {  
  48.             if profile == BluetoothProfile.AVRCP_CONTROLLER) {  
  49.                 mStatusView.setText"AVRCP_CONTROLLER disconnected");  
  50.                 Log.dTAG, "AvrcpControllerService disconnected");  
  51.                 //mAvrcpController.removeCallback);  
  52.                 mAvrcpController = null;  
  53.             }  
  54.         }  
  55.     };  
  56.   
  57.     private void sendCommandint keyCode){  
  58.         if mAvrcpController == null)  
  59.             return;  
  60.   
  61.         List<BluetoothDevice> devices = mAvrcpController.getConnectedDevices);  
  62.         for BluetoothDevice device : devices){  
  63.             Log.dTAG, "send command to device: "+ keyCode + device.getName) + " " + device.getAddress));  
  64.             //该方法是要追踪的重点之二  
  65.             mAvrcpController.sendPassThroughCmddevice, keyCode, BluetoothAvrcp.PASSTHROUGH_STATE_PRESS);  
  66.             mAvrcpController.sendPassThroughCmddevice, keyCode, BluetoothAvrcp.PASSTHROUGH_STATE_RELEASE);  
  67.         }  
  68.     }  
  69.   
  70.     public void onPlayButtonClickView view){  
  71.         sendCommandBluetoothAvrcp.PASSTHROUGH_ID_PLAY);  
  72.     }  

app里关心两处中卫注释就可以追终到其掉用的frameworks层代码。

frameworks层

[java] view plaincopy 在CODE上查看代码片派生到我的代码片

  1. frameworks/base/core/java/android/bluetooth/BluetoothAvrcpController.java  
  2. public final class BluetoothAvrcpController implements BluetoothProfile {  
  3. //服务对象  
  4. private IBluetoothAvrcpController mService;  
  5.    
  6. //创建BluetoothAvrcpController代理对象,用于和本地AVRCP服务交互。  
  7.         /*package*/ BluetoothAvrcpControllerContext context, ServiceListener l) {  
  8.         mContext = context;  
  9.         mServiceListener = l;  
  10.         mAdapter = BluetoothAdapter.getDefaultAdapter);  
  11.         IBluetoothManager mgr = mAdapter.getBluetoothManager);  
  12.         if mgr != null) {  
  13.             try {  
  14.                 mgr.registerStateChangeCallbackmBluetoothStateChangeCallback);  
  15.             } catch RemoteException e) {  
  16.                 Log.eTAG,"",e);  
  17.             }  
  18.         }  
  19.   
  20.         doBind);  
  21.     }  
  22.   
  23.     boolean doBind) {//aidl  
  24.         Intent intent = new IntentIBluetoothAvrcpController.class.getName));  
  25.         ComponentName comp = intent.resolveSystemServicemContext.getPackageManager), 0);  
  26.         intent.setComponentcomp);  
  27.         if comp == null || !mContext.bindServiceAsUserintent, mConnection, 0,  
  28.                 android.os.Process.myUserHandle))) {  
  29.             Log.eTAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent);  
  30.             return false;  
  31.         }  
  32.         return true;  
  33.     }  
  34.   
  35. //这里是应用调用的sendPassThroughCmd方法,该方法调用的是一个service的sendPassThroughCmd方法。  
  36.     public void sendPassThroughCmdBluetoothDevice device, int keyCode, int keyState) {  
  37.         if DBG) Log.dTAG, "sendPassThroughCmd");  
  38.         if mService != null && isEnabled)) {  
  39.             try {  
  40.                 mService.sendPassThroughCmddevice, keyCode, keyState);  
  41.                 return;  
  42.             } catch RemoteException e) {  
  43.                 Log.eTAG, "Error talking to BT service in sendPassThroughCmd)", e);  
  44.                 return;  
  45.             }  
  46.         }  
  47.         if mService == null) Log.wTAG, "Proxy not attached to service");  
  48.     }  

该类提供了蓝牙AVRCP控制profile。BluetoothAvrcpController是一个通过IPC方式控制AVRCP 服务的代理对象。

[java] view plaincopy 在CODE上查看代码片派生到我的代码片

  1. private final ServiceConnection mConnection = new ServiceConnection) {  
  2.     public void onServiceConnectedComponentName className, IBinder service) {  
  3.         if DBG) Log.dTAG, "Proxy object connected");  
  4.         mService = IBluetoothAvrcpController.Stub.asInterfaceservice);  

上述或得了服务对象。

aidl

[java] view plaincopy 在CODE上查看代码片派生到我的代码片

  1. frameworks/base/core/java/android/bluetooth/IBluetoothAvrcpController.aidl  
  2. interface IBluetoothAvrcpController {  
  3.     List<BluetoothDevice> getConnectedDevices);  
  4.     List<BluetoothDevice> getDevicesMatchingConnectionStatesin int[] states);  
  5.     int getConnectionStatein BluetoothDevice device);  
  6.     void sendPassThroughCmdin BluetoothDevice device, int keyCode, int keyState);  
  7. }  

这里描述的是service提供服务的接口函数。

package

[java] view plaincopy 在CODE上查看代码片派生到我的代码片

  1. packages/apps/Bluetooth/src/com/android/bluetooth/avrcp/AvrcpControllerService.java  
  2.   
  3. public class AvrcpControllerService extends ProfileService {  
  4.   
  5.     static {  
  6.         classInitNative);  
  7.     }  
  8.   
  9.     public AvrcpControllerService) {  
  10.         mMetadata = new Metadata);  
  11.         initNative);  
  12.     }  
  13. …  


这张图中BluetoothAvrcpControllerBinder了继承了IBluetoothAvrcpController内部内,这是和aidl关联的,这样可以调用aidl的方法接口。如 [java] view plaincopy 在CODE上查看代码片派生到我的代码片

  1. getConnectedDevices  
  2.   
  3.   
  4.         public List<BluetoothDevice> getConnectedDevices) {  
  5.             AvrcpControllerService service = getService);  
  6.             if service == nullreturn new ArrayList<BluetoothDevice>0);  
  7.             return service.getConnectedDevices);  
  8.         }  

该实现最终调用service的getConnectedDevices方法,就是这个文件里的方法。该方法调用native层实现。

上图左侧颜色相同的部分是调用关系

向上层回调关系

类似向下调用关系,直接上图

在升级到android 6之后,这个测试app在高通平台遇到了如下问题:

其提示我ACCESS_BLUETOOTH_AVRCP_CT_DATA权限没有,但是我的Manifest has definitions as follows:

[html] view plaincopy 在CODE上查看代码片派生到我的代码片

  1. <uses-permission android:name="android.permission.BLUETOOTH" />  
  2. <uses-permission android:name="android.permission.ACCESS_BLUETOOTH_AVRCP_CT_DATA" />  

I'v tried to remove BLUETOOTH permission to verify that it is surely can get the BLUETOOTH permission. So the question is why I can't get ACCESS_BLUETOOTH_AVRCP_CT_DATA permission.

Since ACCESS_BLUETOOTH_AVRCP_CT_DATA is defined in system Bluetooth.apk. My demo apk should have the same sign as system apks. 

The sign is in 签名证书(platform.pk8和platform.x509.pem),  which is in directory build/target/product/security. FOTA also use this files.

Android.mk

[html] view plaincopy 在CODE上查看代码片派生到我的代码片

  1. LOCAL_CERTIFICATE :platform  

or you may use jarsigner by yourself to sign your apk.

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注