乍一看下面的代码mLocationManager
对象应该在onCreate(...)
完成后超出范围,并且预期的行为是onLocationChanged
永远不会被调用或被调用几次直到对象被垃圾收集。但是getSystemService
返回的对象似乎是单身,它超出了MainActivity
的范围(因为它是一个系统服务,所以恰当如此:))
在进行堆转储并使用Eclipse Memory Analyzer完成后,似乎ContextImpl保留了对LocationManager实例的引用。在内存转储中有两个对LocationManager对象的引用,而在代码中显然只有一个,这意味着在其他地方创建了另一个引用。
我的问题是:
在调用以下实现时,是否有人完整地描述了正在发生的事情:
public abstract Object getSystemService(String name);
是一个懒惰创建的单例返回的对象,是否创建/保留了引用的确切位置?
package com.neusoft.bump.client.storage;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.Menu;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v("TAG", "STARTED");
LocationManager mLocationManager = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
Log.v("TAG", "onLocationChanged");
Log.v("TAG", "Latitude: " + location.getLatitude()
+ "Longitude: " + location.getLongitude());
}
public void onStatusChanged(String provider, int status,
Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location
// updates
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
600, 0, locationListener);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
UPDATE1
LocationManager
创建为单身
private LocationManager getLocationManager() {
synchronized (sSync) {
if (sLocationManager == null) {
IBinder b = ServiceManager.getService(LOCATION_SERVICE);
ILocationManager service = ILocationManager.Stub.asInterface(b);
sLocationManager = new LocationManager(service);
}
}
return sLocationManager;
}
但即使在阅读ServiceManager.getService(LOCATION_SERVICE);
代码后,我也无法理解在调用ServiceManager
时会发生什么。
答案 0 :(得分:48)
看看我的讨论是否有意义......
dissection of android service internal
正如其中一位读者所建议的那样,我试图在这里复制部分内容。
你有没有想过一个应用程序如何处理系统服务,如POWER MANAGER或ACTIVITY MANAGER或LOCATION MANAGER以及其他几个这样的系统服务。要知道我挖掘了Android的源代码,并发现它是如何在内部完成的。 所以让我从应用程序端的java代码开始。
在应用程序端,我们必须调用函数getService
并传递系统服务的ID(比如POWER_SERVICE)以获取服务的句柄。
以下是/frameworks/base/core/java/android/os/ServiceManager.java中定义的getService
代码
/**
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的句柄。
以下是/frameworks/base/core/java/android/os/ServiceManager.java中的getIserviceManager()代码
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 }
所以基本上我们正在掌握本地服务管理员。
这个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&amp;中替换展开这两个宏。 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启动期间在init进程中启动),它将通过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的。在这个函数中,我们传递了我们正在寻找的服务。
远程存根上的GET_SERVICE_TRANSACTION的onTransact函数如下所示:
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返回对所需服务的引用。 /frameworks/base/libs/binder/IServiceManager.cpp中的getService函数 如下所示:
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)传递给它。
此远程服务实际上是在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;
因此,我们最终调用名为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并返回我们正在寻找的服务。
答案 1 :(得分:6)
但我无法理解调用ServiceManager.getService(LOCATION_SERVICE)时会发生什么;甚至在阅读了ServiceManager代码之后。
好的,这里是ServiceManager.java中的getService()的源代码:
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
正如我们所看到的,如果所请求的服务尚未缓存,则会调用getIServiceManager().getService(name)
。 getIServiceManager()是同一个类中的一个方法(我们将在下一步中使用getService(name)):
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
所以这基本上将我们发送到ServiceManagerNative.java我们需要查找getService(名称):
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
启动事务以检索名为“LOCATION_SERVICE”的服务。
由于处理低级别内容(如系统服务)的类和接口的复杂结构,从这里开始变得越来越困难。但基本上它都是在Context.java,ContextImpl.java,ServiceManager.java和ServiceManagerNative.java中完成的。另请注意,其中一些可能会保留本地缓存或映射以及对服务实例的引用(即您可以在上面的ServiceManager.java列表中看到sCache.get(name)
),这是可能来自其他引用的位置。
我不认为你会在StackOverflow上得到更详细的答案,因为它变得非常低级。您可能想问一下Android操作系统上的谷歌员工邮件列表。
答案 2 :(得分:2)
位置管理器,因为大多数系统服务/管理器是在启动过程中的早期阶段创建的。
app_process是启动DalvikVM的本机组件,另外,它告诉ZigoteInit(执行实际工作的类)启动SystemServer。在这里创建了LocationManager的第一个实例,并且引用保存在其中的ServerThread中。
/frameworks/base/services/java/com/android/server/SystemServer.java
DevicePolicyManagerService devicePolicy = null;
StatusBarManagerService statusBar = null;
InputMethodManagerService imm = null;
AppWidgetService appWidget = null;
NotificationManagerService notification = null;
WallpaperManagerService wallpaper = null;
-> LocationManagerService location = null;
CountryDetectorService countryDetector = null;
TextServicesManagerService tsms = null;
LockSettingsService lockSettings = null;
DreamManagerService dreamy = null;
try {
Slog.i(TAG, "Location Manager");
location = new LocationManagerService(context);
ServiceManager.addService(Context.LOCATION_SERVICE, location);
} catch (Throwable e) {
reportWtf("starting Location Manager", e);
}
其他人已经知道了,我想。
答案 3 :(得分:2)
方法getSystemService
public abstract Object getSystemService(String name);
中实施
@Override
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
SYSTEM_SERVICE_MAP是:
private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =
new HashMap<String, ServiceFetcher>();
并且所有服务都在静态块中注册
static {
调用registerService,如下所示:
registerService(LOCATION_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(LOCATION_SERVICE);
return new LocationManager(ctx, ILocationManager.Stub.asInterface(b));
}});
或
registerService(INPUT_SERVICE, new StaticServiceFetcher() {
public Object createStaticService() {
return InputManager.getInstance();
}});
ServiceFetcher和StaticServiceFetcher实现延迟加载模式。