Статьи

Внутренние устройства службы Android


Вы когда-нибудь задумывались, как приложение получает управление системными службами, такими как POWER MANAGER, ACTIVITY MANAGER или LOCATION MANAGER и некоторыми другими, подобными этим.
Чтобы узнать, что я копался в исходном коде Android и узнал, как это делается внутри.

Расследование, детализированное ниже, будет работать как держатель для внутренних учеников Android. 

Итак, позвольте мне начать с Java-кода на стороне приложения.

На стороне приложения мы должны вызвать функцию getService и передать идентификатор системной службы (скажем, POWER_SERVCE), чтобы получить дескриптор службы.

Вот код для getService, определенный в /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 null if the service doesn't exist
48     */
49    public static IBinder getService(String name) {
50        try {
51            IBinder service = sCache.get(name);
52            if (service != null) {
53                return service;
54            } else {
55                return getIServiceManager().getService(name);
56            }
57        } catch (RemoteException e) {
58            Log.e(TAG, "error in getService", e);
59        }
60        return null;
61    }

Предположим, у нас нет службы в кэше.
Следовательно, нам нужно сосредоточиться на строке 55 

return getIServiceManager (). getService (name);

Этот вызов фактически получает дескриптор менеджера сервиса и просит его вернуть ссылку на сервис, имя которого мы передали в качестве параметра.

Теперь давайте посмотрим, как функция getIServiceManager () возвращает дескриптор ServiceManager. 

Вот код getIserviceManager () из /frameworks/base/core/java/android/os/ServiceManager.java
private static IServiceManager getIServiceManager() {
34        if (sServiceManager != null) {
35            return sServiceManager;
36        }
37
38        // Find the service manager
39        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
40        return sServiceManager;
41    }
Посмотрите на строку 39. Здесь мы получаем дескриптор BpServiceManager. Причина в том, что после того, как системный сервер запускает servicemanager (вызов main в service_manager.c), servicemanager зарегистрирует себя как context_manager для связывателя с помощью ioctl (bs-> fd, BINDER_SET_CONTEXT_MGR, 0) через функцию 

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

ServicemanagerNative.asInterface () выглядит следующим образом:
/**
28     * Cast a Binder object into a service manager interface, generating
29     * a proxy if needed.
30     */
31    static public IServiceManager asInterface(IBinder obj)
32    {
33        if (obj == null) {
34            return null;
35        }
36        IServiceManager in =
37            (IServiceManager)obj.queryLocalInterface(descriptor);
38        if (in != null) {
39            return in;
40        }
41
42        return new ServiceManagerProxy(obj);
43    }
Таким образом, в основном мы получаем ручку к родному сервис-менеджеру.


Эта функция asInterface фактически скрыта внутри двух макросов DECLARE_META_INTERFACE (ServiceManager) и IMPLEMENT_META_INTERFACE (ServiceManager, «android.os.IServiceManager»);

определены в IserviceManager.h и IServiceManager.cpp соответственно.

Давайте углубимся в два макроса, определенных в /frameworks/base/include/binder/IInterface.h

Макрос DECLARE_META_INTERFACE (ServiceManager).

Это определяется как 
// ----------------------------------------------------------------------
73
74#define DECLARE_META_INTERFACE(INTERFACE)                               \
75    static const android::String16 descriptor;                          \
76    static android::sp<I##INTERFACE> asInterface(                       \
77            const android::sp<android::IBinder>& obj);                  \
78    virtual const android::String16& getInterfaceDescriptor() const;    \
79    I##INTERFACE();                                                     \
80    virtual ~I##INTERFACE();                                            \
И IMPLEMENT_META_INTERFACE (ServiceManager, «android.os.IServiceManager»);


был определен следующим образом:
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
84    const android::String16 I##INTERFACE::descriptor(NAME);             \
85    const android::String16&                                            \
86            I##INTERFACE::getInterfaceDescriptor() const {              \
87        return I##INTERFACE::descriptor;                                \
88    }                                                                   \
89    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
90            const android::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 = new Bp##INTERFACE(obj);                          \
99            }                                                           \
100        }                                                               \
101        return intr;                                                    \
102    }                                                                   \
103    I##INTERFACE::I##INTERFACE() { }                                    \
104    I##INTERFACE::~I##INTERFACE() { }  
Поэтому, если мы заменим эти два макроса в файле IServiceManager.h & IServiceManager.cpp с соответствующими параметрами замены, они будут выглядеть следующим образом:

class IServiceManager : public IInterface
{
public:
   static const android::String16 descriptor;  
    static android::sp<IServiceManager> asInterface( const android::sp<android::IBinder>& obj);  
    virtual const android::String16& getInterfaceDescriptor() const; 
    IServicemanager();  
    virtual ~IServiceManager();  
…......
….....
…...
…..
И в 


IServiceManager.cpp
const android::String16 IServiceManager::descriptor("android.os.IServiceManager”);             
    const android::String16&  
           IServiceManager::getInterfaceDescriptor() const {  
        return  IServiceManager::descriptor;
    }    
    android::sp<IServiceManager> IServiceManager::asInterface(   
            const android::sp<android::IBinder>& obj)  
    {   
        android::sp< IServiceManager> intr;    
        if (obj != NULL) {     
            intr = static_cast<IServiceManager*>(   
                obj->queryLocalInterface(  
                        IServiceManager::descriptor).get());    
            if (intr == NULL) {   
                intr = new BpServiceManager(obj);  
            }  
        }     
        return intr;    
    }     
    IServiceManager::IServiceManager() { }     
IServiceManager :: ~ IIServiceManager {}
    

Если вы посмотрите на строку 15, вы узнаете, как мы получаем дескриптор BpServiceManager.

Теперь, когда мы получаем ссылку на Service Manager, мы в следующий раз 
из ServiceManagerNative.java. в этой функции мы передаем сервис, который ищем.

public IBinder getService(String name) throws RemoteException {
116        Parcel data = Parcel.obtain();
117        Parcel reply = Parcel.obtain();
118        data.writeInterfaceToken(IServiceManager.descriptor);
119        data.writeString(name);
120        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
121        IBinder binder = reply.readStrongBinder();
122        reply.recycle();
123        data.recycle();
124        return binder;
125    }

Возвращает ссылку на нужный сервис через функцию getService.

Функция getService из /frameworks/base/libs/binder/IServiceManager.cpp

выглядит следующим образом:
  
виртуальный sp <IBinder> getService (const String16 & name) const
134    {
135        unsigned n;
136        for (n = 0; n < 5; n++){
137            sp<IBinder> svc = checkService(name);
138            if (svc != NULL) return svc;
139            LOGI("Waiting for service %s...\n", String8(name).string());
140            sleep(1);
141        }
142        return NULL; 
143
    

И вышеупомянутый checkService (name) выглядит следующим образом:
virtual sp<IBinder> checkService( const String16& name) const

    {
        Parcel data, reply;

        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

        data.writeString16(name);

        remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);

        return reply.readStrongBinder();

    }

Таким образом, он фактически вызывает удаленный сервис и передает ему код CHECK_SERVICE_TRANSACTION (его значение enum равно 2).

Этот удаленный сервис фактически реализован в frameworks / base / cmds / servicemanager / service_manager.c

и его onTransact выглядит следующим образом.
switch(txn->code) {
   case SVC_MGR_GET_SERVICE:
 		   case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = do_find_service(bs, s, len);
        if (!ptr)
            break;
        bio_put_ref(reply, ptr);
        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: 
find_svc 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;

    }

}
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.