Вы когда-нибудь задумывались, как приложение получает управление системными службами, такими как 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.