Xem nếu cuộc thảo luận của tôi có ý nghĩa ...
dissection of android service internal
Theo đề nghị của một trong những độc giả Tôi cố gắng để sao chép một số phần của ghi-up ở đây.
Bạn đã bao giờ tự hỏi làm thế nào một ứng dụng có thể xử lý các dịch vụ hệ thống như POWER MANAGER hoặc ACTIVITY MANAGER hoặc LOCATION MANAGER và một số ứng dụng khác như thế này. Để biết rằng tôi đào sâu vào mã nguồn của Android và tìm hiểu cách thực hiện điều này trong nội bộ. Vì vậy, hãy để tôi bắt đầu từ mã java của ứng dụng.
Ở phía ứng dụng, chúng tôi phải gọi hàm getService
và chuyển ID của dịch vụ hệ thống (nói POWER_SERVICE) để xử lý dịch vụ.
Đây là mã cho getService
quy định tại /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 }
Giả sử chúng ta không có các dịch vụ trong bộ nhớ cache. Do đó, chúng tôi cần tập trung vào dòng 55 return getIServiceManager().getService(name);
Cuộc gọi này thực sự được xử lý cho người quản lý dịch vụ và yêu cầu nó trả về tham chiếu về dịch vụ có tên mà chúng tôi đã chuyển làm thông số.
Bây giờ chúng ta hãy xem cách hàm getIServiceManager()
trả về một xử lý cho ServiceManager.
Đây là mã của getIserviceManager() từ /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 }
Các ServicemanagerNative.asInterface() trông giống như sau:
/**
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 }
Vì vậy, về cơ bản chúng tôi đang nhận được một xử lý cho người quản lý bản địa.
Hàm asInterface này thực sự được chôn bên trong hai macro DECLARE_META_INTERFACE(ServiceManager)
và IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
được xác định trong IserviceManager.h và IServiceManager.cpp tương ứng.
Cho phép nghiên cứu kỹ hai macro được xác định trong/khung/base/include/binder/IInterface.h
Các DECLARE_META_INTERFACE(ServiceManager)
vĩ mô được định nghĩa là
// ----------------------------------------------------------------------
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(); \
Và IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
đã được định nghĩa như sau:
#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() { }
Vì vậy, nếu chúng ta thay thế mở rộng hai macro này trong IServiceManager.h & IServiceManager.cpp tệp với thông số thay thế phù hợp, chúng trông giống như sau:
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();
…......
….....
…...
…..
Và trong 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 { }
Vì vậy, nếu bạn nhìn thấy dòng 12 trong đó cho thấy nếu Service Manager khởi động và chạy (và nó nên vì người quản lý dịch vụ bắt đầu trong quá trình init trong Android khởi động lên) nó trả về tham chiếu đến nó thông qua hàm queryLocalinterface và nó đi lên tất cả các cách tới giao diện 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 }
từ ServiceManagerNative.java. Trong chức năng này, chúng tôi chuyển dịch vụ mà chúng tôi đang tìm kiếm.
Và chức năng onTransact cho GET_SERVICE_TRANSACTION trên cuống từ xa trông giống như sau:
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…………………..
………………….
………………….
…………………
Nó trả về tham chiếu đến các dịch vụ cần thiết thông qua chức năng getService. Các getService chức năng từ /frameworks/base/libs/binder/IServiceManager.cpp trông giống như sau:
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 }
Vì vậy, nó thực sự kiểm tra nếu Dịch vụ có sẵn và sau đó trả về một tham chiếu đến nó. Ở đây tôi muốn thêm rằng khi chúng ta trả về một tham chiếu đến một đối tượng IBinder, không giống như các kiểu dữ liệu khác, nó không được sao chép trong không gian địa chỉ của máy khách, nhưng nó thực sự là cùng một tham chiếu của đối tượng IBinder được chia sẻ cho máy khách thông qua kỹ thuật đặc biệt được gọi là ánh xạ đối tượng trong trình điều khiển Binder.
Để thêm chi tiết khác vào cuộc thảo luận, hãy để tôi đi sâu hơn một chút vào đó.
Chức năng checkService trông giống như sau:
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();
}
Vì vậy, nó thực sự gọi một dịch vụ từ xa và vượt qua mã CHECK_SERVICE_TRANSACTION (một giá trị enum của 2) với nó.
Dịch vụ từ xa này thực sự được triển khai trong khung/cơ sở/cmds/servicemanager/service_manager.c và dịch vụ onTransact của nó trông giống như sau.
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 đó, chúng tôi sẽ gọi hàm có tên do_find_service sẽ tham chiếu đến dịch vụ và trả lại dịch vụ.
Các do_find_service từ cùng một tập tin trông như sau:
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 trông như sau:
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;
}
Vì nó trở nên rõ ràng rằng nó đi qua qua svclist và trả về các dịch vụ chúng tôi là tìm kiếm.
Tôi nghĩ 'LocationManager' giữ tham chiếu đến' LocationListener' của bạn miễn là bạn không gọi 'LocationManager.removeUpdates() 'và' LocationListener' của bạn có tham chiếu đến 'Hoạt động' – nicopico
Điều tương tự về phạm vi nên áp dụng cho đối tượng LocationListener được tạo bên trong phương thức 'onCreate (...)'. Ngay sau khi phương thức kết thúc, nó sẽ nằm ngoài phạm vi trừ khi có một tham chiếu đến nó từ một nơi khác (trong trường hợp này là đối tượng LocationManager). Hơn nữa nếu đối tượng LocationManager không được tham chiếu từ một nơi nào khác, cả hai đối tượng này đều đã bị thu gom rác tại một số điểm. Tôi cũng đã thử nghiệm tạo một lớp bên trong tĩnh cho LocationListener (để kiểm tra giả thuyết của bạn) và hành vi tương tự. –
"Người nào đó có mô tả đầy đủ về những gì chính xác xảy ra khi gọi triển khai" - khi bạn đọc mã nguồn, bạn đã học được gì? – CommonsWare