一,serviceManger时序图
本文涉及到的源码文件:
/frameworks/native/cmds/servicemanager/main.cpp
/frameworks/native/libs/binder/ProcessState.cpp
/frameworks/native/cmds/servicemanager/ServiceManager.cpp
/frameworks/native/libs/binder/IPCThreadState.cpp
/system/core/libutils/Looper.cpp
ServiceManager是一个由C/C++编写的系统服务,源码位于/framework/native/cmds/servicemanager中,存在如下文件结构
java层SM
public final class ServiceManager {private static final String TAG = "ServiceManager";private static IServiceManager sServiceManager;private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();private static IServiceManager getIServiceManager() {if (sServiceManager != null) {return sServiceManager;}// Find the service managersServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));return sServiceManager;}/*** Returns a reference to a service with the given name.* * @param name the name of the service to get* @return a reference to the service, or <code>null</code> if the service doesn't exist*/public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {return Binder.allowBlocking(getIServiceManager().getService(name));}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;}/*** Returns a reference to a service with the given name, or throws* {@link NullPointerException} if none is found.** @hide*/public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {final IBinder binder = getService(name);if (binder != null) {return binder;} else {throw new ServiceNotFoundException(name);}}/*** Place a new @a service called @a name into the service* manager.* * @param name the name of the new service* @param service the service object*/public static void addService(String name, IBinder service) {try {getIServiceManager().addService(name, service, false);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}}/*** Place a new @a service called @a name into the service* manager.* * @param name the name of the new service* @param service the service object* @param allowIsolated set to true to allow isolated sandboxed processes* to access this service*/public static void addService(String name, IBinder service, boolean allowIsolated) {try {getIServiceManager().addService(name, service, allowIsolated);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}}/*** Retrieve an existing service called @a name from the* service manager. Non-blocking.*/public static IBinder checkService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {return Binder.allowBlocking(getIServiceManager().checkService(name));}} catch (RemoteException e) {Log.e(TAG, "error in checkService", e);return null;}}/*** Return a list of all currently running services.* @return an array of all currently running services, or <code>null</code> in* case of an exception*/public static String[] listServices() {try {return getIServiceManager().listServices();} catch (RemoteException e) {Log.e(TAG, "error in listServices", e);return null;}}/*** This is only intended to be called when the process is first being brought* up and bound by the activity manager. There is only one thread in the process* at that time, so no locking is done.* * @param cache the cache of service references* @hide*/public static void initServiceCache(Map<String, IBinder> cache) {if (sCache.size() != 0) {throw new IllegalStateException("setServiceCache may only be called once");}sCache.putAll(cache);}/*** Exception thrown when no service published for given name. This might be* thrown early during boot before certain services have published* themselves.** @hide*/public static class ServiceNotFoundException extends Exception {public ServiceNotFoundException(String name) {super("No service published for: " + name);}}
}
native层的SM
/** Copyright (C) 2005 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/#define LOG_TAG "ServiceManager"#include <binder/IServiceManager.h>#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
#include <utils/CallStack.h>#include <private/binder/Static.h>#include <unistd.h>namespace android {sp<IServiceManager> defaultServiceManager()
{if (gDefaultServiceManager != NULL) return gDefaultServiceManager;{AutoMutex _l(gDefaultServiceManagerLock);while (gDefaultServiceManager == NULL) {gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));if (gDefaultServiceManager == NULL)sleep(1);}}return gDefaultServiceManager;
}bool checkCallingPermission(const String16& permission)
{return checkCallingPermission(permission, NULL, NULL);
}static String16 _permission("permission");bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid)
{IPCThreadState* ipcState = IPCThreadState::self();pid_t pid = ipcState->getCallingPid();uid_t uid = ipcState->getCallingUid();if (outPid) *outPid = pid;if (outUid) *outUid = uid;return checkPermission(permission, pid, uid);
}bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
{sp<IPermissionController> pc;gDefaultServiceManagerLock.lock();pc = gPermissionController;gDefaultServiceManagerLock.unlock();int64_t startTime = 0;while (true) {if (pc != NULL) {bool res = pc->checkPermission(permission, pid, uid);if (res) {if (startTime != 0) {ALOGI("Check passed after %d seconds for %s from uid=%d pid=%d",(int)((uptimeMillis()-startTime)/1000),String8(permission).string(), uid, pid);}return res;}// Is this a permission failure, or did the controller go away?if (IInterface::asBinder(pc)->isBinderAlive()) {ALOGW("Permission failure: %s from uid=%d pid=%d",String8(permission).string(), uid, pid);return false;}// Object is dead!gDefaultServiceManagerLock.lock();if (gPermissionController == pc) {gPermissionController = NULL;}gDefaultServiceManagerLock.unlock();}// Need to retrieve the permission controller.sp<IBinder> binder = defaultServiceManager()->checkService(_permission);if (binder == NULL) {// Wait for the permission controller to come back...if (startTime == 0) {startTime = uptimeMillis();ALOGI("Waiting to check permission %s from uid=%d pid=%d",String8(permission).string(), uid, pid);}sleep(1);} else {pc = interface_cast<IPermissionController>(binder);// Install the new permission controller, and try again.gDefaultServiceManagerLock.lock();gPermissionController = pc;gDefaultServiceManagerLock.unlock();}}
}// ----------------------------------------------------------------------class BpServiceManager : public BpInterface<IServiceManager>
{
public:explicit BpServiceManager(const sp<IBinder>& impl): BpInterface<IServiceManager>(impl){}virtual sp<IBinder> getService(const String16& name) const{unsigned n;for (n = 0; n < 5; n++){if (n > 0) {if (!strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder")) {ALOGI("Waiting for vendor service %s...", String8(name).string());CallStack stack(LOG_TAG);} else {ALOGI("Waiting for service %s...", String8(name).string());}sleep(1);}sp<IBinder> svc = checkService(name);if (svc != NULL) return svc;}return NULL;}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();}virtual status_t addService(const String16& name, const sp<IBinder>& service,bool allowIsolated){Parcel data, reply;data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);data.writeStrongBinder(service);data.writeInt32(allowIsolated ? 1 : 0);status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);return err == NO_ERROR ? reply.readExceptionCode() : err;}virtual Vector<String16> listServices(){Vector<String16> res;int n = 0;for (;;) {Parcel data, reply;data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeInt32(n++);status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);if (err != NO_ERROR)break;res.add(reply.readString16());}return res;}
};IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");}; // namespace android
真正的SM服务
/* Copyright 2008 The Android Open Source Project*/#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <cutils/android_filesystem_config.h>
#include <cutils/multiuser.h>#include <selinux/android.h>
#include <selinux/avc.h>#include "binder.h"#ifdef VENDORSERVICEMANAGER
#define LOG_TAG "VendorServiceManager"
#else
#define LOG_TAG "ServiceManager"
#endif
#include <log/log.h>struct audit_data {pid_t pid;uid_t uid;const char *name;
};const char *str8(const uint16_t *x, size_t x_len)
{static char buf[128];size_t max = 127;char *p = buf;if (x_len < max) {max = x_len;}if (x) {while ((max > 0) && (*x != '\0')) {*p++ = *x++;max--;}}*p++ = 0;return buf;
}int str16eq(const uint16_t *a, const char *b)
{while (*a && *b)if (*a++ != *b++) return 0;if (*a || *b)return 0;return 1;
}static char *service_manager_context;
static struct selabel_handle* sehandle;static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
{char *sctx = NULL;const char *class = "service_manager";bool allowed;struct audit_data ad;if (getpidcon(spid, &sctx) < 0) {ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);return false;}ad.pid = spid;ad.uid = uid;ad.name = name;int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);allowed = (result == 0);freecon(sctx);return allowed;
}static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm)
{return check_mac_perms(spid, uid, service_manager_context, perm, NULL);
}static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
{bool allowed;char *tctx = NULL;if (!sehandle) {ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");abort();}if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {ALOGE("SELinux: No match for %s in service_contexts.\n", name);return false;}allowed = check_mac_perms(spid, uid, tctx, perm, name);freecon(tctx);return allowed;
}static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
{const char *perm = "add";if (multiuser_get_app_id(uid) >= AID_APP) {return 0; /* Don't allow apps to register services */}return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
}static int svc_can_list(pid_t spid, uid_t uid)
{const char *perm = "list";return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0;
}static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
{const char *perm = "find";return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
}struct svcinfo
{struct svcinfo *next;uint32_t handle;struct binder_death death;int allow_isolated;size_t len;uint16_t name[0];
};struct svcinfo *svclist = NULL;struct svcinfo *find_svc(const uint16_t *s16, size_t 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 NULL;
}void svcinfo_death(struct binder_state *bs, void *ptr)
{struct svcinfo *si = (struct svcinfo* ) ptr;ALOGI("service '%s' died\n", str8(si->name, si->len));if (si->handle) {binder_release(bs, si->handle);si->handle = 0;}
}uint16_t svcmgr_id[] = {'a','n','d','r','o','i','d','.','o','s','.','I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
};uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{struct svcinfo *si = find_svc(s, len);if (!si || !si->handle) {return 0;}if (!si->allow_isolated) {// If this service doesn't allow access from isolated processes,// then check the uid to see if it is isolated.uid_t appid = uid % AID_USER;if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {return 0;}}if (!svc_can_find(s, len, spid, uid)) {return 0;}return si->handle;
}int do_add_service(struct binder_state *bs,const uint16_t *s, size_t len,uint32_t handle, uid_t uid, int allow_isolated,pid_t spid)
{struct svcinfo *si;//ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,// allow_isolated ? "allow_isolated" : "!allow_isolated", uid);if (!handle || (len == 0) || (len > 127))return -1;if (!svc_can_register(s, len, spid, uid)) {ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",str8(s, len), handle, uid);return -1;}si = find_svc(s, len);if (si) {if (si->handle) {ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",str8(s, len), handle, uid);svcinfo_death(bs, si);}si->handle = handle;} else {si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));if (!si) {ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",str8(s, len), handle, uid);return -1;}si->handle = handle;si->len = len;memcpy(si->name, s, (len + 1) * sizeof(uint16_t));si->name[len] = '\0';si->death.func = (void*) svcinfo_death;si->death.ptr = si;si->allow_isolated = allow_isolated;si->next = svclist;svclist = si;}binder_acquire(bs, handle);binder_link_to_death(bs, handle, &si->death);return 0;
}int svcmgr_handler(struct binder_state *bs,struct binder_transaction_data *txn,struct binder_io *msg,struct binder_io *reply)
{struct svcinfo *si;uint16_t *s;size_t len;uint32_t handle;uint32_t strict_policy;int allow_isolated;//ALOGI("target=%p code=%d pid=%d uid=%d\n",// (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);if (txn->target.ptr != BINDER_SERVICE_MANAGER)return -1;if (txn->code == PING_TRANSACTION)return 0;// Equivalent to Parcel::enforceInterface(), reading the RPC// header with the strict mode policy mask and the interface name.// Note that we ignore the strict_policy and don't propagate it// further (since we do no outbound RPCs anyway).strict_policy = bio_get_uint32(msg);s = bio_get_string16(msg, &len);if (s == NULL) {return -1;}if ((len != (sizeof(svcmgr_id) / 2)) ||memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {fprintf(stderr,"invalid id %s\n", str8(s, len));return -1;}if (sehandle && selinux_status_updated() > 0) {
#ifdef VENDORSERVICEMANAGERstruct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle();
#elsestruct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
#endifif (tmp_sehandle) {selabel_close(sehandle);sehandle = tmp_sehandle;}}switch(txn->code) {case SVC_MGR_GET_SERVICE:case SVC_MGR_CHECK_SERVICE:s = bio_get_string16(msg, &len);if (s == NULL) {return -1;}handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);if (!handle)break;bio_put_ref(reply, handle);return 0;case SVC_MGR_ADD_SERVICE:s = bio_get_string16(msg, &len);if (s == NULL) {return -1;}handle = bio_get_ref(msg);allow_isolated = bio_get_uint32(msg) ? 1 : 0;if (do_add_service(bs, s, len, handle, txn->sender_euid,allow_isolated, txn->sender_pid))return -1;break;case SVC_MGR_LIST_SERVICES: {uint32_t n = bio_get_uint32(msg);if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {ALOGE("list_service() uid=%d - PERMISSION DENIED\n",txn->sender_euid);return -1;}si = svclist;while ((n-- > 0) && si)si = si->next;if (si) {bio_put_string16(reply, si->name);return 0;}return -1;}default:ALOGE("unknown code %d\n", txn->code);return -1;}bio_put_uint32(reply, 0);return 0;
}static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
{struct audit_data *ad = (struct audit_data *)data;if (!ad || !ad->name) {ALOGE("No service manager audit data");return 0;}snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);return 0;
}int main(int argc, char** argv)
{struct binder_state *bs;union selinux_callback cb;char *driver;if (argc > 1) {driver = argv[1];} else {driver = "/dev/binder";}bs = binder_open(driver, 128*1024);if (!bs) {
#ifdef VENDORSERVICEMANAGERALOGW("failed to open binder driver %s\n", driver);while (true) {sleep(UINT_MAX);}
#elseALOGE("failed to open binder driver %s\n", driver);
#endifreturn -1;}if (binder_become_context_manager(bs)) {ALOGE("cannot become context manager (%s)\n", strerror(errno));return -1;}cb.func_audit = audit_callback;selinux_set_callback(SELINUX_CB_AUDIT, cb);cb.func_log = selinux_log_callback;selinux_set_callback(SELINUX_CB_LOG, cb);#ifdef VENDORSERVICEMANAGERsehandle = selinux_android_vendor_service_context_handle();
#elsesehandle = selinux_android_service_context_handle();
#endifselinux_status_open(true);if (sehandle == NULL) {ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");abort();}if (getcon(&service_manager_context) != 0) {ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");abort();}binder_loop(bs, svcmgr_handler);return 0;
}
二,serviceManger运行时时序图
从上述代码可以明确知道:ServiceManager程序一旦启动运行,则不会停止(系统不宕机的情况下),将会一直looper->pollAll(-1)。除此之外,还知道ServiceManager默认情况依托于/dev/binder这个设备节点,当然可以通过向ServiceManager传递参数指定设备节点。ServiceManager作为binder机制的核心组件之一,在实现进程间通信中占据着不可获取的地位。
从Android.bp可以知道,ServiceManager对应的程序名称是servicemanager。从Android.bp文件中,还存在一个名为vndservicemanager的程序,它们的源码都是一样的,只是rc文件存在出入,将传入/dev/vndbinder作为binder驱动。在Android启动启动过程中,vndservicemanager和vndservicemanager都会被init拉起,他俩的区别总结如下:
1、对于servicemanager:
servicemanager是 Android 系统中的核心服务管理器,用于管理系统级的服务。
servicemanager管理的服务包括系统级服务(如ActivityManager、PackageManager、WindowManager等)和由应用程序注册的系统服务。
servicemanager的访问权限较高,一般只有系统级应用或者具有系统权限的应用程序才能够使用servicemanager进行服务的注册和查询。
2、对于vndservicemanager:
vndservicemanager是 servicemanager的一个扩展,用于管理供应商特定的服务。
vndservicemanager管理的服务通常是供应商(vendor)特定的、定制化的服务,例如硬件厂商提供的驱动程序或服务。
vndservicemanager的访问权限一般较低,通常只有供应商特定的应用程序或系统组件才能够使用vndservicemanager进行服务的注册和查询。
二、ServiceManager的启动
第一小节简要介绍了ServiceManager,我们知道ServiceManager是一个具体程序,如果是个程序,那么该程序是如何启动的呢?又在什么时候触发运行的呢?
我们知道Android系统的第一个进程是init,这是由内核决定的。那么在init中将通过解析init.rc来启动系统的一些关键服务进程。其中ServiceManager就在这个时候启动运行