Android R IMS初始化流程

前言

在看这篇文章之前我们可以带着以下几个问题来看:

  1. input的分发流程是怎样的?
  2. input事件是通过什么方式把事件传递到应用进程?
  3. ims里面是怎么去找到当前的焦点app以及window?
  4. ims里面ANR超时5s是在哪里定义的?
  5. ims里面ANR的发生是怎么去处理的?

  6. WindowInputEventReceiver中的onInputEvent方法,是运行在主线程还是子线程?

可以先看初始化流程,了解IMS的由来,如果对IMS有一定了解,上述问题可以直接看专栏里面的后续文章。

IMS启动流程:

Android R IMS启动流程-CSDN博客

input事件分发流程:

Android R input事件分发流程-CSDN博客

IMS问题复盘:

Android R IMS问题复盘-CSDN博客

1. IMS初始化流程

        IMS属于系统重要服务,同样运行在SystemServer进程里面,在系统启动过程中,也会去初始化这些系统服务。

1.1 SystemServer.startOtherServices

/frameworks/base/services/java/com/android/server/SystemServer.java

        ims的初始化入口在SystemServer中的startOtherServices方法里面

/**
       * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
       */
      private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
         t.traceBegin("startOtherServices");
            .....

          InputManagerService inputManager = null;

            .....

           t.traceBegin("StartInputManagerService");
           inputManager = new InputManagerService(context);
           t.traceEnd();

            .....

            t.traceBegin("StartInputManager");
            inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
            inputManager.start();
            t.traceEnd();
            
            .......
}

        这里会将ims的实例传递给wms,后面WMS与IMS的交互都是通过此实例,在inputManager.start之前,会将wm中的InputManagerCallback注册到IMS中。

1.2 IMS构造函数

/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public InputManagerService(Context context) {
          this.mContext = context;
          this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
  
          mStaticAssociations = loadStaticInputPortAssociations();
          mUseDevInputEventForAudioJack =
                              
          context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
          Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                  + mUseDevInputEventForAudioJack);
          mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
  
          String doubleTouchGestureEnablePath = context.getResources().getString(
                  R.string.config_doubleTouchGestureEnableFile);
          mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
              new File(doubleTouchGestureEnablePath);
  
          LocalServices.addService(InputManagerInternal.class, new LocalService());      }

        IMS的构造函数主要做了如下几件事:

  • 初始化InputManagerHandler(InputManagerHandler处理input相关的UI变化信息,例如keyboard与native状态发生变化时进行callback通知到wms)。
  • 调用nativeInit函数返回mPtr,是IMS和native交互的关键,这个是NativeInputManager的指针。
  • 将IMS加入到LocalServices里面。

1.3 com_android_server_input_InputManagerService.nativeInit

/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

  static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
          jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
      sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
      if (messageQueue == nullptr) {
          jniThrowRuntimeException(env, "MessageQueue is not initialized.");
          return 0;
      }  
      NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
              messageQueue->getLooper());
      im->incStrong(0);
      return reinterpret_cast<jlong>(im);
}
  

初始化NativeInputManager。

1.4 com_android_server_input_InputManagerService.NativeInputManager

 /frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

  NativeInputManager::NativeInputManager(jobject contextObj,
          jobject serviceObj, const sp<Looper>& looper) :
          mLooper(looper), mInteractive(true) {
      JNIEnv* env = jniEnv();
  
      mServiceObj = env->NewGlobalRef(serviceObj);
  
      {
          AutoMutex _l(mLock);
          mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
          mLocked.pointerSpeed = 0;
          mLocked.pointerGesturesEnabled = true;
          mLocked.showTouches = false;
          mLocked.pointerCapture = false;
          mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
      }
      mInteractive = true;
  
      mInputManager = new InputManager(this, this);
      defaultServiceManager()->addService(String16("inputflinger"),
              mInputManager, false);
  }

        初始化InputManager。

        NativeInputManager是java和native的桥梁,从类的声明来看NativeInputManager包含了InputReader和InputDispatcher的回调interface.后面从dispatcher和reader抛出来的notify都是在这里转换后抛给java。

        defaultServiceManager()->addService作用往ServiceManager中添加了一个inputflinger服务,用来管理IMS的inputChannel的register和unregister。

1.5 InputManager构造函数

/frameworks/native/services/inputflinger/InputManager.cpp

  InputManager::InputManager(
          const sp<InputReaderPolicyInterface>& readerPolicy,
          const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
      mDispatcher = createInputDispatcher(dispatcherPolicy);
      mClassifier = new InputClassifier(mDispatcher);
      mReader = createInputReader(readerPolicy, mClassifier);
  }

        创建InputDispatcher。

        初始化InputClassifier,这里InputClassifier的作用是InputReader与InputDispatcher通信是通过媒介InputClassifier实例进行,构造InputClassifier时将InputDispatcher作为参数传入。

        创建InputReader。

1.6 InputDispatcher构造函数

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

  InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
        : mPolicy(policy),
          mPendingEvent(nullptr),
          mLastDropReason(DropReason::NOT_DROPPED),
          mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
          mAppSwitchSawKeyDown(false),
          mAppSwitchDueTime(LONG_LONG_MAX),
          mNextUnblockedEvent(nullptr),
          mDispatchEnabled(false),
          mDispatchFrozen(false),
          mInputFilterEnabled(false),
          // mInTouchMode will be initialized by the WindowManager to the default device config.
          // To avoid leaking stack in case that call never comes, and for tests,
          // initialize it here anyways.
          mInTouchMode(true),
          mFocusedDisplayId(ADISPLAY_ID_DEFAULT) {
      mLooper = new Looper(false);
     mReporter = createInputReporter();
  
      mKeyRepeatState.lastKeyEntry = nullptr;
  
      policy->getDispatcherConfiguration(&mConfig);
  }

        创建属于InputDispatcher的looper,从这里可以大致看出InputDispatcher的实现模型就是looper的机制,只不过Input并没有使用Looper相关的Message相关的功能,也就是说没有MessageQueue了,仅是单纯的使用Looper的addFd功能,以及它的epoll阻塞唤醒功能。

1.7 InputReader构造函数

/frameworks/native/services/inputflinger/reader/InputReader.cpp

  InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
                           const sp<InputReaderPolicyInterface>& policy,
                           const sp<InputListenerInterface>& listener)
        : mContext(this),
         mEventHub(eventHub),
          mPolicy(policy),
          mGlobalMetaState(0),
          mGeneration(1),
          mNextInputDeviceId(END_RESERVED_ID),
          mDisableVirtualKeysTimeout(LLONG_MIN),
          mNextTimeout(LLONG_MAX),
          mConfigurationChangesToRefresh(0) {
      mQueuedListener = new QueuedInputListener(listener);
  
      { // acquire lock
          AutoMutex _l(mLock);
  
          refreshConfigurationLocked(0);
          updateGlobalMetaStateLocked();
      } // release lock
  }

        这里主要是将主要是将EventHub保存成私有成员,保存NativeInputManager注册在InputReader中的callback中,通过与InputDispatcher的媒介InputClassifier创建QueuedInputListener,这个主要目的是notify,不过是把多个notify暂时存放成队列,最后通过函数flush()在分别通知出去,所以类名中有个queue。

1.8 EventHub构造函数

/frameworks/native/services/inputflinger/reader/EventHub.cpp

  EventHub::EventHub(void)
        : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
          mNextDeviceId(1),
          mControllerNumbers(),
          mOpeningDevices(nullptr),
          mClosingDevices(nullptr),
          mNeedToSendFinishedDeviceScan(false),
          mNeedToReopenDevices(false),
          mNeedToScanDevices(true),
          mPendingEventCount(0),
          mPendingEventIndex(0),
          mPendingINotify(false) {
      ensureProcessCanBlockSuspend();
      
        //创建epoll对象
      mEpollFd = epoll_create1(EPOLL_CLOEXEC);
      LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
  
        //创建inotify对象
      mINotifyFd = inotify_init();
      mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
      LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s", DEVICE_PATH,
                          strerror(errno));
      if (isV4lScanningEnabled()) {
          mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
          LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
                              VIDEO_DEVICE_PATH, strerror(errno));
      } else {
          mVideoWd = -1;
          ALOGI("Video device scanning disabled");
      }
  

        //将mINotifyFd作为mEpollFd的一个监控对象    
      struct epoll_event eventItem = {};
      eventItem.events = EPOLLIN | EPOLLWAKEUP;
      eventItem.data.fd = mINotifyFd;
      int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
      LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);
  

        //创建唤醒pipe,EventHub唤醒时(wake()),往writepipe写值,readpipe受mEpollFd监控 
      int wakeFds[2];
      result = pipe(wakeFds);
      LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
  
      mWakeReadPipeFd = wakeFds[0];
      mWakeWritePipeFd = wakeFds[1];
  
      result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
      LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
                          errno);
  
      result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
      LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
                          errno);
  
      eventItem.data.fd = mWakeReadPipeFd;
      result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
      LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
                          errno);
  }

        主要作用就是通过inotify监听 /dev/input里的文件的变化,另外创建了一个管道, 将read fd加入到epoll中去监听,而write fd主要用来唤醒epoll。

1.9 IMS初始化流程总结

  • 创建NativeInputManager实例,作为后面native和java之间的传送点。
  • 创建InputDispatcher实例,并将NativeInputManager作为callback传入InputDispatcher中。
  • 创建InputReader实例,并将NativeInputManager作为callback传入InputReader中。
  • 创建InputClassifier实例,将其作为InputReader与InputDispatcher通信的媒介。
  • 创建EventHub实例,并保存在InputReader中,后期input的event获取都通过EventHub获取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android IMS(IP Multimedia Subsystem)通话流程涉及多个组件和协议之间的交互。下面是一个简要的Android IMS通话流程: 1. 注册:设备启动时,IMS客户端将向IMS网络注册。这包括与P-CSCF(Proxy Call Session Control Function)进行SIP注册,然后与S-CSCF(Serving Call Session Control Function)进行认证和注册。 2. 呼叫建立:当用户拨打电话时,IMS客户端将向S-CSCF发起呼叫请求。S-CSCF将执行鉴权和授权,并将呼叫请求转发给相应的应用服务器(AS)。 3. 呼叫路由:AS根据呼叫请求中的信息,确定呼叫目标的位置,并将呼叫路由到目标用户所在的S-CSCF。 4. 呼叫传输:S-CSCF将呼叫请求转发给目标用户所在的P-CSCF。P-CSCF将负责与目标用户设备建立会话并传输呼叫请求。 5. 呼叫控制:目标用户设备接收到呼叫请求后,IMS客户端将对呼叫进行控制,包括呼叫接听、挂断等操作。 6. 媒体传输:一旦呼叫建立成功,媒体流将通过IMS网络进行传输。这可能涉及到RTP(Real-time Transport Protocol)和RTCP(Real-time Transport Control Protocol)。 7. 呼叫结束:当通话结束时,IMS客户端将向S-CSCF发送呼叫释放请求,S-CSCF将释放与呼叫相关的资源,并通知AS。 这只是Android IMS通话流程的简要描述,实际流程可能会因网络配置和运营商要求而有所不同。IMS通话流程涉及的协议包括SIP(Session Initiation Protocol)、SDP(Session Description Protocol)、RTP等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值