【Framework】bindService启动流程

这篇具有很好参考价值的文章主要介绍了【Framework】bindService启动流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在【Service启动流程之startService】 中,我们已经分析了startService的流程,这篇就继续讲bindService的流程,他们两有很多相似之处。同样,流程图在总结处。

我们在调用bindService方法时候,实际调用的是ContextImpl的实现。

1. ContextImpl

代码路径:frameworks\base\core\java\android\app\ContextImpl.java

1.1 bindService

@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
            getUser());
}

1.2 bindServiceCommon

private boolean bindServiceCommon(Intent service, ServiceConnection conn, 
                                  int flags, String instanceName, Handler handler, 
                                  Executor executor, UserHandle user) {
    IServiceConnection sd;
    if (mPackageInfo != null) {
        // 将ServiceConnection 通过LoadedApk包装到 ServiceDispatcher 中
        if (executor != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
        } else {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        }
    }
    try {
        IBinder token = getActivityToken();
        if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                && mPackageInfo.getApplicationInfo().targetSdkVersion
                < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            flags |= BIND_WAIVE_PRIORITY;
        }
        service.prepareToLeaveProcess(this);
        // 调用 AMS 接口
        int res = ActivityManager.getService().bindServiceInstance(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
        return res != 0;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

2. LoaderApk

代码路径:frameworks\base\core\java\android\app\LoadedApk.java

getServiceDispatcher 直接调用getServiceDispatcherCommon 方法

2.1 getServiceDispatcherCommon

private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
            Context context, Handler handler, Executor executor, int flags) {
        synchronized (mServices) {
            LoadedApk.ServiceDispatcher sd = null;
            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
            if (map != null) {
                sd = map.get(c);
            }
            if (sd == null) {
                if (executor != null) {
                    // 将ServiceConnection 保存到ServiceDispatcher中
                    sd = new ServiceDispatcher(c, context, executor, flags);
                } else {
                    sd = new ServiceDispatcher(c, context, handler, flags);
                }
                if (map == null) {
                    map = new ArrayMap<>();
                    mServices.put(context, map);
                }
                map.put(c, sd);
            } else {
                sd.validate(context, handler, executor);
            }
            // 最后返回的是一个bind对象,即IServiceConnection
            return sd.getIServiceConnection();
        }
    }

3. ActivityManagerService

代码路径:frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

3.1 bindServiceInstance

    private int bindServiceInstance(IApplicationThread caller, IBinder token, 
                                    Intent service, String resolvedType,
                                    ServiceConnection connection ...) {
		....
        try {
            synchronized (this) {
                // 调用ActiveServices的bindServiceLocked
                return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,        sdkSandboxClientAppPackage, callingPackage, userId);
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

4. ActiveService

代码路径:frameworks\base\services\core\java\com\android\server\am\ActiveServices.java

4.1 bindServiceLocked

其中:

  • ServiceRecord:用于描述一个Service
  • processRecord:一个进程的信息
  • ConnectionRecord:用于描述应用程序进程和Service建立的通信
  • AppBindRecord:维护Service与应用进程的关联,包含通信记录ArraySet,绑定Service的intent。
  • IntentBindRecord:描述绑定Service的intent。
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, final IServiceConnection connection ...)
        throws TransactionTooLargeException {
    final ProcessRecord callerApp = mAm.getRecordForAppLOSP(caller);
    ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
    int clientLabel = 0;
    PendingIntent clientIntent = null;
    // 获取 ServiceRecord
    ServiceLookupResult res = retrieveServiceLocked(service, instanceName,
            isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
            resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg,
            isBindExternal, allowInstant);
    ServiceRecord s = res.record;
    try {
        AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
        // 用于保存 serviceConnect 信息
        ConnectionRecord c = new ConnectionRecord(b, activity,
                connection, flags, clientLabel, clientIntent,
                callerApp.uid, callerApp.processName, callingPackage, res.aliasComponent);
        IBinder binder = connection.asBinder();
        // 将connection binder对象添加到map中
        s.addConnection(binder, c);
        b.connections.add(c);
        boolean needOomAdj = false;
        // 传入flag是BIND_AUTO_CREATE
        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
            // Service还没启动,就走启动流程
            // bringUpServiceLocked 方法返回null意味着成功启动Service
            if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                    permissionsReviewRequired, packageFrozen, true) != null) {
                // 启动失败,添加排队
                mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
                return 0;
            }
        }
        // b.intent.received 表示已接收到绑定Service时返回的binder对象。
        if (s.app != null && b.intent.received) {
            // 服务已经在运行,可以直接调用connected
            //如果客户端尝试启动/连接的是别名,那么需要将别名组件名称传递给客户端。
            final ComponentName clientSideComponentName =
                    res.aliasComponent != null ? res.aliasComponent : s.name;
            try {
                // 这里的c.conn 即 IServiceConnection对象
                c.conn.connected(clientSideComponentName, b.intent.binder, false);
            } catch (Exception e) {
            }

            // 如果这是连接回此绑定的第一个应用, 并且Service已经调用过onUnBind方法
            // 则需要调用requestServiceBindingLocked。
            if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                requestServiceBindingLocked(s, b.intent, callerFg, true);
            }
        } else if (!b.intent.requested) {
            requestServiceBindingLocked(s, b.intent, callerFg, false);
        }

    } finally {
        Binder.restoreCallingIdentity(origId);
    }
    return 1;
}

4.2 realStartServiceLocked

如startService流程中的分析,bringUpServiceLocked 调用 realStartServiceLocked来启动Service

private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
        IApplicationThread thread ...) throws RemoteException {
    // 通知客户端创建service
    thread.scheduleCreateService(r, r.serviceInfo,
            mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
            app.mState.getReportedProcState());
    // 调用Service的onBind方法
    requestServiceBindingsLocked(r, execInFg);
    .....
}

4.3 requestServiceBindingsLocked

    private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
        for (int i=r.bindings.size()-1; i>=0; i--) {
            IntentBindRecord ibr = r.bindings.valueAt(i);
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
                break;
            }
        }
    }

4.4 requestServiceBindingLocked

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
	   // i.requested:表示是否发送过绑定Service的请求,这里为true
       // i.apps.size():表示当前intent绑定Service的应用进程个数
	   if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                // 启动计时
                bumpServiceExecutingLocked(r, execInFg, "bind",
                        OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
                // 通知客户端调用bind
                r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.mState.getReportedProcState());
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } catch (TransactionTooLargeException e) {
                ....
            }
      }
      return true;
}

5. ApplicationThread

代码路径:frameworks\base\core\java\android\app\ActivityThread.java

5.1 scheduleBindService

public final void scheduleBindService(IBinder token, Intent intent,
        boolean rebind, int processState) {
    updateProcessState(processState, false);
    BindServiceData s = new BindServiceData();
    s.token = token;
    s.intent = intent;
    s.rebind = rebind;
    sendMessage(H.BIND_SERVICE, s);
}

6. ActivityThread

代码路径:frameworks\base\core\java\android\app\ActivityThread.java

在发送BIND_SERVICE 消息后,最后调用到ActivityThread#handleBindService 方法

6.1 handleBindService

    private void handleBindService(BindServiceData data) {
        CreateServiceData createData = mServicesData.get(data.token);
        Service s = mServices.get(data.token);
        try {
           if (!data.rebind) {
               // 不是重新bind,即没有绑定过,调用onBind方法
               IBinder binder = s.onBind(data.intent);
               // 将binder对象传给AMS
               ActivityManager.getService().publishService(
                       data.token, data.intent, binder);
           } else {
               // 调用onRebind方法
               s.onRebind(data.intent);
               ActivityManager.getService().serviceDoneExecuting(
                       data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
           }
       } catch (RemoteException ex) {
           throw ex.rethrowFromSystemServer();
       }
    }

7. ActivityManagerService

代码路径:frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

7.1 publishService

public void publishService(IBinder token, Intent intent, IBinder service) {
    ....
    synchronized(this) {
        mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    }
}

8. ActiveServices

代码路径:frameworks\base\services\core\java\com\android\server\am\ActiveServices.java

8.1 publishServiceLocked

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
            if (r != null) {
                Intent.FilterComparison filter
                        = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null && !b.received) {
                    b.binder = service; // 保存Service#onBind方法返回的binder对象
                    b.requested = true;
                    b.received = true;
                    ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
                    for (int conni = connections.size() - 1; conni >= 0; conni--) {
                        ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
                        for (int i=0; i<clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                            if (!filter.equals(c.binding.intent.intent)) {
                                continue;
                            }
                            try {
                                // 调用ServiceConnection的回调
                                c.conn.connected(clientSideComponentName, service, false);
                            } catch (Exception e) {
                            }
                        }
                    }
                }
                // 移除定时任务等
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false, false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

8.2 ConnectionRecord

代码路径:frameworks\base\services\core\java\com\android\server\am\ConnectionRecord.java

该类定义如下

final class ConnectionRecord {
    final IServiceConnection conn;  // The client connection.
    .....
}

这里的IServiceConnection 即我们在bindService的时候,生成的ServiceDispatcher中内部mIServiceConnection 变量

9. LoadedApk

代码路径:frameworks\base\core\java\android\app\LoadedApk.java

9.1 InnerConnection

private static class InnerConnection extends IServiceConnection.Stub {
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

    InnerConnection(LoadedApk.ServiceDispatcher sd) {
        mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
    }

    public void connected(ComponentName name, IBinder service, boolean dead)
            throws RemoteException {
        LoadedApk.ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
            sd.connected(name, service, dead);
        }
    }
}

9.2 ServiceDispatcher

connect方法中会做切线程的动作,RunConnection 内部实际是调用到doConnected 方法。

static final class ServiceDispatcher {
  public void connected(ComponentName name, IBinder service, boolean dead) {
      if (mActivityExecutor != null) {
          mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
      } else if (mActivityThread != null) {
          mActivityThread.post(new RunConnection(name, service, 0, dead));
      } else {
          doConnected(name, service, dead);
      }
  }
}

9.3 doConnected

public void doConnected(ComponentName name, IBinder service, boolean dead) {
    ServiceDispatcher.ConnectionInfo old;
    ServiceDispatcher.ConnectionInfo info;
    synchronized (this) {
        old = mActiveConnections.get(name)
        if (service != null) {
            info = new ConnectionInfo();
            info.binder = service;
            info.deathMonitor = new DeathMonitor(name, service);
            try {
                // 监听bind的死亡回调
                service.linkToDeath(info.deathMonitor, 0);
                mActiveConnections.put(name, info);
            } catch (RemoteException e) {
                mActiveConnections.remove(name);
                return;
            }
        } else {
            // The named service is being disconnected... clean up.
            mActiveConnections.remove(name);
        }
        if (old != null) {
            old.binder.unlinkToDeath(old.deathMonitor, 0);
        }
    }
    // 如果有老的服务,那就通知断开
    if (old != null) {
        mConnection.onServiceDisconnected(name);
    }
    if (dead) {
        // 如果service端已经dead,就调用onBindingDied
        mConnection.onBindingDied(name);
    } else {
        // 通知service已经连接上,并且远程服务返回的bind对象不为null
        if (service != null) {
            mConnection.onServiceConnected(name, service);
        } else {
            // 远程服务返回null的bind对象,
            mConnection.onNullBinding(name);
        }
    }
}

总结

如果当前应用是第一个与Service绑定,并且Service已经调用过unUnBind方法,则会调用Service的onRebind方法

对应的uml图如下
【Framework】bindService启动流程文章来源地址https://www.toymoban.com/news/detail-514099.html

到了这里,关于【Framework】bindService启动流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Android Framework系列】5章 AMS启动流程

    AMS(Activity Manager Service) 是 Android 中最核心的服务,管理着 四大组件的启动 、 切换 、 调度 及 应用进程的管理和调度 等工作。AndroidQ将Activity移到了 ActivityTaskManagerService 中,但也和AMS相关联。 AMS 通过使用一些系统资源和数据结构(如进程、任务栈、记录四大组件生命周期

    2024年02月15日
    浏览(54)
  • 【Android Framework (八) 】- Service

    1,挂载文件系统,创建文件目录 调用selinux_setup权限安全相关 2,初始化内存空间 初始化属性服务 创建Epoll 注册监听子进程重启异常操作等,对子进程进行线程守护 3,startPropertyServic 开启属性服务 进行监听 4,LoadBootScripts 加载init.rc文件 进行解析 调用do_class_start 文件开启

    2024年02月01日
    浏览(38)
  • 微服务平台(Tencent Service Framework,TSF)

    微服务平台 TSF - 文档中心 - 腾讯云 (tencent.com) TSF 服务治理平台对比基于开源 SpringCloud 自建平台,具有以下优势: 对比项 腾讯微服务平台 TSF Paas 平台 基于开源 SpringCloud 自建平台 服务注册中心 平台提供高可用的注册中心集群,金融级别容灾。 自行搭建,维护困难,可靠性

    2023年04月08日
    浏览(33)
  • SQL Server安装提示【需要microsoft.NET Framework 3.5 Service Pack 1】

            我在自己电脑安装SQL Server 2014 的时候遇到了这个问题,SQL Server安装提示【需要microsoft.NET Framework 3.5 Service Pack 1】: 1、打开控制面板: 2、选择“程序”:   3、点击“启动或关闭Windows功能”,把NET Framework 3.5(包括.NET 2.0和3.0)选择上,点击“确定”:   4、加载功

    2024年02月11日
    浏览(49)
  • Ubuntu下的自启动(Service启动)

    在Ubuntu中设置Python3命令开机自启需要创建一个systemd service文件,步骤如下: 使用任一文本编辑器,打开一个终端窗口。 在终端中输入以下命令,创建一个.service文件: 在打开的文件中输入以下代码: 其中,my_script.service是服务名称,我的Python脚本在 /path/to/my/script.py,可以根

    2024年02月09日
    浏览(43)
  • 云服务器安装SQL Server2014(解决SQL安装规则需要 Microsoft .NET Framework 3.5 Service Pack 1失败问题)

    昨天的文件里已经上传了SQL Server2014的安装镜像,今天开始安装 第一步:右键装载安装镜像 第二部:默认下一步,勾选我接受许可条款 第三步:继续默认下一步 第四步:到功能选择,将 全选 勾上 要保证你的云盘内存足够,否则无法安装 第五步:出现一个规则未通过,点击

    2024年02月07日
    浏览(53)
  • FrameWork的概述与启动过程

    Framework定义了客户端组件和服务端组件功能及接口。以下阐述中,“应用程序”一般是指“.apk”程序。 框架中包含三个主要部分,分别为服务端、客户端和Linux驱动。 服务端主要包含两个重要类,分别是WindowManagerService(WmS)和ActivityManagerService (AmS)。 WmS的作用是为所有的应

    2024年02月10日
    浏览(46)
  • 微软官网下载Net Framework流程

    1、官网下载链接 https://dotnet.microsoft.com/en-us/download/dotnet-framework/net451 2、选择合适的版本 3、点击下载

    2024年02月16日
    浏览(48)
  • Android Framework学习之Activity启动原理

    Android 13.0 Activity启动原理逻辑流程图如下:

    2024年02月05日
    浏览(55)
  • Android9.0 系统Framework发送通知流程分析

      在android 9.0的系统rom定制化开发中,在systemui中一个重要的内容就是系统通知的展示,在状态栏展示系统发送通知的图标,而在 系统下拉通知栏中展示接收到的系统发送过来的通知,所以说对系统framework中发送通知的流程分析很重要,接下来就来分析下系统 通知从framework到

    2024年02月02日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包