bind Service 基础

一、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中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值