[Quote] How does getSystemService() work exactly?

From  http://stackoverflow.com/questions/15137247/how-does-getsystemservice-work-exactly

https://docs.google.com/document/d/10EYlyuxDw1KPy7LJlGtgMz69gwMO-pjDHS2GRtppvZg/edit#

Android Services Internals

by

Somenath Mukhopadhyay

[email protected]

Have you ever wondered how an app gets an handle to the system services like POWER MANAGER or ACTIVITY MANAGER or LOCATION MANAGER and several others like these. To know that i dug into the source code of Android and found out how this is done internally.

The investigation detailed below will work as an hand-holder for an Android internal learners.

So let me start from the application side’s java code.

At the application side we have to call the function getService and pass the ID of the system service (say POWER_SERVCE) to get an handle to the service.

Here is the code for getService defined in  /frameworks/base/core/java/android/os/ServiceManager.java

/**
44     * Returns a reference to a service with the given name.
45     *
46     * @param name the name of the service to get
47     * @return a reference to the service, or <code>null</code> if the service doesn‘t exist
48     */
49    public staticIBindergetService(Stringname) {
50        try {
51           IBinderservice =sCache.get(name);
52            if (service !=null) {
53                returnservice;
54            } else {
55                returngetIServiceManager().getService(name);
56            }
57        } catch (RemoteException e) {
58           Log.e(TAG, "error in getService", e);
59        }
60        returnnull;
61    }

Suppose we don’t have the service in the cache. Hence we need to concentrate on the line 55

returngetIServiceManager().getService(name);

This call actually gets an handle to the service manager and asks it to return a reference of the service whose name we have passed as a parameter.

Now let us see how the getIServiceManager() function returns a handle to the ServiceManager.

Here is the code of getIserviceManager() from /frameworks/base/core/java/android/os/ServiceManager.java

private staticIServiceManagergetIServiceManager() {
34        if (sServiceManager !=null) {
35            returnsServiceManager;
36        }
3738        // Find the service manager
39        sServiceManager =ServiceManagerNative.asInterface(BinderInternal.getContextObject());
40        returnsServiceManager;
41    }

Look at the line 39. Here we get an handle to the BpServiceManager. The reason is because after the systemserver starts servicemanager(call main in service_manager.c), the servicemanager will register itself as a context_manager of binder by ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0) through the function

int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);

}

The ServicemanagerNative.asInterface() looks like the following:

/**
28     * Cast a Binder object into a service manager interface, generating
29     * a proxy if needed.
30     */
31    static publicIServiceManagerasInterface(IBinderobj)
32    {
33        if (obj ==null) {
34            returnnull;
35        }
36       IServiceManagerin =
37            (IServiceManager)obj.queryLocalInterface(descriptor);
38        if (in !=null) {
39            returnin;
40        }
4142        return newServiceManagerProxy(obj);
43    }

So basically we are getting a handle to the native servicemanager.

This asInterface function is actually buried inside the two macros DECLARE_META_INTERFACE(ServiceManager) and IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

defined in IserviceManager.h and IServiceManager.cpp respectively.

Lets delve into the two macros defined in /frameworks/base/include/binder/IInterface.h

DECLARE_META_INTERFACE(ServiceManager) macro.

Its defined as

// ----------------------------------------------------------------------
7374#defineDECLARE_META_INTERFACE(INTERFACE)                               \
75    static constandroid::String16descriptor;                          \
76    staticandroid::sp<I##INTERFACE>asInterface(                       \
77            constandroid::sp<android::IBinder>&obj);                  \
78   virtual constandroid::String16&getInterfaceDescriptor() const;    \
79    I##INTERFACE();                                                     \
80   virtual ~I##INTERFACE();                                            \

And the IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

has been defined as follows:

#defineIMPLEMENT_META_INTERFACE(INTERFACE,NAME)                       \
84    constandroid::String16 I##INTERFACE::descriptor(NAME);             \
85    constandroid::String16&                                            \
86            I##INTERFACE::getInterfaceDescriptor() const {              \
87        return I##INTERFACE::descriptor;                                \
88    }                                                                   \
89   android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
90            constandroid::sp<android::IBinder>&obj)                   \
91    {                                                                   \
92       android::sp<I##INTERFACE>intr;                                 \
93        if (obj !=NULL) {                                              \
94           intr =static_cast<I##INTERFACE*>(                          \
95               obj->queryLocalInterface(                               \
96                        I##INTERFACE::descriptor).get());               \
97            if (intr ==NULL) {                                         \
98               intr =newBp##INTERFACE(obj);                          \
99            }                                                           \
100        }                                                               \
101        returnintr;                                                    \
102    }                                                                   \
103    I##INTERFACE::I##INTERFACE() { }                                    \
104    I##INTERFACE::~I##INTERFACE() { }

So if we replace expand these two macros in IServiceManager.h & IServiceManager.cpp file with the appropriate replacement parameters they look like the following:

  1. classIServiceManager :publicIInterface{
    public:
      static const android::String16 descriptor;
  2. static android::sp<IServiceManager> asInterface( const android::sp<android::IBinder>& obj);
  3. virtual const android::String16& getInterfaceDescriptor() const;
  4. IServicemanager();
  5. virtual ~IServiceManager();

…......

….....

…...

…..

And in
IServiceManager.cpp

  1. const android::String16 IServiceManager::descriptor("android.os.IServiceManager”);
  2. const android::String16&
  3. IServiceManager::getInterfaceDescriptor() const {
  4. return  IServiceManager::descriptor;
  5. }
  6. android::sp<IServiceManager> IServiceManager::asInterface(
  7. const android::sp<android::IBinder>& obj)
  8. {
  9. android::sp< IServiceManager> intr;
  10. if (obj != NULL) {
  11. intr = static_cast<IServiceManager*>(
  12. obj->queryLocalInterface(
  13. IServiceManager::descriptor).get());
  14. if (intr == NULL) {
  15. intr = new BpServiceManager(obj);
  16. }
  17. }
  18. return intr;
  19. }
  20. IServiceManager::IServiceManager() { }
  21. IServiceManager::~IIServiceManager { }

If you look at line 15, you will get how we get an handle to the BpServiceManager.

now once we get the reference of the Service Manager, we next call

publicIBindergetService(Stringname) throwsRemoteException {
116       Parceldata =Parcel.obtain();
117       Parcelreply =Parcel.obtain();
118       data.writeInterfaceToken(IServiceManager.descriptor);
119       data.writeString(name);
120       mRemote.transact(GET_SERVICE_TRANSACTION,data,reply, 0);
121       IBinderbinder =reply.readStrongBinder();
122       reply.recycle();
123       data.recycle();
124        returnbinder;
125    }

from  ServiceManagerNative.java. in this function we pass the service that we are looking for.

It returns the reference to the needed service through the function getService.

The getService function from /frameworks/base/libs/binder/IServiceManager.cpp

looks like the following:

virtualsp<IBinder>getService(constString16&name) const
134    {
135        unsigned n;
136        for (n = 0; n < 5; n++){
137           sp<IBinder>svc =checkService(name);
138            if (svc !=NULL) returnsvc;
139           LOGI("Waiting for service %s...\n",String8(name).string());
140           sleep(1);
141        }
142        returnNULL;
143

And the above checkService(name) looks like the following:

  1. virtual sp<IBinder> checkService( const String16& name) const
  2. {
  3. Parcel data, reply;
  4. data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
  5. data.writeString16(name);
  6. remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
  7. return reply.readStrongBinder();
  8. }

So it actually calls a remote service and pass CHECK_SERVICE_TRANSACTION code (its an enum value of 2) to it.

This remote service is actually implemented in frameworks/base/cmds/servicemanager/service_manager.c

and its onTransact looks like the following.

switch(txn->code) {

case SVC_MGR_GET_SERVICE:

case SVC_MGR_CHECK_SERVICE:

  1. s = bio_get_string16(msg, &len);
  2. ptr = do_find_service(bs, s, len);
  3. if (!ptr)
  4. break;
  5. bio_put_ref(reply, ptr);
  6. return 0;

Hence we end up calling the function named do_find_service which gets a reference to the service and returns it back.

The do_find_service from the same file looks as follows:

void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len)

{

struct svcinfo *si;

si = find_svc(s, len);

//    ALOGI("check_service(‘%s‘) ptr = %p\n", str8(s), si ? si->ptr : 0);

if (si && si->ptr) {

return si->ptr;

} else {

return 0;

}

}

find_svc looks as follows:

struct svcinfo *find_svc(uint16_t *s16, unsigned len)

{

struct svcinfo *si;

for (si = svclist; si; si = si->next) {

if ((len == si->len) &&

!memcmp(s16, si->name, len * sizeof(uint16_t))) {

return si;

}

}

return 0;

}

As it becomes clear that it traverses through the svclist and returns the the service we are looking for.

Hope it helps the Android learners to know about the internal of Android services.

时间: 2024-11-15 00:24:17

[Quote] How does getSystemService() work exactly?的相关文章

演哥德堡

http://quote.hexun.com/stock/icb.aspx?code=1&name=%A8%7D%C3%C0%C9%B3%CD%AA%C4%C4%C0%EF%B6%A9%B9%BA%A3%D1%3A%A3%B1%A3%B1%A3%B2%A3%B7%A3%B4%A3%B0%A3%B1%A3%B1%A3%B7%A3%B5 http://quote.hexun.com/stock/icb.aspx?code=1&name=%A1%EF%D4%F5%C3%B4%B6%A9%B9%B

[Fatal Error] :3:13: Open quote is expected for attribute &quot;{1}&quot; associated with an element type &quot;id&quot;.

用DOM解析XML时出现了如下错误: [Fatal Error] :3:13: Open quote is expected for attribute "{1}" associated with an  element type  "id".org.xml.sax.SAXParseException: Open quote is expected for attribute "{1}" associated with an  element t

android中getSystemService详解

android的后台运行在很多service,它们在系统启动时被SystemServer开启,支持系统的正常工作,比如MountService监听是否有SD卡安装及移除,ClipboardService提供剪切板功能,PackageManagerService提供软件包的安装移除及查看等等,应用程序可以通过系统提供的Manager接口来访问这些Service提供的数据. getSystemService是Android很重要的一个API,它是Activity的一个方法,根据传入的NAME来取得对

getSystemservice()原理

1. 说明 android的后台运行在很多service,它们在系统启动时被SystemServer开启,支持系统的正常工作,比如MountService监听是否有SD卡安装及移除,ClipboardService提供剪切板功能,PackageManagerService提供软件包的安装移除及查看等等,应用程序可以通过系统提供的Manager接口来访问这些Service提供的数据,以下将说明他们的工具流程 2. 举例说明基本流程 以android系统支持sensor(传感器)实例来说明框架层的s

「6月雅礼集训 2017 Day10」quote

[题目大意] 一个合法的引号序列是空串:如果引号序列合法,那么在两边加上同一个引号也合法:或是把两个合法的引号序列拼起来也是合法的. 求长度为$n$,字符集大小为$k$的合法引号序列的个数.多组数据. $1 \leq T \leq 10^5, 1 \leq n \leq 10^7, 1\leq K \leq 10^9$ [题解] 显然引号序列可以看做括号序列,于是我们有了一个$O(n^2)$的dp了. 设$f_{i,j}$表示到第$i$个位置,前面有$j$个左引号没有匹配,的方案数 每次,要么有

Android Context getSystemService分析

我们知道一个应用的Context个数是Activity个数+Service个数+1 当我们希望获取到系统服务时,可以调用Context的getSystemService方法,如获取到ActivityManager: ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 那么getSystemService又是怎么工作的呢? Activity是一个Context,他调用getS

[2016-1-14]OMG美语每日笔记-?What is your favorite Star Wars quote?

坚持学习英语,OMG口语非常长不错,坚持每天整理.学英语坚持最重要,学英语坚持最重要,学英语坚持最重要说三遍! May the Force be with you. 愿原力与你同在. One of the most famous quetes from the original Start Wars movies is "May the Force be with you". 星战电影里最著名的台词是"愿原力与你同在" Use the Force,Luke! 使用原

CRM 2011: 报价(Quote Detail)到订单(Order Detail)的Mapping

CRM 2011: 报价(Quote Detail)到订单(Order Detail)的Mapping (MSCRM 2011 Mapping QuoteProduct to OrderProduct) 由于QuoteProduct 到 OrderProduct 的mapping是隐藏的,我们在solution管理里面是看不到它们之间的Mapping信息的,但是它们的关系是存在的. 我们怎么找到它们的关系呢? 在SQL里面查询如下语句: SELECT EntityMapId FROM Entit

Open quote is expected for attribute &quot;property&quot; associated with an element type &quot;result&quot;.错误

java  Mybatis 框架下的项目 报   Open quote is expected for attribute "property" associated with an element type "result".    这个错 眼快使瞎了,终于找到了 错误写法: <result column="DELETE_STATUS" property=delete_status  jdbcType="VARCHAR"