系统服务中的Binder对象
在应用程序编程时,经常使用getSystemService(String serviceName)方法获取一个系统服务,那么,这些系统服务的Binder引用是如何传递给客户端的呢?须知系统服务并不是通过startService()启动的。
getSystemService()函数的实现是在ContextImpl类中,该函数所返回的Service比较多,具体可参照源码。这些Service一般都由ServiceManager管理。
@Override public Object getSystemService(String name) { if (WINDOW_SERVICE.equals(name)) { return WindowManagerImpl.getDefault(); } else if (LAYOUT_INFLATER_SERVICE.equals(name)) { synchronized (mSync) { LayoutInflater inflater = mLayoutInflater; if (inflater != null) { return inflater; } mLayoutInflater = inflater = PolicyManager.makeNewLayoutInflater(getOuterContext()); return inflater; } } else if (ACTIVITY_SERVICE.equals(name)) { return getActivityManager(); } else if (INPUT_METHOD_SERVICE.equals(name)) { return InputMethodManager.getInstance(this); } else if (ALARM_SERVICE.equals(name)) { return getAlarmManager(); } else if (ACCOUNT_SERVICE.equals(name)) { return getAccountManager(); } else if (POWER_SERVICE.equals(name)) { return getPowerManager(); } else if (CONNECTIVITY_SERVICE.equals(name)) { return getConnectivityManager(); } else if (THROTTLE_SERVICE.equals(name)) { return getThrottleManager(); } else if (WIFI_SERVICE.equals(name)) { return getWifiManager(); } else if (NOTIFICATION_SERVICE.equals(name)) { return getNotificationManager(); } else if (KEYGUARD_SERVICE.equals(name)) { return new KeyguardManager(); } else if (ACCESSIBILITY_SERVICE.equals(name)) { return AccessibilityManager.getInstance(this); } else if (LOCATION_SERVICE.equals(name)) { return getLocationManager(); } else if (SEARCH_SERVICE.equals(name)) { return getSearchManager(); } else if (SENSOR_SERVICE.equals(name)) { return getSensorManager(); } else if (STORAGE_SERVICE.equals(name)) { return getStorageManager(); } else if (VIBRATOR_SERVICE.equals(name)) { return getVibrator(); } else if (STATUS_BAR_SERVICE.equals(name)) { synchronized (mSync) { if (mStatusBarManager == null) { mStatusBarManager = new StatusBarManager(getOuterContext()); } return mStatusBarManager; } } else if (AUDIO_SERVICE.equals(name)) { return getAudioManager(); } else if (TELEPHONY_SERVICE.equals(name)) { return getTelephonyManager(); } else if (CLIPBOARD_SERVICE.equals(name)) { return getClipboardManager(); } else if (WALLPAPER_SERVICE.equals(name)) { return getWallpaperManager(); } else if (DROPBOX_SERVICE.equals(name)) { return getDropBoxManager(); } else if (DEVICE_POLICY_SERVICE.equals(name)) { return getDevicePolicyManager(); } else if (UI_MODE_SERVICE.equals(name)) { return getUiModeManager(); } else if (DOWNLOAD_SERVICE.equals(name)) { return getDownloadManager(); } else if (NFC_SERVICE.equals(name)) { return getNfcManager(); } return null; }
// activity manager private ActivityManager getActivityManager() { synchronized (mSync) { if (mActivityManager == null) { mActivityManager = new ActivityManager(getOuterContext(), mMainThread.getHandler()); } } return mActivityManager; } // alarm manager private AlarmManager getAlarmManager() { synchronized (sSync) { if (sAlarmManager == null) { IBinder b = ServiceManager.getService(ALARM_SERVICE); IAlarmManager service = IAlarmManager.Stub.asInterface(b); sAlarmManager = new AlarmManager(service); } } return sAlarmManager; }
ServiceManager管理的服务
ServiceManager是一个独立进程,其作用如名称所示,管理各种系统服务,管理的逻辑如下所示。
ServiceManager |
AlarmService |
InputMethodManagerService |
VibrationService |
AccountManagerService |
WIFIService |
LOcationService |
... |
ServiceManager本身也是一个Service,Framework提供了一个系统函数,可以获取该Service对应的Binder引用,那就是BinderInternal.getContextObject()。该静态函数返回ServiceManager后,就可以通过ServiceManager提供的方法获取其他系统Service的Binder引用。这种设计模式在日常生活中到处可见,ServiceManager就像是一个公司的总机,这个总机号码是公开的,系统中任何进程都可以使用BinderInternal.getContextObject()获取该总机的Binder对象,而当用户想联系公司中的其他人(服务)时,则要经过总机再获得分机号码。这种设计的好处是系统中仅暴露一个全局Binder引用,那就是ServiceManager,而其他系统服务则可以隐藏起来,从而有助于系统服务的扩展,以及调用系统服务的安全检查。其他系统服务在启动时,首先把自己的Binder对象传递给ServiceManager,即所谓的注册(addService)。
下面从代码实现来看以上逻辑。可以查看ContextImpl.getSystemService()中各种Service的具体获取方式,比如INPUT_METHOD_SERVICE,代码如下:
} else if (INPUT_METHOD_SERVICE.equals(name)) { return InputMethodManager.getInstance(this); }
而InputMethodManager.getInstance(this)的关键代码如下:
/** * Retrieve the global InputMethodManager instance, creating it if it * doesn't already exist. * @hide */ static public InputMethodManager getInstance(Context context) { return getInstance(context.getMainLooper()); }
/** * Internally, the input method manager can't be context-dependent, so * we have this here for the places that need it. * @hide */ static public InputMethodManager getInstance(Looper mainLooper) { synchronized (mInstanceSync) { if (mInstance != null) { return mInstance; } IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE); IInputMethodManager service = IInputMethodManager.Stub.asInterface(b); mInstance = new InputMethodManager(service, mainLooper); } return mInstance; }
即通过ServiceManager获取InputMethod Service对应的Binder对象b,然后再将该Binder对象作为IInputMethodManager.Stub.asInterface()的参数,返回一个IInputMethodManager的统一接口。
ServiceManager.getService()的代码如下:
/** * 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 getIServiceManager().getService(name); } } catch (RemoteException e) { Log.e(TAG, "error in getService", e); } return null; }
即首先从sCache缓存中查看是否有对应的Binder对象,有则返回,没有则调用getIServiceManager().getService(name),第一个函数getIServiceManager()即用于返回系统中唯一的ServiceManager对应的Binder,其代码如下:
private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; }
以上代码中,BinderInternal.getContextObject()静态函数即用于返回ServiceManager对应的全局Binder对象,该函数不需要任何参数,因为它的作用是固定的。从这个角度来看,这个函数的命名似乎更应该明确一些,比如,可以命名为getServiceManager()。
其他所有通过ServiceManager获取的系统服务的过程与以上基本类似,所不同的就是传递给ServiceManager的服务名称不同,因为ServiceManager正是按照服务的名称(String类型)来保存不同的Binder对象的。
关于使用addService()向ServiceManager中添加一个服务一般是在SystemService进程启动时完成的,具体见关于Framework启动过程的描述。
系统服务列表
/** * Use with {@link #getSystemService} to retrieve a * {@link android.os.PowerManager} for controlling power management, * including "wake locks," which let you keep the device on while * you're running long tasks. */ public static final String POWER_SERVICE = "power"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.view.WindowManager} for accessing the system's window * manager. * * @see #getSystemService * @see android.view.WindowManager */ public static final String WINDOW_SERVICE = "window"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.view.LayoutInflater} for inflating layout resources in this * context. * * @see #getSystemService * @see android.view.LayoutInflater */ public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.accounts.AccountManager} for receiving intents at a * time of your choosing. * * @see #getSystemService * @see android.accounts.AccountManager */ public static final String ACCOUNT_SERVICE = "account"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.app.ActivityManager} for interacting with the global * system state. * * @see #getSystemService * @see android.app.ActivityManager */ public static final String ACTIVITY_SERVICE = "activity"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.app.AlarmManager} for receiving intents at a * time of your choosing. * * @see #getSystemService * @see android.app.AlarmManager */ public static final String ALARM_SERVICE = "alarm"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.app.NotificationManager} for informing the user of * background events. * * @see #getSystemService * @see android.app.NotificationManager */ public static final String NOTIFICATION_SERVICE = "notification"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.view.accessibility.AccessibilityManager} for giving the user * feedback for UI events through the registered event listeners. * * @see #getSystemService * @see android.view.accessibility.AccessibilityManager */ public static final String ACCESSIBILITY_SERVICE = "accessibility"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.app.NotificationManager} for controlling keyguard. * * @see #getSystemService * @see android.app.KeyguardManager */ public static final String KEYGUARD_SERVICE = "keyguard"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.location.LocationManager} for controlling location * updates. * * @see #getSystemService * @see android.location.LocationManager */ public static final String LOCATION_SERVICE = "location"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.app.SearchManager} for handling searches. * * @see #getSystemService * @see android.app.SearchManager */ public static final String SEARCH_SERVICE = "search"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.hardware.SensorManager} for accessing sensors. * * @see #getSystemService * @see android.hardware.SensorManager */ public static final String SENSOR_SERVICE = "sensor"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.os.storage.StorageManager} for accessing system storage * functions. * * @see #getSystemService * @see android.os.storage.StorageManager */ public static final String STORAGE_SERVICE = "storage"; /** * Use with {@link #getSystemService} to retrieve a * com.android.server.WallpaperService for accessing wallpapers. * * @see #getSystemService */ public static final String WALLPAPER_SERVICE = "wallpaper"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.os.Vibrator} for interacting with the vibration hardware. * * @see #getSystemService * @see android.os.Vibrator */ public static final String VIBRATOR_SERVICE = "vibrator"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.app.StatusBarManager} for interacting with the status bar. * * @see #getSystemService * @see android.app.StatusBarManager * @hide */ public static final String STATUS_BAR_SERVICE = "statusbar"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.net.ConnectivityManager} for handling management of * network connections. * * @see #getSystemService * @see android.net.ConnectivityManager */ public static final String CONNECTIVITY_SERVICE = "connectivity"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.net.ThrottleManager} for handling management of * throttling. * * @hide * @see #getSystemService * @see android.net.ThrottleManager */ public static final String THROTTLE_SERVICE = "throttle"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.net.NetworkManagementService} for handling management of * system network services * * @hide * @see #getSystemService * @see android.net.NetworkManagementService */ public static final String NETWORKMANAGEMENT_SERVICE = "network_management"; /** * Use with {@link #getSystemService} to retrieve a {@link * android.net.wifi.WifiManager} for handling management of * Wi-Fi access. * * @see #getSystemService * @see android.net.wifi.WifiManager */ public static final String WIFI_SERVICE = "wifi"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.media.AudioManager} for handling management of volume, * ringer modes and audio routing. * * @see #getSystemService * @see android.media.AudioManager */ public static final String AUDIO_SERVICE = "audio"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.telephony.TelephonyManager} for handling management the * telephony features of the device. * * @see #getSystemService * @see android.telephony.TelephonyManager */ public static final String TELEPHONY_SERVICE = "phone"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.text.ClipboardManager} for accessing and modifying * the contents of the global clipboard. * * @see #getSystemService * @see android.text.ClipboardManager */ public static final String CLIPBOARD_SERVICE = "clipboard"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.view.inputmethod.InputMethodManager} for accessing input * methods. * * @see #getSystemService */ public static final String INPUT_METHOD_SERVICE = "input_method"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.appwidget.AppWidgetManager} for accessing AppWidgets. * * @hide * @see #getSystemService */ public static final String APPWIDGET_SERVICE = "appwidget"; /** * Use with {@link #getSystemService} to retrieve an * {@link android.app.backup.IBackupManager IBackupManager} for communicating * with the backup mechanism. * @hide * * @see #getSystemService */ public static final String BACKUP_SERVICE = "backup"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.os.DropBoxManager} instance for recording * diagnostic logs. * @see #getSystemService */ public static final String DROPBOX_SERVICE = "dropbox"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.app.admin.DevicePolicyManager} for working with global * device policy management. * * @see #getSystemService */ public static final String DEVICE_POLICY_SERVICE = "device_policy"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.app.UiModeManager} for controlling UI modes. * * @see #getSystemService */ public static final String UI_MODE_SERVICE = "uimode"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.app.DownloadManager} for requesting HTTP downloads. * * @see #getSystemService */ public static final String DOWNLOAD_SERVICE = "download"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.nfc.NfcManager} for using NFC. * * @see #getSystemService */ public static final String NFC_SERVICE = "nfc"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.net.sip.SipManager} for accessing the SIP related service. * * @see #getSystemService */ /** @hide */ public static final String SIP_SERVICE = "sip";