bind Service 基础

    技术2022-07-10  193

    一、bind service涉及到的数据结构

    1、概览 ServiceRecord首先针对intent,维护一个IntentBindRecord map; 在IntentBindRecord中又针对ProcessRecord,维护一个AppBindRecord的map ; 在AppBindRecord中维护一个ConnectionRecord的集合。

    主要结构如下图 2、细节 1)ConnectionRecord 描述单个service的绑定,持有上一级AppBindRecord的引用,对应客户端的ServiceConnection

    final AppBindRecord binding; // The application/service binding.

    添加connection : bindServiceLocked

    移除connection : removeConnectionLocked,具体见 2)中代码

    2)AppBindRecord 描述一个Service与Client application的关联

    final ServiceRecord service; // The running service. final IntentBindRecord intent; // The intent we are bound to. final ProcessRecord client; // Who has started/bound the service. final ArraySet<ConnectionRecord> connections = new ArraySet<>(); // All ConnectionRecord for this client. 添加app: retrieveAppBindingLocked 根据intent找到对应的IntentBindRecord,再根据ProcessRecord在IntentBindRecord中找对应的AppBindRecord,存在则返回,不存在则创建 public AppBindRecord retrieveAppBindingLocked(Intent intent, ProcessRecord app) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord i = bindings.get(filter); if (i == null) { i = new IntentBindRecord(this, filter); bindings.put(filter, i); } AppBindRecord a = i.apps.get(app); if (a != null) { return a; } a = new AppBindRecord(this, i, app); i.apps.put(app, a); return a; } 移除app: removeConnectionLocked 先从AppBindRecord移除当前ConnectionRecord,若移除完后connections 集合为空,则从对应的IntentBindRecord中移除当前AppBindRecord void removeConnectionLocked(ConnectionRecord c, ProcessRecord skipApp, ActivityServiceConnectionsHolder skipAct) { IBinder binder = c.conn.asBinder(); AppBindRecord b = c.binding; ...... if (b.connections.size() == 0) { b.intent.apps.remove(b.client); } }

    3)IntentBindRecord 绑定到Service的特定Intent

    /** All apps that have bound to this Intent. */ final ArrayMap<ProcessRecord, AppBindRecord> apps = new ArrayMap<ProcessRecord, AppBindRecord>(); 添加binding: retrieveAppBindingLocked 根据intent找到对应的IntentBindRecord,若不存在则创建,并添加到ServiceRecord的bindings map中移除binding Service销毁时clear

    4)ServiceRecord 对应于App的Service

    final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings = new ArrayMap<Intent.FilterComparison, IntentBindRecord>(); // All active bindings to the service,代表bind 这个service的链接 private final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();

    二、相关flags

    1、BIND_TREAT_LIKE_ACTIVITY 将binding 视为持有一个activity,unbinding视为activity在后台。这意味着unbinding时,进程将会进入activity的LRU list而不是常规的LRU list,从而更有可能保持这个进程。这个通常用在输入法进程,以便更快捷的切换键盘。

    需要校验calling MANAGE_ACTIVITY_STACKS 权限

    if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { s.app.treatLikeActivity = true; } // This could have made the service more important. mAm.updateLruProcessLocked(s.app, (callerApp.hasActivitiesOrRecentTasks() && s.app.hasClientActivities()) || (callerApp.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP && (flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0), b.client);

    2、BIND_SCHEDULE_LIKE_TOP_APP 此标志仅用于系统调整IME(以及与top应用程序紧密配合的任何进程外用户可见组件)的调度策略。所以托管此类服务的UI能够拥有top app一样的调度策略

    仅限于系统调用,否则会抛出安全异常

    3、BIND_ALLOW_WHITELIST_MANAGEMENT 允许绑定Service应用程序管理白名单,例如临时绕过省电模式

    仅限于系统调用,否则会抛出安全异常

    if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) { s.whitelistManager = true; } // If this connection requested whitelist management, see if we should // now clear that state. if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) { s.updateWhitelistManager(); if (!s.whitelistManager && s.app != null) { updateWhitelistManagerLocked(s.app); } }

    4、BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS 允许绑定Service的进程启动后台Activity,需要校验android.Manifest.permission#START_ACTIVITIES_FROM_BACKGROUND

    5、BIND_EXTERNAL_SERVICE 这将 Service绑定到调用的应用package中,而非声明Service的package,即Service将在调用者进程package和userId下运行。

    1)Service的声明需要以下几点,以下三个属性皆必须为true

    <service android:name=".XXXService" android:exported="true" android:externalService="true" android:isolatedProcess="true" />

    2)绑定Service需要加入这个flag

    bindService(intent, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);

    涉及到的校验代码在retrieveServiceLocked中

    Processed: 0.023, SQL: 9