Ответ 1
Посмотрите, имеет ли смысл мое обсуждение...
вскрытие внутренней службы Android
Как предложил один из читателей, я пытаюсь скопировать некоторую часть записи здесь.
Вы когда-нибудь задумывались над тем, как приложение получает доступ к системным службам, таким как POWER MANAGER или MANITER ACTIVITY MANAGER или LOCATION MANAGER, и тому подобное. Чтобы узнать, что я ворвался в исходный код Android и узнал, как это делается внутри. Поэтому позвольте мне начать с Java-кода сторон приложения.
На стороне приложения нам нужно вызвать функцию getService
и передать идентификатор системной службы (например, POWER_SERVICE), чтобы получить дескриптор этой службы.
Вот код для 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 <code>null</code> 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 }
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 }
Таким образом, в основном мы получаем ручку для собственного servicemanager.
Эта функция 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 { }
Итак, если вы видите строку 12, которая показывает, запущен и запущен Service Manager (и это должно произойти из-за того, что диспетчер сервисов запускается в процессе инициализации во время загрузки Android), он возвращает ссылку на него через функцию queryLocalinterface, и это доходит до интерфейса 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 }
из ServiceManagerNative.java. В этой функции мы передаем сервис, который мы ищем.
И функция onTransact для GET_SERVICE_TRANSACTION на удаленной заглушке выглядит следующим образом:
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
51 {
52 try {
53 switch (code) {
54 case IServiceManager.GET_SERVICE_TRANSACTION: {
55 data.enforceInterface(IServiceManager.descriptor);
56 String name = data.readString();
57 IBinder service = getService(name);
58 reply.writeStrongBinder(service);
59 return true;
60 }
61
62 case IServiceManager.CHECK_SERVICE_TRANSACTION: {
63 data.enforceInterface(IServiceManager.descriptor);
64 String name = data.readString();
65 IBinder service = checkService(name);
66 reply.writeStrongBinder(service);
67 return true;
68 }
69
//Rest has been discarded for brevity…………………..
………………….
………………….
…………………
Он возвращает ссылку на необходимую службу через функцию getService. Функция getService из /frameworks/base/libs/binder/IServiceManager.cpp выглядит следующим образом:
virtual 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 }
Таким образом, он фактически проверяет, доступна ли Служба, и затем возвращает ссылку на нее. Здесь я хотел бы добавить, что когда мы возвращаем ссылку на объект IBinder, в отличие от других типов данных, он не копируется в адресное пространство клиентов, но на самом деле это та же ссылка объекта IBinder, которая совместно используется клиентом через специальная техника, называемая отображением объектов в драйвере Binder.
Чтобы добавить более подробную информацию к обсуждению, позвольте мне углубиться в нее.
Функция checkService выглядит следующим образом:
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 (его значение перечисления 2).
Эта удаленная служба фактически реализована в рамках /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;
Следовательно, мы вызываем функцию с именем do_find_service, которая получает ссылку на службу и возвращает ее обратно.
Do_find_service из того же файла выглядит следующим образом:
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 выглядит следующим образом:
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;
}
Как становится ясно, что он проходит через svclist и возвращает службу, которую мы ищем.