3.Android内核 ServiceManager

来源:互联网 发布:并发编程博客 编辑:程序博客网 时间:2024/05/16 15:05




getSystemService很尽职,你知道吗?



   那个...嗯...曾记否上篇的2.Android Binder 中留下的疑问?就是在Context的实现类中使用

getSystemService(String serviceName)方法获取一个系统服务,那么这些系统服务的Binder

引用时如何传递给客户端的呢?其实这里有个关键点,就是系统服务并不是通过startService()启

动的。


   getSystemService函数的实现是在Context的实现类中,该函数返回的Service比较多。那

么就让我们看一下ActivityContextThemeWrapper的部分源代码吧:


Activity:

    @Override    public Object getSystemService(@ServiceName @NonNull String name) {        if (getBaseContext() == null) {            throw new IllegalStateException(                    "System services not available to Activities before onCreate()");        }        if (WINDOW_SERVICE.equals(name)) {            return mWindowManager;        } else if (SEARCH_SERVICE.equals(name)) {            ensureSearchManager();            return mSearchManager;        }        return super.getSystemService(name);    }


   1.首先, if (getBaseContext() == null)判断 mBase(Context类型)是否为空。如果为空则 ,提

示Context没创建前调用了getSystemService的错误。至于,我为什么能准确地mBase这个名字呢?让

我们再看一段关于ContextWrapperActivity的父类Context的子类)的源代码

    Context mBase;    public ContextWrapper(Context base) {        mBase = base;    }        /**     * Set the base context for this ContextWrapper.  All calls will then be     * delegated to the base context.  Throws     * IllegalStateException if a base context has already been set.     *      * @param base The new base context for this wrapper.     */    protected void attachBaseContext(Context base) {        if (mBase != null) {            throw new IllegalStateException("Base context already set");        }        mBase = base;    }    /**     * @return the base context as set by the constructor or setBaseContext     */    public Context getBaseContext() {        return mBase;    }

   以上很简单,也就是从父类继承下来的Context mBase属性。


   2.if (WINDOW_SERVICE.equals(name)) {......}elseif(SEARCH_SERVICE.equals(name)){......}。这个

就是判断要取的服务是Window类型还是Search类型的。这个在Activity里有对应的WindowManager类

型和SearchManager类型属性,并且做了对应的实例化。


   3.return super.getSystemService(name)当要取的服务不是Window类型也不是Search类型的时候,就

调用了父类(ContextThemeWrapper)的getSystemService(String name)帮你找服务。那么就让我们顺便看看

ContextThemeWrapper的源代码

    @Override public Object getSystemService(String name) {        if (LAYOUT_INFLATER_SERVICE.equals(name)) {            if (mInflater == null) {                mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);            }            return mInflater;        }        return getBaseContext().getSystemService(name);    }


   4.这里也做了个Activity里类似的判断是否为 layout Inflater 服务,然后返回相应的layout Inflater 服务。


   5.return getBaseContext().getSystemService(name):这里的话就回到了Context 这个抽象的基类。 我

们就再看看Context的源代码


    /**     * Return the handle to a system-level service by name. The class of the     * returned object varies by the requested name. Currently available names     * are:     *     * <dl>     *  <dt> {@link #WINDOW_SERVICE} ("window")     *  <dd> The top-level window manager in which you can place custom     *  windows.  The returned object is a {@link android.view.WindowManager}.     *  <dt> {@link #LAYOUT_INFLATER_SERVICE} ("layout_inflater")     *  <dd> A {@link android.view.LayoutInflater} for inflating layout resources     *  in this context.     *  <dt> {@link #ACTIVITY_SERVICE} ("activity")     *  <dd> A {@link android.app.ActivityManager} for interacting with the     *  global activity state of the system.     *  <dt> {@link #POWER_SERVICE} ("power")     *  <dd> A {@link android.os.PowerManager} for controlling power     *  management.     *  <dt> {@link #ALARM_SERVICE} ("alarm")     *  <dd> A {@link android.app.AlarmManager} for receiving intents at the     *  time of your choosing.     *  <dt> {@link #NOTIFICATION_SERVICE} ("notification")     *  <dd> A {@link android.app.NotificationManager} for informing the user     *   of background events.     *  <dt> {@link #KEYGUARD_SERVICE} ("keyguard")     *  <dd> A {@link android.app.KeyguardManager} for controlling keyguard.     *  <dt> {@link #LOCATION_SERVICE} ("location")     *  <dd> A {@link android.location.LocationManager} for controlling location     *   (e.g., GPS) updates.     *  <dt> {@link #SEARCH_SERVICE} ("search")     *  <dd> A {@link android.app.SearchManager} for handling search.     *  <dt> {@link #VIBRATOR_SERVICE} ("vibrator")     *  <dd> A {@link android.os.Vibrator} for interacting with the vibrator     *  hardware.     *  <dt> {@link #CONNECTIVITY_SERVICE} ("connection")     *  <dd> A {@link android.net.ConnectivityManager ConnectivityManager} for     *  handling management of network connections.     *  <dt> {@link #WIFI_SERVICE} ("wifi")     *  <dd> A {@link android.net.wifi.WifiManager WifiManager} for management of     * Wi-Fi connectivity.     *  <dt> {@link #WIFI_P2P_SERVICE} ("wifip2p")     *  <dd> A {@link android.net.wifi.p2p.WifiP2pManager WifiP2pManager} for management of     * Wi-Fi Direct connectivity.     * <dt> {@link #INPUT_METHOD_SERVICE} ("input_method")     * <dd> An {@link android.view.inputmethod.InputMethodManager InputMethodManager}     * for management of input methods.     * <dt> {@link #UI_MODE_SERVICE} ("uimode")     * <dd> An {@link android.app.UiModeManager} for controlling UI modes.     * <dt> {@link #DOWNLOAD_SERVICE} ("download")     * <dd> A {@link android.app.DownloadManager} for requesting HTTP downloads     * <dt> {@link #BATTERY_SERVICE} ("batterymanager")     * <dd> A {@link android.os.BatteryManager} for managing battery state     * <dt> {@link #JOB_SCHEDULER_SERVICE} ("taskmanager")     * <dd>  A {@link android.app.job.JobScheduler} for managing scheduled tasks     * </dl>     *     * <p>Note:  System services obtained via this API may be closely associated with     * the Context in which they are obtained from.  In general, do not share the     * service objects between various different contexts (Activities, Applications,     * Services, Providers, etc.)     *     * @param name The name of the desired service.     *     * @return The service or null if the name does not exist.     *     * @see #WINDOW_SERVICE     * @see android.view.WindowManager     * @see #LAYOUT_INFLATER_SERVICE     * @see android.view.LayoutInflater     * @see #ACTIVITY_SERVICE     * @see android.app.ActivityManager     * @see #POWER_SERVICE     * @see android.os.PowerManager     * @see #ALARM_SERVICE     * @see android.app.AlarmManager     * @see #NOTIFICATION_SERVICE     * @see android.app.NotificationManager     * @see #KEYGUARD_SERVICE     * @see android.app.KeyguardManager     * @see #LOCATION_SERVICE     * @see android.location.LocationManager     * @see #SEARCH_SERVICE     * @see android.app.SearchManager     * @see #SENSOR_SERVICE     * @see android.hardware.SensorManager     * @see #STORAGE_SERVICE     * @see android.os.storage.StorageManager     * @see #VIBRATOR_SERVICE     * @see android.os.Vibrator     * @see #CONNECTIVITY_SERVICE     * @see android.net.ConnectivityManager     * @see #WIFI_SERVICE     * @see android.net.wifi.WifiManager     * @see #AUDIO_SERVICE     * @see android.media.AudioManager     * @see #MEDIA_ROUTER_SERVICE     * @see android.media.MediaRouter     * @see #TELEPHONY_SERVICE     * @see android.telephony.TelephonyManager     * @see #INPUT_METHOD_SERVICE     * @see android.view.inputmethod.InputMethodManager     * @see #UI_MODE_SERVICE     * @see android.app.UiModeManager     * @see #DOWNLOAD_SERVICE     * @see android.app.DownloadManager     * @see #BATTERY_SERVICE     * @see android.os.BatteryManager     * @see #JOB_SCHEDULER_SERVICE     * @see android.app.job.JobScheduler     */    public abstract Object getSystemService(@ServiceName @NonNull String name);    /******************************以下是服务的名称***************************/    /**     * 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     */     /*******************************下面还有很多很多*************************/


   6.以上可以看出,如果在Activity和ContextThemeWrapper不能帮你取到服务的话,最终会回到Context来一个"大搜查"






ServiceManager 管理的服务


   ServiceManager是一个独立的进程!这里特别强调它是一个进程!作用就跟它的名称一样,管理各种系统服务,如下图所示:







   其实ServiceManager本身也是一个Service,Framework提供了一个系统函数,可以获取ServiceManager

对应的Binder引用,那就是BinderInternal.getContextObject()。该静态函数返回ServiceManager后,就

可以通过ServiceManger提供的方法获取其他服务Service的Binder引用。这种设计模式就好比:ServiceManager

是一个公司的总机,这个总计的号码是公开的,系统中任何进程都可以使用BinderInternal.getContextObject()

获取该总机的Binder对象,而当前用户想联系公司的其他人(服务)的时候,则要经过总机再获取到分机的号码。

这种设计模式的优点就是:系统中仅仅只暴漏一个全局Binder引用,那就是ServiceManager,而其他服务则可以

隐藏起来,从而有助于系统服务的扩展,以及调用系统服务的安全检查其他系统服务在启动的时候,首先把自己

的Binder对象传递给ServiceManager,就是所谓的注册(addService)



BinderInternal.getContextObject() ->ServiceManager ->其它Service的Binder引用


那么我们来看一看ServiceManager.getService()的源码


public static IBinder getService(String name){try{IBinder service = sCache.get(name);if(servie != null){return service}else{return getIServiceManager().getService(name);}}catch (RemoteException e) {Log.e(TAG, "error in getService",e);}return null;}


以上片段源码,sCache.get(name) 缓存中查看是否有对应的 Binder 对象有则返回没有则调用 

return getIServiceManager.getService(name)第一个getIServiceManager()即用于返回系统中

唯一的ServiceManager对应的Binder。



接着看看getIServiceManager()


private static IServiceManager getIServiceManager() {if (sServiceManager != null) {return sServiceManager;}// Find the service managersServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());return sServiceManager;}




以上源码中,BinderInternal.getContextObject()静态函数用于返回ServiceManager对应的全局Binder

对象,该函数不需要任何参数,因为它的作用所致是固定的。


其他所有通过ServiceManager获取的系统服务的过程与以上基本相似,所不同的就是传递给ServiceManager

的服务名称不同,因为ServiceManager正是按照服务的名称(String)来保存不同的Binder





Android 中的 Manager


在Android中,Manager的含义应该翻译为“经纪人”,Manager所管理的对象时服务本身,因为每一

个具体的服务一般都会提供多个API接口,而Manager所管理的就是这些API客户端一般不能直接通过

Binder访问的服务,而是要经过一个Manager,对应的Manager类对客户端是可见的,而远程的服务类

对客户端是隐藏的。


而这些Manager的类内部都会存在一个远程服务Binder的变量,而且在一般情况下,这些Manager的构造

函数中都会包含这个Binder对象。即先通过ServiceManager获取远程服务的Binder引用,然后使用这个Binder

引用构造一个客户端本地可以访问的经纪人,然后客户端就可以通过经纪人间接访问远程的服务了。


这种设计的作用是为了屏蔽客户端直接访问远程服务,从而可以给应用程序提供灵活的、可控的API接口,比

如Ams。系统不希望用户直接去访问Ams,而是经过ActivityManager类去访问,而ActivityManager内部则

提供一些更具可操作性的数据结构,比如RecentTaskInfo数据结构封装了最近访问过的Task列表;MemoryInfo

数据类封装了和内存相关的信息。如下(RecentTaskInfo和MemoryInfo的源代码):


ActivityManager 中的 RecentTaskInfo 类 源码


    /**     * Information you can retrieve about tasks that the user has most recently     * started or visited.     */    public static class RecentTaskInfo implements Parcelable {        /**         * If this task is currently running, this is the identifier for it.         * If it is not running, this will be -1.         */        public int id;        /**         * The true identifier of this task, valid even if it is not running.         */        public int persistentId;                /**         * The original Intent used to launch the task.  You can use this         * Intent to re-launch the task (if it is no longer running) or bring         * the current task to the front.         */        public Intent baseIntent;        /**         * If this task was started from an alias, this is the actual         * activity component that was initially started; the component of         * the baseIntent in this case is the name of the actual activity         * implementation that the alias referred to.  Otherwise, this is null.         */        public ComponentName origActivity;        /**         * Description of the task's last state.         */        public CharSequence description;        /**         * The id of the ActivityStack this Task was on most recently.         * @hide         */        public int stackId;        /**         * The id of the user the task was running as.         * @hide         */        public int userId;        /**         * The first time this task was active.         * @hide         */        public long firstActiveTime;        /**         * The last time this task was active.         * @hide         */        public long lastActiveTime;        /**         * The recent activity values for the highest activity in the stack to have set the values.         * {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.         */        public TaskDescription taskDescription;        /**         * Task affiliation for grouping with other tasks.         */        public int affiliatedTaskId;        /**         * Task affiliation color of the source task with the affiliated task id.         *         * @hide         */        public int affiliatedTaskColor;        public RecentTaskInfo() {        }        @Override        public int describeContents() {            return 0;        }        @Override        public void writeToParcel(Parcel dest, int flags) {            dest.writeInt(id);            dest.writeInt(persistentId);            if (baseIntent != null) {                dest.writeInt(1);                baseIntent.writeToParcel(dest, 0);            } else {                dest.writeInt(0);            }            ComponentName.writeToParcel(origActivity, dest);            TextUtils.writeToParcel(description, dest,                    Parcelable.PARCELABLE_WRITE_RETURN_VALUE);            if (taskDescription != null) {                dest.writeInt(1);                taskDescription.writeToParcel(dest, 0);            } else {                dest.writeInt(0);            }            dest.writeInt(stackId);            dest.writeInt(userId);            dest.writeLong(firstActiveTime);            dest.writeLong(lastActiveTime);            dest.writeInt(affiliatedTaskId);            dest.writeInt(affiliatedTaskColor);        }        public void readFromParcel(Parcel source) {            id = source.readInt();            persistentId = source.readInt();            baseIntent = source.readInt() > 0 ? Intent.CREATOR.createFromParcel(source) : null;            origActivity = ComponentName.readFromParcel(source);            description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);            taskDescription = source.readInt() > 0 ?                    TaskDescription.CREATOR.createFromParcel(source) : null;            stackId = source.readInt();            userId = source.readInt();            firstActiveTime = source.readLong();            lastActiveTime = source.readLong();            affiliatedTaskId = source.readInt();            affiliatedTaskColor = source.readInt();        }        public static final Creator<RecentTaskInfo> CREATOR                = new Creator<RecentTaskInfo>() {            public RecentTaskInfo createFromParcel(Parcel source) {                return new RecentTaskInfo(source);            }            public RecentTaskInfo[] newArray(int size) {                return new RecentTaskInfo[size];            }        };        private RecentTaskInfo(Parcel source) {            readFromParcel(source);        }    }


ActivityManager 的 MemoryInfo类 源代码 :


    /**     * Information you can retrieve about the available memory through     * {@link ActivityManager#getMemoryInfo}.     */    public static class MemoryInfo implements Parcelable {        /**         * The available memory on the system.  This number should not         * be considered absolute: due to the nature of the kernel, a significant         * portion of this memory is actually in use and needed for the overall         * system to run well.         */        public long availMem;        /**         * The total memory accessible by the kernel.  This is basically the         * RAM size of the device, not including below-kernel fixed allocations         * like DMA buffers, RAM for the baseband CPU, etc.         */        public long totalMem;        /**         * The threshold of {@link #availMem} at which we consider memory to be         * low and start killing background services and other non-extraneous         * processes.         */        public long threshold;                /**         * Set to true if the system considers itself to currently be in a low         * memory situation.         */        public boolean lowMemory;        /** @hide */        public long hiddenAppThreshold;        /** @hide */        public long secondaryServerThreshold;        /** @hide */        public long visibleAppThreshold;        /** @hide */        public long foregroundAppThreshold;        public MemoryInfo() {        }        public int describeContents() {            return 0;        }        public void writeToParcel(Parcel dest, int flags) {            dest.writeLong(availMem);            dest.writeLong(totalMem);            dest.writeLong(threshold);            dest.writeInt(lowMemory ? 1 : 0);            dest.writeLong(hiddenAppThreshold);            dest.writeLong(secondaryServerThreshold);            dest.writeLong(visibleAppThreshold);            dest.writeLong(foregroundAppThreshold);        }                public void readFromParcel(Parcel source) {            availMem = source.readLong();            totalMem = source.readLong();            threshold = source.readLong();            lowMemory = source.readInt() != 0;            hiddenAppThreshold = source.readLong();            secondaryServerThreshold = source.readLong();            visibleAppThreshold = source.readLong();            foregroundAppThreshold = source.readLong();        }        public static final Creator<MemoryInfo> CREATOR                = new Creator<MemoryInfo>() {            public MemoryInfo createFromParcel(Parcel source) {                return new MemoryInfo(source);            }            public MemoryInfo[] newArray(int size) {                return new MemoryInfo[size];            }        };        private MemoryInfo(Parcel source) {            readFromParcel(source);        }    }



这种通过Manager 访问远程服务的模型如下图:





0 0
原创粉丝点击