Java层Binder使用(ServiceManager)

来源:互联网 发布:pkpm结构软件下载 编辑:程序博客网 时间:2024/05/19 03:19
 

转自:http://blog.csdn.net/jacklam200/article/details/37567409


跟上篇Binder使用一样,先通过例子来跟踪JavaBinder机制。本文参考了Binder In java

http://www.cnblogs.com/angeldevil/p/3328748.html,只作为研究Android记忆用

Init进程的init2阶段,系统启动了ServerThread,在ServerThread中会启动很多用Java实现的系统服务

(frameworks/base/services/java/com/android/server/SystemServer.java)

代码

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. power = new PowerManagerService();  
  2. ServiceManager.addService(Context.POWER_SERVICE, power);  
  3. context = ActivityManagerService.main(factoryTest);  
  4. Slog.i(TAG, "Display Manager");  
  5. display = new DisplayManagerService(context, wmHandler, uiHandler);  
  6. ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);  

通过ServiceManageraddService注册为binder server端。

 

我们以PowerManagerService为例,

(frameworks/base/services/java/com/android/server/power/)


PowerManagerService继承于IPowerManager.stub,IPowerManager.stub位于

(frameworks/base/core/java/com/android/os/IPowerManager.aidl)


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package android.os;  
  2.   
  3. import android.os.WorkSource;  
  4.   
  5. /** @hide */  
  6.   
  7. interface IPowerManager  
  8. {  
  9.     // WARNING: The first two methods must remain the first two methods because their  
  10.     // transaction numbers must not change unless IPowerManager.cpp is also updated.  
  11.     void acquireWakeLock(IBinder lock, int flags, String tag, in WorkSource ws);  
  12.     void releaseWakeLock(IBinder lock, int flags);  
  13.   
  14.     void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);  
  15.     boolean isWakeLockLevelSupported(int level);  
  16.   
  17.     void userActivity(long time, int event, int flags);  
  18.     void wakeUp(long time);  
  19.     void goToSleep(long time, int reason);  
  20.     void nap(long time);  
  21.   
  22.     boolean isScreenOn();  
  23.     void reboot(boolean confirm, String reason, boolean wait);  
  24.     void shutdown(boolean confirm, boolean wait);  
  25.     void crash(String message);  
  26.   
  27.     void setStayOnSetting(int val);  
  28.     void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs);  
  29.   
  30.     // temporarily overrides the screen brightness settings to allow the user to  
  31.     // see the effect of a settings change without applying it immediately  
  32.     void setTemporaryScreenBrightnessSettingOverride(int brightness);  
  33.     void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj);  
  34.   
  35.     // sets the attention light (used by phone app only)  
  36.     void setAttentionLight(boolean on, int color);  
  37. }  

Aidlandroid内部进程通信接口的描述语言,通过编译我们可以编译出



[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package android.os;  
  2.   
  3. /** @hide */  
  4. public interface IPowerManager extends android.os.IInterface {  
  5.     /** Local-side IPC implementation stub class. */  
  6.     public static abstract class Stub extends android.os.Binder implements  
  7.             android.os.IPowerManager {  
  8.         private static final java.lang.String DESCRIPTOR = "android.os.IPowerManager";  
  9.   
  10.         /** Construct the stub at attach it to the interface. */  
  11.         public Stub() {  
  12.             this.attachInterface(this, DESCRIPTOR);  
  13.         }  
  14.   
  15.         /** 
  16.          * Cast an IBinder object into an android.os.IPowerManager interface, 
  17.          * generating a proxy if needed. 
  18.          */  
  19.         public static android.os.IPowerManager asInterface(  
  20.                 android.os.IBinder obj) {  
  21.             if ((obj == null)) {  
  22.                 return null;  
  23.             }  
  24.             android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);  
  25.             if (((iin != null) && (iin instanceof android.os.IPowerManager))) {  
  26.                 return ((android.os.IPowerManager) iin);  
  27.             }  
  28.             return new android.os.IPowerManager.Stub.Proxy(obj);  
  29.         }  
  30.   
  31.         @Override  
  32.         public android.os.IBinder asBinder() {  
  33.             return this;  
  34.         }  
  35.   
  36.         @Override  
  37.         public boolean onTransact(int code, android.os.Parcel data,  
  38.                 android.os.Parcel reply, int flags)  
  39.                 throws android.os.RemoteException {  
  40.             switch (code) {  
  41.             case INTERFACE_TRANSACTION: {  
  42.                 reply.writeString(DESCRIPTOR);  
  43.                 return true;  
  44.             }  
  45.             case TRANSACTION_acquireWakeLock: {  
  46.                 data.enforceInterface(DESCRIPTOR);  
  47.                 android.os.IBinder _arg0;  
  48.                 _arg0 = data.readStrongBinder();  
  49.                 int _arg1;  
  50.                 _arg1 = data.readInt();  
  51.                 java.lang.String _arg2;  
  52.                 _arg2 = data.readString();  
  53.                 android.os.WorkSource _arg3;  
  54.                 if ((0 != data.readInt())) {  
  55.                     _arg3 = android.os.WorkSource.CREATOR  
  56.                             .createFromParcel(data);  
  57.                 } else {  
  58.                     _arg3 = null;  
  59.                 }  
  60.                 this.acquireWakeLock(_arg0, _arg1, _arg2, _arg3);  
  61.                 reply.writeNoException();  
  62.                 return true;  
  63.             }  
  64.             case TRANSACTION_releaseWakeLock: {  
  65.                 data.enforceInterface(DESCRIPTOR);  
  66.                 android.os.IBinder _arg0;  
  67.                 _arg0 = data.readStrongBinder();  
  68.                 int _arg1;  
  69.                 _arg1 = data.readInt();  
  70.                 this.releaseWakeLock(_arg0, _arg1);  
  71.                 reply.writeNoException();  
  72.                 return true;  
  73.             }  
  74.             case TRANSACTION_updateWakeLockWorkSource: {  
  75.                 data.enforceInterface(DESCRIPTOR);  
  76.                 android.os.IBinder _arg0;  
  77.                 _arg0 = data.readStrongBinder();  
  78.                 android.os.WorkSource _arg1;  
  79.                 if ((0 != data.readInt())) {  
  80.                     _arg1 = android.os.WorkSource.CREATOR  
  81.                             .createFromParcel(data);  
  82.                 } else {  
  83.                     _arg1 = null;  
  84.                 }  
  85.                 this.updateWakeLockWorkSource(_arg0, _arg1);  
  86.                 reply.writeNoException();  
  87.                 return true;  
  88.             }  
  89.             case TRANSACTION_isWakeLockLevelSupported: {  
  90.                 data.enforceInterface(DESCRIPTOR);  
  91.                 int _arg0;  
  92.                 _arg0 = data.readInt();  
  93.                 boolean _result = this.isWakeLockLevelSupported(_arg0);  
  94.                 reply.writeNoException();  
  95.                 reply.writeInt(((_result) ? (1) : (0)));  
  96.                 return true;  
  97.             }  
  98.             case TRANSACTION_userActivity: {  
  99.                 data.enforceInterface(DESCRIPTOR);  
  100.                 long _arg0;  
  101.                 _arg0 = data.readLong();  
  102.                 int _arg1;  
  103.                 _arg1 = data.readInt();  
  104.                 int _arg2;  
  105.                 _arg2 = data.readInt();  
  106.                 this.userActivity(_arg0, _arg1, _arg2);  
  107.                 reply.writeNoException();  
  108.                 return true;  
  109.             }  
  110.             case TRANSACTION_wakeUp: {  
  111.                 data.enforceInterface(DESCRIPTOR);  
  112.                 long _arg0;  
  113.                 _arg0 = data.readLong();  
  114.                 this.wakeUp(_arg0);  
  115.                 reply.writeNoException();  
  116.                 return true;  
  117.             }  
  118.             case TRANSACTION_goToSleep: {  
  119.                 data.enforceInterface(DESCRIPTOR);  
  120.                 long _arg0;  
  121.                 _arg0 = data.readLong();  
  122.                 int _arg1;  
  123.                 _arg1 = data.readInt();  
  124.                 this.goToSleep(_arg0, _arg1);  
  125.                 reply.writeNoException();  
  126.                 return true;  
  127.             }  
  128.             case TRANSACTION_nap: {  
  129.                 data.enforceInterface(DESCRIPTOR);  
  130.                 long _arg0;  
  131.                 _arg0 = data.readLong();  
  132.                 this.nap(_arg0);  
  133.                 reply.writeNoException();  
  134.                 return true;  
  135.             }  
  136.             case TRANSACTION_isScreenOn: {  
  137.                 data.enforceInterface(DESCRIPTOR);  
  138.                 boolean _result = this.isScreenOn();  
  139.                 reply.writeNoException();  
  140.                 reply.writeInt(((_result) ? (1) : (0)));  
  141.                 return true;  
  142.             }  
  143.             case TRANSACTION_reboot: {  
  144.                 data.enforceInterface(DESCRIPTOR);  
  145.                 boolean _arg0;  
  146.                 _arg0 = (0 != data.readInt());  
  147.                 java.lang.String _arg1;  
  148.                 _arg1 = data.readString();  
  149.                 boolean _arg2;  
  150.                 _arg2 = (0 != data.readInt());  
  151.                 this.reboot(_arg0, _arg1, _arg2);  
  152.                 reply.writeNoException();  
  153.                 return true;  
  154.             }  
  155.             case TRANSACTION_shutdown: {  
  156.                 data.enforceInterface(DESCRIPTOR);  
  157.                 boolean _arg0;  
  158.                 _arg0 = (0 != data.readInt());  
  159.                 boolean _arg1;  
  160.                 _arg1 = (0 != data.readInt());  
  161.                 this.shutdown(_arg0, _arg1);  
  162.                 reply.writeNoException();  
  163.                 return true;  
  164.             }  
  165.             case TRANSACTION_crash: {  
  166.                 data.enforceInterface(DESCRIPTOR);  
  167.                 java.lang.String _arg0;  
  168.                 _arg0 = data.readString();  
  169.                 this.crash(_arg0);  
  170.                 reply.writeNoException();  
  171.                 return true;  
  172.             }  
  173.             case TRANSACTION_setStayOnSetting: {  
  174.                 data.enforceInterface(DESCRIPTOR);  
  175.                 int _arg0;  
  176.                 _arg0 = data.readInt();  
  177.                 this.setStayOnSetting(_arg0);  
  178.                 reply.writeNoException();  
  179.                 return true;  
  180.             }  
  181.             case TRANSACTION_setMaximumScreenOffTimeoutFromDeviceAdmin: {  
  182.                 data.enforceInterface(DESCRIPTOR);  
  183.                 int _arg0;  
  184.                 _arg0 = data.readInt();  
  185.                 this.setMaximumScreenOffTimeoutFromDeviceAdmin(_arg0);  
  186.                 reply.writeNoException();  
  187.                 return true;  
  188.             }  
  189.             case TRANSACTION_setTemporaryScreenBrightnessSettingOverride: {  
  190.                 data.enforceInterface(DESCRIPTOR);  
  191.                 int _arg0;  
  192.                 _arg0 = data.readInt();  
  193.                 this.setTemporaryScreenBrightnessSettingOverride(_arg0);  
  194.                 reply.writeNoException();  
  195.                 return true;  
  196.             }  
  197.             case TRANSACTION_setTemporaryScreenAutoBrightnessAdjustmentSettingOverride: {  
  198.                 data.enforceInterface(DESCRIPTOR);  
  199.                 float _arg0;  
  200.                 _arg0 = data.readFloat();  
  201.                 this.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(_arg0);  
  202.                 reply.writeNoException();  
  203.                 return true;  
  204.             }  
  205.             case TRANSACTION_setAttentionLight: {  
  206.                 data.enforceInterface(DESCRIPTOR);  
  207.                 boolean _arg0;  
  208.                 _arg0 = (0 != data.readInt());  
  209.                 int _arg1;  
  210.                 _arg1 = data.readInt();  
  211.                 this.setAttentionLight(_arg0, _arg1);  
  212.                 reply.writeNoException();  
  213.                 return true;  
  214.             }  
  215.             }  
  216.             return super.onTransact(code, data, reply, flags);  
  217.         }  
  218.   
  219.         private static class Proxy implements android.os.IPowerManager {  
  220.             private android.os.IBinder mRemote;  
  221.   
  222.             Proxy(android.os.IBinder remote) {  
  223.                 mRemote = remote;  
  224.             }  
  225.   
  226.             @Override  
  227.             public android.os.IBinder asBinder() {  
  228.                 return mRemote;  
  229.             }  
  230.   
  231.             public java.lang.String getInterfaceDescriptor() {  
  232.                 return DESCRIPTOR;  
  233.             }  
  234.   
  235.             // WARNING: The first two methods must remain the first two methods  
  236.             // because their  
  237.             // transaction numbers must not change unless IPowerManager.cpp is  
  238.             // also updated.  
  239.   
  240.             @Override  
  241.             public void acquireWakeLock(android.os.IBinder lock, int flags,  
  242.                     java.lang.String tag, android.os.WorkSource ws)  
  243.                     throws android.os.RemoteException {  
  244.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  245.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  246.                 try {  
  247.                     _data.writeInterfaceToken(DESCRIPTOR);  
  248.                     _data.writeStrongBinder(lock);  
  249.                     _data.writeInt(flags);  
  250.                     _data.writeString(tag);  
  251.                     if ((ws != null)) {  
  252.                         _data.writeInt(1);  
  253.                         ws.writeToParcel(_data, 0);  
  254.                     } else {  
  255.                         _data.writeInt(0);  
  256.                     }  
  257.                     mRemote.transact(Stub.TRANSACTION_acquireWakeLock, _data,  
  258.                             _reply, 0);  
  259.                     _reply.readException();  
  260.                 } finally {  
  261.                     _reply.recycle();  
  262.                     _data.recycle();  
  263.                 }  
  264.             }  
  265.   
  266.             @Override  
  267.             public void releaseWakeLock(android.os.IBinder lock, int flags)  
  268.                     throws android.os.RemoteException {  
  269.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  270.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  271.                 try {  
  272.                     _data.writeInterfaceToken(DESCRIPTOR);  
  273.                     _data.writeStrongBinder(lock);  
  274.                     _data.writeInt(flags);  
  275.                     mRemote.transact(Stub.TRANSACTION_releaseWakeLock, _data,  
  276.                             _reply, 0);  
  277.                     _reply.readException();  
  278.                 } finally {  
  279.                     _reply.recycle();  
  280.                     _data.recycle();  
  281.                 }  
  282.             }  
  283.   
  284.             @Override  
  285.             public void updateWakeLockWorkSource(android.os.IBinder lock,  
  286.                     android.os.WorkSource ws) throws android.os.RemoteException {  
  287.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  288.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  289.                 try {  
  290.                     _data.writeInterfaceToken(DESCRIPTOR);  
  291.                     _data.writeStrongBinder(lock);  
  292.                     if ((ws != null)) {  
  293.                         _data.writeInt(1);  
  294.                         ws.writeToParcel(_data, 0);  
  295.                     } else {  
  296.                         _data.writeInt(0);  
  297.                     }  
  298.                     mRemote.transact(Stub.TRANSACTION_updateWakeLockWorkSource,  
  299.                             _data, _reply, 0);  
  300.                     _reply.readException();  
  301.                 } finally {  
  302.                     _reply.recycle();  
  303.                     _data.recycle();  
  304.                 }  
  305.             }  
  306.   
  307.             @Override  
  308.             public boolean isWakeLockLevelSupported(int level)  
  309.                     throws android.os.RemoteException {  
  310.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  311.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  312.                 boolean _result;  
  313.                 try {  
  314.                     _data.writeInterfaceToken(DESCRIPTOR);  
  315.                     _data.writeInt(level);  
  316.                     mRemote.transact(Stub.TRANSACTION_isWakeLockLevelSupported,  
  317.                             _data, _reply, 0);  
  318.                     _reply.readException();  
  319.                     _result = (0 != _reply.readInt());  
  320.                 } finally {  
  321.                     _reply.recycle();  
  322.                     _data.recycle();  
  323.                 }  
  324.                 return _result;  
  325.             }  
  326.   
  327.             @Override  
  328.             public void userActivity(long time, int event, int flags)  
  329.                     throws android.os.RemoteException {  
  330.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  331.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  332.                 try {  
  333.                     _data.writeInterfaceToken(DESCRIPTOR);  
  334.                     _data.writeLong(time);  
  335.                     _data.writeInt(event);  
  336.                     _data.writeInt(flags);  
  337.                     mRemote.transact(Stub.TRANSACTION_userActivity, _data,  
  338.                             _reply, 0);  
  339.                     _reply.readException();  
  340.                 } finally {  
  341.                     _reply.recycle();  
  342.                     _data.recycle();  
  343.                 }  
  344.             }  
  345.   
  346.             @Override  
  347.             public void wakeUp(long time) throws android.os.RemoteException {  
  348.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  349.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  350.                 try {  
  351.                     _data.writeInterfaceToken(DESCRIPTOR);  
  352.                     _data.writeLong(time);  
  353.                     mRemote.transact(Stub.TRANSACTION_wakeUp, _data, _reply, 0);  
  354.                     _reply.readException();  
  355.                 } finally {  
  356.                     _reply.recycle();  
  357.                     _data.recycle();  
  358.                 }  
  359.             }  
  360.   
  361.             @Override  
  362.             public void goToSleep(long time, int reason)  
  363.                     throws android.os.RemoteException {  
  364.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  365.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  366.                 try {  
  367.                     _data.writeInterfaceToken(DESCRIPTOR);  
  368.                     _data.writeLong(time);  
  369.                     _data.writeInt(reason);  
  370.                     mRemote.transact(Stub.TRANSACTION_goToSleep, _data, _reply,  
  371.                             0);  
  372.                     _reply.readException();  
  373.                 } finally {  
  374.                     _reply.recycle();  
  375.                     _data.recycle();  
  376.                 }  
  377.             }  
  378.   
  379.             @Override  
  380.             public void nap(long time) throws android.os.RemoteException {  
  381.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  382.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  383.                 try {  
  384.                     _data.writeInterfaceToken(DESCRIPTOR);  
  385.                     _data.writeLong(time);  
  386.                     mRemote.transact(Stub.TRANSACTION_nap, _data, _reply, 0);  
  387.                     _reply.readException();  
  388.                 } finally {  
  389.                     _reply.recycle();  
  390.                     _data.recycle();  
  391.                 }  
  392.             }  
  393.   
  394.             @Override  
  395.             public boolean isScreenOn() throws android.os.RemoteException {  
  396.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  397.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  398.                 boolean _result;  
  399.                 try {  
  400.                     _data.writeInterfaceToken(DESCRIPTOR);  
  401.                     mRemote.transact(Stub.TRANSACTION_isScreenOn, _data,  
  402.                             _reply, 0);  
  403.                     _reply.readException();  
  404.                     _result = (0 != _reply.readInt());  
  405.                 } finally {  
  406.                     _reply.recycle();  
  407.                     _data.recycle();  
  408.                 }  
  409.                 return _result;  
  410.             }  
  411.   
  412.             @Override  
  413.             public void reboot(boolean confirm, java.lang.String reason,  
  414.                     boolean wait) throws android.os.RemoteException {  
  415.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  416.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  417.                 try {  
  418.                     _data.writeInterfaceToken(DESCRIPTOR);  
  419.                     _data.writeInt(((confirm) ? (1) : (0)));  
  420.                     _data.writeString(reason);  
  421.                     _data.writeInt(((wait) ? (1) : (0)));  
  422.                     mRemote.transact(Stub.TRANSACTION_reboot, _data, _reply, 0);  
  423.                     _reply.readException();  
  424.                 } finally {  
  425.                     _reply.recycle();  
  426.                     _data.recycle();  
  427.                 }  
  428.             }  
  429.   
  430.             @Override  
  431.             public void shutdown(boolean confirm, boolean wait)  
  432.                     throws android.os.RemoteException {  
  433.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  434.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  435.                 try {  
  436.                     _data.writeInterfaceToken(DESCRIPTOR);  
  437.                     _data.writeInt(((confirm) ? (1) : (0)));  
  438.                     _data.writeInt(((wait) ? (1) : (0)));  
  439.                     mRemote.transact(Stub.TRANSACTION_shutdown, _data, _reply,  
  440.                             0);  
  441.                     _reply.readException();  
  442.                 } finally {  
  443.                     _reply.recycle();  
  444.                     _data.recycle();  
  445.                 }  
  446.             }  
  447.   
  448.             @Override  
  449.             public void crash(java.lang.String message)  
  450.                     throws android.os.RemoteException {  
  451.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  452.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  453.                 try {  
  454.                     _data.writeInterfaceToken(DESCRIPTOR);  
  455.                     _data.writeString(message);  
  456.                     mRemote.transact(Stub.TRANSACTION_crash, _data, _reply, 0);  
  457.                     _reply.readException();  
  458.                 } finally {  
  459.                     _reply.recycle();  
  460.                     _data.recycle();  
  461.                 }  
  462.             }  
  463.   
  464.             @Override  
  465.             public void setStayOnSetting(int val)  
  466.                     throws android.os.RemoteException {  
  467.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  468.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  469.                 try {  
  470.                     _data.writeInterfaceToken(DESCRIPTOR);  
  471.                     _data.writeInt(val);  
  472.                     mRemote.transact(Stub.TRANSACTION_setStayOnSetting, _data,  
  473.                             _reply, 0);  
  474.                     _reply.readException();  
  475.                 } finally {  
  476.                     _reply.recycle();  
  477.                     _data.recycle();  
  478.                 }  
  479.             }  
  480.   
  481.             @Override  
  482.             public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs)  
  483.                     throws android.os.RemoteException {  
  484.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  485.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  486.                 try {  
  487.                     _data.writeInterfaceToken(DESCRIPTOR);  
  488.                     _data.writeInt(timeMs);  
  489.                     mRemote.transact(  
  490.                             Stub.TRANSACTION_setMaximumScreenOffTimeoutFromDeviceAdmin,  
  491.                             _data, _reply, 0);  
  492.                     _reply.readException();  
  493.                 } finally {  
  494.                     _reply.recycle();  
  495.                     _data.recycle();  
  496.                 }  
  497.             }  
  498.   
  499.             // temporarily overrides the screen brightness settings to allow the  
  500.             // user to  
  501.             // see the effect of a settings change without applying it  
  502.             // immediately  
  503.   
  504.             @Override  
  505.             public void setTemporaryScreenBrightnessSettingOverride(  
  506.                     int brightness) throws android.os.RemoteException {  
  507.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  508.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  509.                 try {  
  510.                     _data.writeInterfaceToken(DESCRIPTOR);  
  511.                     _data.writeInt(brightness);  
  512.                     mRemote.transact(  
  513.                             Stub.TRANSACTION_setTemporaryScreenBrightnessSettingOverride,  
  514.                             _data, _reply, 0);  
  515.                     _reply.readException();  
  516.                 } finally {  
  517.                     _reply.recycle();  
  518.                     _data.recycle();  
  519.                 }  
  520.             }  
  521.   
  522.             @Override  
  523.             public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(  
  524.                     float adj) throws android.os.RemoteException {  
  525.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  526.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  527.                 try {  
  528.                     _data.writeInterfaceToken(DESCRIPTOR);  
  529.                     _data.writeFloat(adj);  
  530.                     mRemote.transact(  
  531.                             Stub.TRANSACTION_setTemporaryScreenAutoBrightnessAdjustmentSettingOverride,  
  532.                             _data, _reply, 0);  
  533.                     _reply.readException();  
  534.                 } finally {  
  535.                     _reply.recycle();  
  536.                     _data.recycle();  
  537.                 }  
  538.             }  
  539.   
  540.             // sets the attention light (used by phone app only)  
  541.   
  542.             @Override  
  543.             public void setAttentionLight(boolean on, int color)  
  544.                     throws android.os.RemoteException {  
  545.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  546.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  547.                 try {  
  548.                     _data.writeInterfaceToken(DESCRIPTOR);  
  549.                     _data.writeInt(((on) ? (1) : (0)));  
  550.                     _data.writeInt(color);  
  551.                     mRemote.transact(Stub.TRANSACTION_setAttentionLight, _data,  
  552.                             _reply, 0);  
  553.                     _reply.readException();  
  554.                 } finally {  
  555.                     _reply.recycle();  
  556.                     _data.recycle();  
  557.                 }  
  558.             }  
  559.         }  
  560.   
  561.         static final int TRANSACTION_acquireWakeLock = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);  
  562.         static final int TRANSACTION_releaseWakeLock = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);  
  563.         static final int TRANSACTION_updateWakeLockWorkSource = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);  
  564.         static final int TRANSACTION_isWakeLockLevelSupported = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);  
  565.         static final int TRANSACTION_userActivity = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);  
  566.         static final int TRANSACTION_wakeUp = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);  
  567.         static final int TRANSACTION_goToSleep = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);  
  568.         static final int TRANSACTION_nap = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);  
  569.         static final int TRANSACTION_isScreenOn = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);  
  570.         static final int TRANSACTION_reboot = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);  
  571.         static final int TRANSACTION_shutdown = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10);  
  572.         static final int TRANSACTION_crash = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11);  
  573.         static final int TRANSACTION_setStayOnSetting = (android.os.IBinder.FIRST_CALL_TRANSACTION + 12);  
  574.         static final int TRANSACTION_setMaximumScreenOffTimeoutFromDeviceAdmin = (android.os.IBinder.FIRST_CALL_TRANSACTION + 13);  
  575.         static final int TRANSACTION_setTemporaryScreenBrightnessSettingOverride = (android.os.IBinder.FIRST_CALL_TRANSACTION + 14);  
  576.         static final int TRANSACTION_setTemporaryScreenAutoBrightnessAdjustmentSettingOverride = (android.os.IBinder.FIRST_CALL_TRANSACTION + 15);  
  577.         static final int TRANSACTION_setAttentionLight = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16);  
  578.     }  
  579.   
  580.     // WARNING: The first two methods must remain the first two methods because  
  581.     // their  
  582.     // transaction numbers must not change unless IPowerManager.cpp is also  
  583.     // updated.  
  584.   
  585.     public void acquireWakeLock(android.os.IBinder lock, int flags,  
  586.             java.lang.String tag, android.os.WorkSource ws)  
  587.             throws android.os.RemoteException;  
  588.   
  589.     public void releaseWakeLock(android.os.IBinder lock, int flags)  
  590.             throws android.os.RemoteException;  
  591.   
  592.     public void updateWakeLockWorkSource(android.os.IBinder lock,  
  593.             android.os.WorkSource ws) throws android.os.RemoteException;  
  594.   
  595.     public boolean isWakeLockLevelSupported(int level)  
  596.             throws android.os.RemoteException;  
  597.   
  598.     public void userActivity(long time, int event, int flags)  
  599.             throws android.os.RemoteException;  
  600.   
  601.     public void wakeUp(long time) throws android.os.RemoteException;  
  602.   
  603.     public void goToSleep(long time, int reason)  
  604.             throws android.os.RemoteException;  
  605.   
  606.     public void nap(long time) throws android.os.RemoteException;  
  607.   
  608.     public boolean isScreenOn() throws android.os.RemoteException;  
  609.   
  610.     public void reboot(boolean confirm, java.lang.String reason, boolean wait)  
  611.             throws android.os.RemoteException;  
  612.   
  613.     public void shutdown(boolean confirm, boolean wait)  
  614.             throws android.os.RemoteException;  
  615.   
  616.     public void crash(java.lang.String message)  
  617.             throws android.os.RemoteException;  
  618.   
  619.     public void setStayOnSetting(int val) throws android.os.RemoteException;  
  620.   
  621.     public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs)  
  622.             throws android.os.RemoteException;  
  623.   
  624.     // temporarily overrides the screen brightness settings to allow the user to  
  625.     // see the effect of a settings change without applying it immediately  
  626.   
  627.     public void setTemporaryScreenBrightnessSettingOverride(int brightness)  
  628.             throws android.os.RemoteException;  
  629.   
  630.     public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(  
  631.             float adj) throws android.os.RemoteException;  
  632.   
  633.     // sets the attention light (used by phone app only)  
  634.   
  635.     public void setAttentionLight(boolean on, int color)  
  636.             throws android.os.RemoteException;  
  637. }  

我们可以从代码中看到Stub是一个抽象类,里面还有个proxy

Stub提供asInterface asBinder onTransact 


                    PowerManagerService




其实这个是不是看起来很熟悉呢,我们回忆下MediaplayerServiceMediaplayerService 继承于BnMediaPlayerService,BnMediaPlayerService刚好跟这个Stub很类似,

然后我们再看看proxy类是不是跟BpMediaPlayerService类似,而IPowerManager则跟IMediaPlayerService类似,而PowerManagerServic则跟MediaplayerService一样实现功能。

Stub继承于Binder,而在Binder构造函数中调用nativeinit

framework\base\core\jni\android_util_Binder.cpp

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static void android_os_Binder_init(JNIEnv* env, jobject obj)  
  2. {  
  3.     JavaBBinderHolder* jbh = new JavaBBinderHolder();  
  4.     if (jbh == NULL) {  
  5.         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);  
  6.         return;  
  7.     }  
  8.     ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);  
  9.     jbh->incStrong((void*)android_os_Binder_init);  
  10.     env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);  
  11. }  

可以看出创建了一个JavaBBinderHolder,然后把值强制转int,返回给javaBinder类的

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private int mObject;  
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. </pre><p class="p0" style="margin-bottom:0pt; margin-top:0pt"><span style="font-size:10pt; font-family:宋体">在<span style="font-family:Consolas">AndroidRuntine::startReg</span><span style="font-family:宋体">中会调用</span><span style="font-family:Consolas">register_android_os_Binder</span><span style="font-family:宋体">,</span><span style="font-family:Consolas">register_android_os_Binder</span><span style="font-family:宋体">会调用</span><span style="font-family:Consolas">int_register_android_os_Binder</span><span style="font-family:宋体">等函数建立</span><span style="font-family:Consolas">Java</span><span style="font-family:宋体">层</span><span style="font-family:Consolas">Binder</span><span style="font-family:宋体">、</span><span style="font-family:Consolas">BinderProxy</span><span style="font-family:宋体">、</span><span style="font-family:Consolas">BinderInternal</span><span style="font-family:宋体">、</span><span style="font-family:Consolas">Log</span><span style="font-family:宋体">等与</span><span style="font-family:Consolas">Native</span><span style="font-family:宋体">层的映射关系</span></span><span style="font-size:10pt; font-family:宋体"></span></p><p class="p0" style="margin-bottom:0pt; margin-top:0pt"><span style="font-size:10pt; font-family:宋体">Native<span style="font-family:宋体">层对</span><span style="font-family:Consolas">java</span><span style="font-family:宋体">层的反射</span></span><span style="font-size:10pt; font-family:宋体"></span></p><pre code_snippet_id="422453" snippet_file_name="blog_20140708_7_4207713" name="code" class="cpp">static int int_register_android_os_Binder(JNIEnv* env)  
  2. {  
  3.     jclass clazz;  
  4.   
  5.     clazz = env->FindClass(kBinderPathName);  
  6.     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");  
  7.   
  8.     gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);  
  9.     gBinderOffsets.mExecTransact  
  10.         = env->GetMethodID(clazz, "execTransact""(IIII)Z");  
  11.     assert(gBinderOffsets.mExecTransact);  
  12.   
  13.     gBinderOffsets.mObject  
  14.         = env->GetFieldID(clazz, "mObject""I");  
  15.     assert(gBinderOffsets.mObject);  
  16.   
  17.     return AndroidRuntime::registerNativeMethods(  
  18.         env, kBinderPathName,  
  19.         gBinderMethods, NELEM(gBinderMethods));  
  20. }  

JavaBBinderHolder是什么呢?

android_os_Binder_initnew了一个JavaBBinderHolderJavaBBinderHolder get()函数new了一个JavaBBinder保存到了自己的成员sp<JavaBBinder> mBinder中。而JavaBBinder继承自Native层的BBinder,还记得在IPC thread中接收binder的数据,并且通过BBinder回调的,然后再调用BnXXonTransact执行Server端的相关命令

有了这些我们可以猜测IPowerManager.aidl编译出来的文件就是binder机制中Server


 

 

现在既然知道了PowerManagerServicebinderserver端,那他怎么在java层向binder注册呢,还有client端怎么在java层获取Service

 

首先,按着binder的机制,ServiceManager.addService(Context.POWER_SERVICE, power);

我们查看ServiceManager


(frameworks/base/core/java/android/os/ServiceManager.java)

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public static void addService(String name, IBinder service, boolean allowIsolated) {  
  2.         try {  
  3.             getIServiceManager().addService(name, service, allowIsolated);  
  4.         } catch (RemoteException e) {  
  5.             Log.e(TAG, "error in addService", e);  
  6.         }  
  7.     }  
  8.       
  9.  private static IServiceManager getIServiceManager() {  
  10.         if (sServiceManager != null) {  
  11.             return sServiceManager;  
  12.         }  
  13.   
  14.         // Find the service manager  
  15.         sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  
  16.         return sServiceManager;  
  17. }  

从代码可以看出addService是调用了ServiceManagerNative,而asInterface则是传入一个IBinder对象,并创建出ServiceManagerProxy,是不是跟Mediaplayer Server获取binder smgr有点类似?

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public void addService(String name, IBinder service, boolean allowIsolated)  
  2.             throws RemoteException {  
  3.         Parcel data = Parcel.obtain();  
  4.         Parcel reply = Parcel.obtain();  
  5.         data.writeInterfaceToken(IServiceManager.descriptor);  
  6.         data.writeString(name);  
  7.         data.writeStrongBinder(service);  
  8.         data.writeInt(allowIsolated ? 1 : 0);  
  9.         mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);  
  10.         reply.recycle();  
  11.         data.recycle();  
  12.     }  

我们在看看BinderInternal.getContextObject(),他是一个native函数,我们到native层看看是不是跟Mediaplayer Server一样通过new Bpbinder(0),获取到Binder smgr

framework\base\core\jni\android_util_Binder.cpp

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)  
  2. {  
  3.     sp<IBinder> b = ProcessState::self()->getContextObject(NULL);  
  4.     return javaObjectForIBinder(env, b);  
  5. }  
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)  
  2. {  
  3.     if (val == NULL) return NULL;  
  4.   
  5.     if (val->checkSubclass(&gBinderOffsets)) {// BpBinder没重写,返回false  
  6.         // One of our own!  
  7.         jobject object = static_cast<JavaBBinder*>(val.get())->object();  
  8.         LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);  
  9.         return object;  
  10.     }  
  11.   
  12.     // For the rest of the function we will hold this lock, to serialize  
  13.     // looking/creation of Java proxies for native Binder proxies.  
  14.     AutoMutex _l(mProxyLock);  
  15.   
  16.     // Someone else's...  do we know about it?  
  17. // BpBinder没有带proxy过来  
  18.     jobject object = (jobject)val->findObject(&gBinderProxyOffsets);  
  19.     if (object != NULL) {  
  20.         jobject res = jniGetReferent(env, object);  
  21.         if (res != NULL) {  
  22.             ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);  
  23.             return res;  
  24.         }  
  25.         LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());  
  26.         android_atomic_dec(&gNumProxyRefs);  
  27.         val->detachObject(&gBinderProxyOffsets);  
  28.         env->DeleteGlobalRef(object);  
  29.     }  
  30.     // 因为proxy,创建一个proxy  
  31.    // const char* const kBinderProxyPathName = "android/os/BinderProxy";  
  32.     object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);  
  33.     if (object != NULL) {  
  34.         LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);  
  35.         // The proxy holds a reference to the native object.  
  36.         env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get()); // 把BpBinder(0)赋值给BinderProxy 的mObject  
  37.         val->incStrong((void*)javaObjectForIBinder);  
  38.   
  39.         // The native object needs to hold a weak reference back to the  
  40.         // proxy, so we can retrieve the same proxy if it is still active.  
  41.         jobject refObject = env->NewGlobalRef(  
  42.                 env->GetObjectField(object, gBinderProxyOffsets.mSelf));  
  43.         val->attachObject(&gBinderProxyOffsets, refObject,  
  44.                 jnienv_to_javavm(env), proxy_cleanup);  
  45.   
  46.         // Also remember the death recipients registered on this proxy  
  47.         sp<DeathRecipientList> drl = new DeathRecipientList;  
  48.         drl->incStrong((void*)javaObjectForIBinder);  
  49.         env->SetIntField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jint>(drl.get()));  
  50.   
  51.         // Note that a new object reference has been created.  
  52.         android_atomic_inc(&gNumProxyRefs);  
  53.         incRefsCreated(env);  
  54.     }  
  55.   
  56.     return object;  
  57. }  

可以看出返回了android.os.BinderProxy

也就是说ServiceManagerProxymRemote带的BinderProxy

frameworks/base/core/java/com/android/os/Binder.java)

而里面的Transact是调用native层的android_os_BinderProxy_transact

frameworks/base/core/jni/android/android.util.Binder.cpp)



[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,  
  2.         jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException  
  3. {  
  4.     if (dataObj == NULL) {  
  5.         jniThrowNullPointerException(env, NULL);  
  6.         return JNI_FALSE;  
  7.     }  
  8.   
  9.     Parcel* data = parcelForJavaObject(env, dataObj);  
  10.     if (data == NULL) {  
  11.         return JNI_FALSE;  
  12.     }  
  13.     Parcel* reply = parcelForJavaObject(env, replyObj);  
  14.     if (reply == NULL && replyObj != NULL) {  
  15.         return JNI_FALSE;  
  16.     }  
  17.   
  18.     IBinder* target = (IBinder*)  
  19.         env->GetIntField(obj, gBinderProxyOffsets.mObject); //此时的mObject为BpBinder(0);   
  20.     if (target == NULL) {  
  21.         jniThrowException(env, "java/lang/IllegalStateException""Binder has been finalized!");  
  22.         return JNI_FALSE;  
  23.     }  
  24.   
  25.     ALOGV("Java code calling transact on %p in Java object %p with code %d\n",  
  26.             target, obj, code);  
  27.   
  28.     // Only log the binder call duration for things on the Java-level main thread.  
  29.     // But if we don't  
  30.     const bool time_binder_calls = should_time_binder_calls();  
  31.   
  32.     int64_t start_millis;  
  33.     if (time_binder_calls) {  
  34.         start_millis = uptimeMillis();  
  35.     }  
  36.     //printf("Transact from Java code to %p sending: ", target); data->print();  
  37.     status_t err = target->transact(code, *data, reply, flags);  
  38.     //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();  
  39.     if (time_binder_calls) {  
  40.         conditionally_log_binder_call(start_millis, target, code);  
  41.     }  
  42.   
  43.     if (err == NO_ERROR) {  
  44.         return JNI_TRUE;  
  45.     } else if (err == UNKNOWN_TRANSACTION) {  
  46.         return JNI_FALSE;  
  47.     }  
  48.   
  49.     signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);  
  50.     return JNI_FALSE;  
  51. }  

看出status_t err = target->transact(code, *data, reply, flags);

是调用了BinderProxy里面mObjectBpbinder(0))的transact来传输数据

 




可以看到跟Mediaplayer Server一样 获取了smgr binder,并通过他通讯给smgr binder

那我们可以归结出ServiceManagerProxy BpServicemanager,并带入了smgr binder,跟binder通讯

 

 

 

其次,我们在java层获取Service是通过

Context.getSystemService(Context.POWER_SERVICE);

getSystemService位于ContextImpl

(frameworks/base/core/java/com/android/app/ContextImpl.java)


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Override  
  2.     public Object getSystemService(String name) {  
  3.         ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);  
  4.         return fetcher == null ? null : fetcher.getService(this);  
  5. }  


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Static{  
  2. ....  
  3.  registerService(POWER_SERVICE, new ServiceFetcher() {  
  4.                 public Object createService(ContextImpl ctx) {  
  5.                     IBinder b = ServiceManager.getService(POWER_SERVICE);  
  6.                     IPowerManager service = IPowerManager.Stub.asInterface(b);  
  7.                     return new PowerManager(ctx.getOuterContext(),  
  8.                             service, ctx.mMainThread.getHandler());  
  9.                 }});  
  10. ....  
  11. };  

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static class ServiceFetcher {  
  2.         int mContextCacheIndex = -1;  
  3.   
  4.         /** 
  5.          * Main entrypoint; only override if you don't need caching. 
  6.          */  
  7.         public Object getService(ContextImpl ctx) {  
  8.             ArrayList<Object> cache = ctx.mServiceCache;  
  9.             Object service;  
  10.             synchronized (cache) {  
  11.                 if (cache.size() == 0) {  
  12.                     // Initialize the cache vector on first access.  
  13.                     // At this point sNextPerContextServiceCacheIndex  
  14.                     // is the number of potential services that are  
  15.                     // cached per-Context.  
  16.                     for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {  
  17.                         cache.add(null);  
  18.                     }  
  19.                 } else {  
  20.                     service = cache.get(mContextCacheIndex);  
  21.                     if (service != null) {  
  22.                         return service;  
  23.                     }  
  24.                 }  
  25.                 service = createService(ctx);  
  26.                 cache.set(mContextCacheIndex, service);  
  27.                 return service;  
  28.             }  
  29.         }  
  30.   
  31.         /** 
  32.          * Override this to create a new per-Context instance of the 
  33.          * service.  getService() will handle locking and caching. 
  34.          */  
  35.         public Object createService(ContextImpl ctx) {  
  36.             throw new RuntimeException("Not implemented");  
  37.         }  
  38.     }  


从代码里面看出,要是从cache中获取不到service,那么


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Static{  
  2. ....  
  3.  registerService(POWER_SERVICE, new ServiceFetcher() {  
  4.                 public Object createService(ContextImpl ctx) {  
  5.                     IBinder b = ServiceManager.getService(POWER_SERVICE);  
  6.                     IPowerManager service = IPowerManager.Stub.asInterface(b);  
  7.                     return new PowerManager(ctx.getOuterContext(),  
  8.                             service, ctx.mMainThread.getHandler());  
  9.                 }});  
  10. ....  
  11. };  


通过ServiceManager获取到PowerService,并通过Stub转化成IPowerManager,并创建了PowerManager返回给客户端调用。

getService函数就跟addService一样,先获取smgr,然后用ServiceManagerProxy getService获取到binder,然后通过stubasInterface转化为IPowerManager(实际是让其带ServiceBinder

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public static android.os.IPowerManager asInterface(  
  2.                 android.os.IBinder obj) {  
  3.             if ((obj == null)) {  
  4.                 return null;  
  5.             }  
  6.             android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);  
  7.             if (((iin != null) && (iin instanceof android.os.IPowerManager))) {  
  8.                 return ((android.os.IPowerManager) iin);  
  9.             }  
  10.             return new android.os.IPowerManager.Stub.Proxy(obj);  
  11.         }  


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Proxy(android.os.IBinder remote) {  
  2.                 mRemote = remote;  
  3.             }  
0 0
原创粉丝点击