自顶向下分析Binder【1】—— Binder实例篇

欢迎转载,转载请注明:http://blog.csdn.net/zhgxhuaa

一个Binder实例

我们Binder的学习将从以下的一个实例開始。依据Android文档中的描写叙述,创建一个Binder服务主要包含例如以下3步:

以下详细看一下在eclipse中是怎样开发一个Binder应用的。

第一步:在project文件夹下定义aidl文件。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

package com.zxh.ipc;

import com.zxh.ipc.PermissionInfo;

interface ITestManager{

    int checkPermission(String
permName, String pkgName);

    

    int checkUidPermission(String
permName, 
int uid);

    

    boolean addPermission(in
PermissionInfo info);

    

    void removePermission(String
name);

    boolean isProtectedBroadcast(String
actionName);

}

第二步:在定义aidl后,eclipse在project文件夹的gen文件夹下会自己主动生成相应的接口,以下是有aidl自己主动生成的Java代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

package com.zxh.ipc;

 

public interface ITestManager extends android.os.IInterface

{

    /**
Local-side IPC implementation stub class. */

    public static abstract class Stub extends android.os.Binder implements com.zxh.ipc.ITestManager

    {

        private static final java.lang.String
DESCRIPTOR = 
"com.zxh.ipc.ITestManager";

 

        /**
Construct the stub at attach it to the interface. */

        public Stub()

        {

            this.attachInterface(this,
DESCRIPTOR);

        }

 

        /**

         *
Cast an IBinder object into an com.zxh.ipc.ITestManager interface, generating a proxy if needed.

         */

        public static com.zxh.ipc.ITestManager
asInterface(android.os.IBinder obj)

        {

            if ((obj
== 
null))
{

                return null;

            }

            android.os.IInterface
iin = obj.queryLocalInterface(DESCRIPTOR);

            if (((iin
!= 
null)
&& (iin 
instanceof com.zxh.ipc.ITestManager)))
{

                return ((com.zxh.ipc.ITestManager)
iin);

            }

            return new com.zxh.ipc.ITestManager.Stub.Proxy(obj);

        }

 

        @Override

        public android.os.IBinder
asBinder()

        {

            return this;

        }

 

        @Override

        public boolean onTransact(int code,
android.os.Parcel data, android.os.Parcel reply, 
int flags)

                throws android.os.RemoteException

        {

            switch (code)

            {

                case INTERFACE_TRANSACTION:
{

                    reply.writeString(DESCRIPTOR);

                    return true;

                }

                case TRANSACTION_checkPermission:
{

                    data.enforceInterface(DESCRIPTOR);

                    java.lang.String
_arg0;

                    _arg0
= data.readString();

                    java.lang.String
_arg1;

                    _arg1
= data.readString();

                    int _result
this.checkPermission(_arg0,
_arg1);

                    reply.writeNoException();

                    reply.writeInt(_result);

                    return true;

                }

                case TRANSACTION_checkUidPermission:
{

                    data.enforceInterface(DESCRIPTOR);

                    java.lang.String
_arg0;

                    _arg0
= data.readString();

                    int _arg1;

                    _arg1
= data.readInt();

                    int _result
this.checkUidPermission(_arg0,
_arg1);

                    reply.writeNoException();

                    reply.writeInt(_result);

                    return true;

                }

                case TRANSACTION_addPermission:
{

                    data.enforceInterface(DESCRIPTOR);

                    com.zxh.ipc.PermissionInfo
_arg0;

                    if ((0 !=
data.readInt())) {

                        _arg0
= com.zxh.ipc.PermissionInfo.CREATOR.createFromParcel(data);

                    }

                    else {

                        _arg0
null;

                    }

                    boolean _result
this.addPermission(_arg0);

                    reply.writeNoException();

                    reply.writeInt(((_result)
? (
1)
: (
0)));

                    return true;

                }

                case TRANSACTION_removePermission:
{

                    data.enforceInterface(DESCRIPTOR);

                    java.lang.String
_arg0;

                    _arg0
= data.readString();

                    this.removePermission(_arg0);

                    reply.writeNoException();

                    return true;

                }

                case TRANSACTION_isProtectedBroadcast:
{

                    data.enforceInterface(DESCRIPTOR);

                    java.lang.String
_arg0;

                    _arg0
= data.readString();

                    boolean _result
this.isProtectedBroadcast(_arg0);

                    reply.writeNoException();

                    reply.writeInt(((_result)
? (
1)
: (
0)));

                    return true;

                }

            }

            return super.onTransact(code,
data, reply, flags);

        }

 

        private static class Proxy implements com.zxh.ipc.ITestManager

        {

            private android.os.IBinder
mRemote;

 

            Proxy(android.os.IBinder
remote)

            {

                mRemote
= remote;

            }

 

            @Override

            public android.os.IBinder
asBinder()

            {

                return mRemote;

            }

 

            public java.lang.String
getInterfaceDescriptor()

            {

                return DESCRIPTOR;

            }

 

            @Override

            public int checkPermission(java.lang.String
permName, java.lang.String pkgName)

                    throws android.os.RemoteException

            {

                android.os.Parcel
_data = android.os.Parcel.obtain();

                android.os.Parcel
_reply = android.os.Parcel.obtain();

                int _result;

                try {

                    _data.writeInterfaceToken(DESCRIPTOR);

                    _data.writeString(permName);

                    _data.writeString(pkgName);

                    mRemote.transact(Stub.TRANSACTION_checkPermission,
_data, _reply, 
0);

                    _reply.readException();

                    _result
= _reply.readInt();

                finally {

                    _reply.recycle();

                    _data.recycle();

                }

                return _result;

            }

 

            @Override

            public int checkUidPermission(java.lang.String
permName, 
int uid) throws android.os.RemoteException

            {

                android.os.Parcel
_data = android.os.Parcel.obtain();

                android.os.Parcel
_reply = android.os.Parcel.obtain();

                int _result;

                try {

                    _data.writeInterfaceToken(DESCRIPTOR);

                    _data.writeString(permName);

                    _data.writeInt(uid);

                    mRemote.transact(Stub.TRANSACTION_checkUidPermission,
_data, _reply, 
0);

                    _reply.readException();

                    _result
= _reply.readInt();

                finally {

                    _reply.recycle();

                    _data.recycle();

                }

                return _result;

            }

 

            @Override

            public boolean addPermission(com.zxh.ipc.PermissionInfo
info) 
throws android.os.RemoteException

            {

                android.os.Parcel
_data = android.os.Parcel.obtain();

                android.os.Parcel
_reply = android.os.Parcel.obtain();

                boolean _result;

                try {

                    _data.writeInterfaceToken(DESCRIPTOR);

                    if ((info
!= 
null))
{

                        _data.writeInt(1);

                        info.writeToParcel(_data, 0);

                    }

                    else {

                        _data.writeInt(0);

                    }

                    mRemote.transact(Stub.TRANSACTION_addPermission,
_data, _reply, 
0);

                    _reply.readException();

                    _result
= (
0 !=
_reply.readInt());

                finally {

                    _reply.recycle();

                    _data.recycle();

                }

                return _result;

            }

 

            @Override

            public void removePermission(java.lang.String
name) 
throws android.os.RemoteException

            {

                android.os.Parcel
_data = android.os.Parcel.obtain();

                android.os.Parcel
_reply = android.os.Parcel.obtain();

                try {

                    _data.writeInterfaceToken(DESCRIPTOR);

                    _data.writeString(name);

                    mRemote.transact(Stub.TRANSACTION_removePermission,
_data, _reply, 
0);

                    _reply.readException();

                finally {

                    _reply.recycle();

                    _data.recycle();

                }

            }

 

            @Override

            public boolean isProtectedBroadcast(java.lang.String
actionName) 
throws android.os.RemoteException

            {

                android.os.Parcel
_data = android.os.Parcel.obtain();

                android.os.Parcel
_reply = android.os.Parcel.obtain();

                boolean _result;

                try {

                    _data.writeInterfaceToken(DESCRIPTOR);

                    _data.writeString(actionName);

                    mRemote.transact(Stub.TRANSACTION_isProtectedBroadcast,
_data, _reply, 
0);

                    _reply.readException();

                    _result
= (
0 !=
_reply.readInt());

                finally {

                    _reply.recycle();

                    _data.recycle();

                }

                return _result;

            }

        }

 

        static final int TRANSACTION_checkPermission
= (android.os.IBinder.FIRST_CALL_TRANSACTION + 
0);

        static final int TRANSACTION_checkUidPermission
= (android.os.IBinder.FIRST_CALL_TRANSACTION + 
1);

        static final int TRANSACTION_addPermission
= (android.os.IBinder.FIRST_CALL_TRANSACTION + 
2);

        static final int TRANSACTION_removePermission
= (android.os.IBinder.FIRST_CALL_TRANSACTION + 
3);

        static final int TRANSACTION_isProtectedBroadcast
= (android.os.IBinder.FIRST_CALL_TRANSACTION + 
4);

    }

 

    public int checkPermission(java.lang.String
permName, java.lang.String pkgName) 
throws android.os.RemoteException;

 

    public int checkUidPermission(java.lang.String
permName, 
int uid) throws android.os.RemoteException;

 

    public boolean addPermission(com.zxh.ipc.PermissionInfo
info) 
throws android.os.RemoteException;

 

    public void removePermission(java.lang.String
name) 
throws android.os.RemoteException;

 

    public boolean isProtectedBroadcast(java.lang.String
actionName) 
throws android.os.RemoteException;

}

第三步:继承上一步生成的接口,实现自己的Service类:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

package com.zxh.server;

import android.app.Service;

import android.content.Intent;

import android.content.ServiceConnection;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

import com.zxh.ipc.ITestManager;

import com.zxh.ipc.PermissionInfo;

public class TestService extends Service{

    private final static String
TAG = 
"zxh";

    class TestManagerService extends ITestManager.Stub{

        

        @Override

        public int checkPermission(String
permName, String pkgName)

                throws RemoteException
{

            Log.i(TAG, "checkPermission
server"
);

            return 0;

        }

        @Override

        public int checkUidPermission(String
permName, 
int uid)

                throws RemoteException
{

            Log.i(TAG, "checkUidPermission
server"
);

            return 0;

        }

        @Override

        public boolean addPermission(PermissionInfo
info) 
throws RemoteException
{

            Log.i(TAG, "addPermission
server"
);

            return false;

        }

        @Override

        public void removePermission(String
name) 
throws RemoteException
{

            Log.i(TAG, "removePermission
server"
);

        }

        @Override

        public boolean isProtectedBroadcast(String
actionName)

                throws RemoteException
{

            Log.i(TAG, "isProtectedBroadcast
server"
);

            return false;

        }

    }

    

    

    private TestManagerService
mService = 
new TestManagerService();

    

    @Override

    public IBinder
onBind(Intent intent) {

        Log.i("zxh""unbindService");

        return mService;

    }

    

    @Override

    public void unbindService(ServiceConnection
conn) {

        super.unbindService(conn);

        Log.i("zxh""unbindService");

    }

}

第四步:实现client代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

package com.zxh.server;

import android.app.Activity;

import android.app.Service;

import android.content.ComponentName;

import android.content.Intent;

import android.content.ServiceConnection;

import android.os.Bundle;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import com.zxh.ipc.ITestManager;

public class MainActivity extends Activity
{

    private ITestManager
manager = 
null;

    

    ServiceConnection
connection = 
new ServiceConnection()
{

        @Override

        public void onServiceDisconnected(ComponentName
name) {

            Log.i("binder""onServiceDisconnected");

        }

        

        @Override

        public void onServiceConnected(ComponentName
name, IBinder service) {

            manager
= ITestManager.Stub.asInterface(service);

        }

    };

    

    @Override

    protected void onCreate(Bundle
savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        findViewById(R.id.startServer).setOnClickListener(new OnClickListener()
{

            @Override

            public void onClick(View
v) {

                bindService(new Intent(MainActivity.this,
TestService.
class),
connection, Service.BIND_AUTO_CREATE);

            }

        });

        

        findViewById(R.id.stop).setOnClickListener(new OnClickListener()
{

            @Override

            public void onClick(View
v) {

                unbindService(connection);

            }

        });

        

        findViewById(R.id.check).setOnClickListener(new OnClickListener()
{

            @Override

            public void onClick(View
v) {

                try {

                    manager.checkPermission("permName""pkgName");

                catch (RemoteException
e) {

                    e.printStackTrace();

                }

            }

        });

    }

}

到这里我们就实现了一个完整的Binder实例,以下是project文件夹的截图:

完整代码能够查看后面的附件。以下来介绍一下这个实例中涉及到的一些知识点。

AIDL

除了eclipse,也能够使用Android开发包中提供的aidl命令工具来生成,例如以下是adil命令:

关于adil的具体介绍能够查看Android官方文档,地址为:http://developer.android.com/intl/zh-cn/guide/components/aidl.html

想要了解aidl处理过程的朋友也能够自己查看aidl的源码,位于@/frameworks/base/tools/adil。

AIDL编译产生的类

以下我们来分析一下aidl编译产生的ITestManager类。

从ITestManager中能够看出,ITestManager实现了IInterface接口。在ITestManager类中共包括了三部分内容,各自是:

  • 我们在ITestManager.adil中定义的接口。
  • Stub类:主要由Server端实现,Server端通过继承本类,来提供详细的处理逻辑。
  • Proxy类:client代理,通过mRemote成员变量訪问远程Binder服务。

为了实现我们在ITestManager自定义接口的跨进程通信,Stub类和Proxy都实现了ITestManager接口。Stub自己继承了Binder类来实现Binder机制,Proxy则以引用的方式实现Binder机制。

client和服务端的通信主要通过onTransact方法实现,client和服务端的数据传递通过Parcel类完毕。这里须要注意一个问题:就是在client写入数据的顺序与在服务端读取数据的顺序必须是一致的。

尽管在上面的实现中,我们定义了一个Service类TestService,但这里要说明的是Service甚至adil都不是必须的,使用者全然能够自定义。

时间: 2024-10-12 11:16:57

自顶向下分析Binder【1】—— Binder实例篇的相关文章

Android Binder设计与实现篇

摘要 Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有管道,system V IPC,socket等IPC手段,却还要倚赖Binder来实现进程间通信,说明Binder具有无可比拟的优势.深入了解Binder并将之与传统IPC做对比有助于我们深入领会进程间通信的实现和性能优化.本文将对Binder的设计细节做一个全面的阐述,首先通过介绍Binder通信模型和Binder通信协议了解Binder的设计需求:然后分别阐述Binder在系统不同部分的表述方式和起的作用:

红茶一杯话Binder(传输机制篇_上)

红茶一杯话Binder (传输机制篇_上) 侯 亮 1 Binder是如何做到精确打击的? 我们先问一个问题,binder机制到底是如何从代理对象找到其对应的binder实体呢?难道它有某种制导装置吗?要回答这个问题,我们只能静下心来研究binder驱动的代码.在本系列文档的初始篇中,我们曾经介绍过ProcessState,这个结构是属于应用层次的东西,仅靠它当然无法完成精确打击.其实,在binder驱动层,还有个与之相对的结构,叫做binder_proc.为了说明问题,我修改了初始篇中的示意图

红茶一杯话Binder (传输机制篇_下)

红茶一杯话Binder (传输机制篇_下) 侯 亮 1 事务的传递和处理 从IPCThreadState的角度看,它的transact()函数是通过向binder驱动发出BC_TRANSACTION语义,来表达其传输意图的,而后如有必要,它会等待从binder发回的回馈,这些回馈语义常常以“BR_”开头.另一方面,当IPCThreadState作为处理命令的一方需要向发起方反馈信息的话,它会调用sendReply()函数,向binder驱动发出BC_REPLY语义.当BC_语义经由binder驱

红茶一杯话Binder (传输机制篇_中)

红茶一杯话Binder (传输机制篇_中) 侯 亮 1 谈谈底层IPC机制吧 在上一篇文章的最后,我们说到BpBinder将数据发到了Binder驱动.然而在驱动层,这部分数据又是如何传递到BBinder一侧的呢?这里面到底藏着什么猫腻?另外,上一篇文章虽然阐述了4棵红黑树,但是并未说明红黑树的节点到底是怎么产生的.现在,我们试着回答这些问题. 1.1 概述 在Binder驱动层,和ioctl()相对的动作是binder_ioctl()函数.在这个函数里,会先调用类似copy_from_user

自定向下分析Binder 之 Binder Model(1)

Java层的Binder对象模型: IBinder IBinder是Binder通信机制中的核心部分(Base interface for a remotable object, the core part of a lightweight remote procedure call mechanism designed for high performance when performing in-process and cross-process calls. ). This interfa

Andorid Binder进程间通信---Binder本地对象,实体对象,引用对象,代理对象的引用计数

本文参考<Android系统源代码情景分析>,作者罗升阳. 一.Binder库(libbinder)代码: ~/Android/frameworks/base/libs/binder ----BpBinder.cpp ----Parcel.cpp ----ProcessState.cpp ----Binder.cpp ----IInterface.cpp ----IPCThreadState.cpp ----IServiceManager.cpp ----Static.cpp ~/Androi

Andorid Binder进程间通信---Binder对象死亡通知机制

本文参考<Android系统源代码情景分析>,作者罗升阳. 一.Binder库(libbinder)代码: ~/Android/frameworks/base/libs/binder ----BpBinder.cpp ----Parcel.cpp ----ProcessState.cpp ----Binder.cpp ----IInterface.cpp ----IPCThreadState.cpp ----IServiceManager.cpp ----Static.cpp ~/Androi

了解javascript中的this --实例篇

对javascript this的赋值有了深一层的理解后,看一下比较复杂的情况,this的应用篇参考<对javascript this的理解>. #demo1 1 var name="window"; 2 var object = { 3 name:"me", 4 getname:(function(){ 5 alert(this.name);//window,加载即执行 6 return function(){ 7 return this.name;

Android Binder进程间通信---Binder类图

上传两张Binder类图,有助于理解Binder进程间通信: Android Binder进程间通信---Binder类图

MonoRail学习-入门实例篇

1.到官方网站下载安装文件,地址如下: http://www.castleproject.org/index.php/Castle:Download目前最新版本Beta5(您也可以不需要下载,直接使用实例代码中lib中的dll) 2.添加对Castle.MonoRail.Framework.dllCastle.MonoRail.Framework.Views.CompositeView.dllCastle.MonoRail.Framework.Views.NVelocity.dllNVeloci