美文网首页
Bundler机制

Bundler机制

作者: Tony__Ren | 来源:发表于2019-04-11 16:45 被阅读0次

    Bundler在app中是以AIDL的方式表现的。
    AIDL实现类中,有2个重要的三要素,DESCRIPTOR(描述)、Stub(存根)、Proxy(代理)。
    Stub是服务端,Proxy是客户端。
    客户端在拿到服务端传过来的IBunder引用,会调用asInterface,这里会根据当前的描述是否相同,如果相同说明是同一个进程。
    原因在于在new的时候绑定了描述。

    //AIDL中
    public Stub()
    {
    this.attachInterface(this, DESCRIPTOR);
    }
    //bundler中
    public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
            mOwner = owner;
            mDescriptor = descriptor;
    }
    

    客户端通过Proxy拿到mRemote引用调用mRemote.transact()服务端的方法。
    服务端通过transact()回调AIDL在service的实现方法。

    怎么拿到引用呢?

    bindService(new Intent(xx,xxx), new ServiceConnection() {
     @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    //这里的service就是远程的引用
      IMyAidlInterface test = IMyAidlInterface.Stub.asInterface(service);
    }
    @Override
      public void onServiceDisconnected(ComponentName name) {
    }
    }, Context.BIND_AUTO_CREATE);
    

    主要是通过ActivityManagerService来拿到引用的。
    通过2次进程间通信。第一次是调用ASM的bindService第二次是
    在服务端AcitivityThread类中handlerService方法中调用ASM的publishService中回调ServiceConnection的方法拿到引用。

    private void handleBindService(BindServiceData data) {
            Service s = mServices.get(data.token);
            if (DEBUG_SERVICE)
                Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
            if (s != null) {
                try {
                    data.intent.setExtrasClassLoader(s.getClassLoader());
                    data.intent.prepareToEnterProcess();
                    try {
                        if (!data.rebind) {
                            IBinder binder = s.onBind(data.intent);
                            ActivityManagerNative.getDefault().publishService(
                                    data.token, data.intent, binder);
                        } else {
                            s.onRebind(data.intent);
                            ActivityManagerNative.getDefault().serviceDoneExecuting(
                                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                        }
                        ensureJitEnabled();
                    } catch (RemoteException ex) {
                    }
                } catch (Exception e) {
                    if (!mInstrumentation.onException(s, e)) {
                        throw new RuntimeException(
                                "Unable to bind to service " + s
                                + " with " + data.intent + ": " + e.toString(), e);
                    }
                }
            }
        }
    

    画图表示一下过程

    bindService流程图

    这是ASM调用ActiveServices管理类来实现服务的注册管理的。

    
        int bindServiceLocked(IApplicationThread caller, IBinder token,
                Intent service, String resolvedType,
                IServiceConnection connection, int flags, int userId) {
            if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
                    + " type=" + resolvedType + " conn=" + connection.asBinder()
                    + " flags=0x" + Integer.toHexString(flags));
            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
            if (callerApp == null) {
                throw new SecurityException(
                        "Unable to find app for caller " + caller
                        + " (pid=" + Binder.getCallingPid()
                        + ") when binding service " + service);
            }
    
            ActivityRecord activity = null;
            if (token != null) {
                activity = ActivityRecord.isInStackLocked(token);
                if (activity == null) {
                    Slog.w(TAG, "Binding with unknown activity: " + token);
                    return 0;
                }
            }
    
            int clientLabel = 0;
            PendingIntent clientIntent = null;
    
            if (callerApp.info.uid == Process.SYSTEM_UID) {
                // Hacky kind of thing -- allow system stuff to tell us
                // what they are, so we can report this elsewhere for
                // others to know why certain services are running.
                try {
                    clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
                } catch (RuntimeException e) {
                }
                if (clientIntent != null) {
                    clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
                    if (clientLabel != 0) {
                        // There are no useful extras in the intent, trash them.
                        // System code calling with this stuff just needs to know
                        // this will happen.
                        service = service.cloneFilter();
                    }
                }
            }
    
            if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
                        "BIND_TREAT_LIKE_ACTIVITY");
            }
    
            final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
    
            ServiceLookupResult res =
                retrieveServiceLocked(service, resolvedType,
                        Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
            if (res == null) {
                return 0;
            }
            if (res.record == null) {
                return -1;
            }
            ServiceRecord s = res.record;
    
            final long origId = Binder.clearCallingIdentity();
    
            try {
                if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
                    if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
                            + s);
                }
    
                if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                    s.lastActivity = SystemClock.uptimeMillis();
                    if (!s.hasAutoCreateConnections()) {
                        // This is the first binding, let the tracker know.
                        ProcessStats.ServiceState stracker = s.getTracker();
                        if (stracker != null) {
                            stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
                                    s.lastActivity);
                        }
                    }
                }
    
                mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
                        s.appInfo.uid, s.name, s.processName);
    
                AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
                ConnectionRecord c = new ConnectionRecord(b, activity,
                        connection, flags, clientLabel, clientIntent);
    
                IBinder binder = connection.asBinder();
                ArrayList<ConnectionRecord> clist = s.connections.get(binder);
                if (clist == null) {
                    clist = new ArrayList<ConnectionRecord>();
                    s.connections.put(binder, clist);
                }
                clist.add(c);
                b.connections.add(c);
                if (activity != null) {
                    if (activity.connections == null) {
                        activity.connections = new HashSet<ConnectionRecord>();
                    }
                    activity.connections.add(c);
                }
                b.client.connections.add(c);
                if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                    b.client.hasAboveClient = true;
                }
                if (s.app != null) {
                    updateServiceClientActivitiesLocked(s.app, c, true);
                }
                clist = mServiceConnections.get(binder);
                if (clist == null) {
                    clist = new ArrayList<ConnectionRecord>();
                    mServiceConnections.put(binder, clist);
                }
                clist.add(c);
    
                if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                    s.lastActivity = SystemClock.uptimeMillis();
                    if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                        return 0;
                    }
                }
    
                if (s.app != null) {
                    if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                        s.app.treatLikeActivity = true;
                    }
                    // This could have made the service more important.
                    mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
                            || s.app.treatLikeActivity, b.client);
                    mAm.updateOomAdjLocked(s.app);
                }
    
                if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
                        + ": received=" + b.intent.received
                        + " apps=" + b.intent.apps.size()
                        + " doRebind=" + b.intent.doRebind);
    
                if (s.app != null && b.intent.received) {
                    // Service is already running, so we can immediately
                    // publish the connection.
                    try {
                        c.conn.connected(s.name, b.intent.binder);
                    } catch (Exception e) {
                        Slog.w(TAG, "Failure sending service " + s.shortName
                                + " to connection " + c.conn.asBinder()
                                + " (in " + c.binding.client.processName + ")", e);
                    }
    
                    // If this is the first app connected back to this binding,
                    // and the service had previously asked to be told when
                    // rebound, then do so.
                    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);
                }
    
                getServiceMap(s.userId).ensureNotStartingBackground(s);
    
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
    
            return 1;
        }
    
    • 最后ActivityManagerNative getDefault留个下次分解
     static public IActivityManager getDefault() {
            return gDefault.get();
        }
    
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
            protected IActivityManager create() {
                IBinder b = ServiceManager.getService("activity");
                if (false) {
                    Log.v("ActivityManager", "default service binder = " + b);
                }
                IActivityManager am = asInterface(b);
                if (false) {
                    Log.v("ActivityManager", "default service = " + am);
                }
                return am;
            }
        };
    

    相关文章

      网友评论

          本文标题:Bundler机制

          本文链接:https://www.haomeiwen.com/subject/ybnziqtx.html