此次分析基于Android 5.0.1源码

onConfigureChanges被调用的流程框架图:



源码分析

1.Android系统启动的时候会通过读取/init.rc文件启动zygote进程

service zygote /system/bin/app_process -Xzygote /system/bin --zygote   socket zygote 666
2.zygote孵化出SystemServer进程,在frameworks\base\core\java\com\android\internal\os\ZygoteInit.java的main()中有如下代码段开启SystemServer进程

    public static void main(String argv[]) {      ......            // Disable tracing so that forked processes do not inherit stale tracing tags from            // Zygote.            Trace.setTracingEnabled(false);            if (startSystemServer) {                startSystemServer(abiList, socketName);            }            ......    }

调用到ZygoteInit.java的startSystemServer()方法

private static boolean startSystemServer(String abiList, String socketName)...... try {            parsedArgs = new ZygoteConnection.Arguments(args);            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);            /* Request to fork the system server process */            pid = Zygote.forkSystemServe(                    parsedArgs.uid, parsedArgs.gid,                    parsedArgs.gids,                    parsedArgs.debugFlags,                    null,                    parsedArgs.permittedCapabilities,                    parsedArgs.effectiveCapabilities);        } catch (IllegalArgumentException ex) {            throw new RuntimeException(ex);        }......}

startSystemServer函数调用到 Zygote.forkSystemServer孵化出SystemService进程,根据startSystemServer参数socketName可以得知Zygote是根据socket监听创建进程请求,当我们点击桌面上的一个应用图标打开一个应用就是通过发送一个socket消息给zygote的socket服务端,zygote受到请求、解析然后fork出一个进程

3.在frameworks\base\services\java\com\android\server\SystemServer.java的main方法会为ServiceManager添加一些服务

    public static void main(String[] args) {        new SystemServer().run();    }
    private void run() {        ......// Start services.        try {            startBootstrapServices();            startCoreServices();            startOtherServices();        } catch (Throwable ex) {            Slog.e("System", "******************************************");            Slog.e("System", "************ Failure starting system services", ex);            throw ex;        }  ......        Looper.loop();        throw new RuntimeException("Main thread loop unexpectedly exited");    }
private void startOtherServices() {......Slog.i(TAG, "Window Manager");wm = WindowManagerService.main(context, inputManager,                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,                    !mFirstBoot, mOnlyCore);ServiceManager.addService(Context.WINDOW_SERVICE, wm);ServiceManager.addService(Context.INPUT_SERVICE, inputManager);mActivityManagerService.setWindowManager(wm);inputManager.setWindowManagerCallbacks(wm.getInputMonitor());inputManager.start();......}
    public void start() {        Slog.i(TAG, "Starting input manager");        nativeStart(mPtr);        // Add ourself to the Watchdog monitors.        Watchdog.getInstance().addMonitor(this);        registerPointerSpeedSettingObserver();        registerShowTouchesSettingObserver();        mContext.registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                updatePointerSpeedFromSettings();                updateShowTouchesFromSettings();            }        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);        updatePointerSpeedFromSettings();        updateShowTouchesFromSettings();    }

创建了inputManager,inputManager类型为InputManagerService,并且调用了start()方法,接着调用一个jni方法nativeStart(mPtr),看一下mPtr的定义

  // Pointer to native input manager service object.    private final long mPtr;

注意注释// Pointer to native input manager service object,

指向了本地的input manager service对象,mPtr底层传上来的NativeInputManager对象的地址,底层通过调用这个对象的一些方法来回调java层的InputManagerSevice中的一些方法,比如notifyANR就调用到了InputManagerSevice的notifyANR。而mPtr是在InputManagerService的构造函数中通过调用nativeInit()获取的,也就是navtive中的input manager service和java层的input manager service是一起创建的,mPtr的初始化如下:

    public InputManagerService(Context context) {        this.mContext = context;        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());        mUseDevInputEventForAudioJack =                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="                + mUseDevInputEventForAudioJack);        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());        LocalServices.addService(InputManagerInternal.class, new LocalService());    }

nativeInit底层实现如下:

static jlong nativeInit(JNIEnv* env, jclass clazz,        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {    sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);    if (messageQueue == NULL) {        jniThrowRuntimeException(env, "MessageQueue is not initialized.");        return 0;    }    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,            messageQueue->getLooper());    im->incStrong(0);    return reinterpret_cast(im);}
这个函数创建了NativeInputManager对方,并且将地址返回给了mPtr,这个NativeInputManager就是回调java层的对象.

nativeStart()的实现在文件

frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp 中

static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) {    NativeInputManager* im = reinterpret_cast(ptr);    status_t result = im->getInputManager()->start();    if (result) {        jniThrowRuntimeException(env, "Input manager could not be started.");    }}

这个函数返回的im对象,

然后start方法实现如下:

status_t InputManager::start() {    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);    if (result) {        ALOGE("Could not start InputDispatcher thread due to error %d.", result);        return result;    }    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);    if (result) {        ALOGE("Could not start InputReader thread due to error %d.", result);        mDispatcherThread->requestExit();        return result;    }    return OK;}

所以跟了这么久最终启动的时候会启动InputDispatcherThread和InputReaderThread两个线程

InputDispatcherThread和InputReaderThread是在InputManager构造方法中创建的

InputManager::InputManager(        const sp& reader,        const sp& dispatcher) :        mReader(reader),        mDispatcher(dispatcher) {        initialize();}


void InputManager::initialize() {    mReaderThread = new InputReaderThread(mReader);    mDispatcherThread = new InputDispatcherThread(mDispatcher);}
mReaderThread是InputReaderThread线程,mDispatcherThread是InputDispatcherThread线程

mReaderThread持有一个InputReader对象

mDispatcherThread持有一个InputDispatcher对象

mReaderThread在轮询设备信息的时候,会回调到InputReader的loopOnce()方法,进而调用到InputDispatcher的方法

void InputReader::loopOnce() {......    // Flush queued events out to the listener.    // This must happen outside of the lock because the listener could potentially call    // back into the InputReader's methods, such as getScanCodeState, or become blocked    // on another thread similarly waiting to acquire the InputReader lock thereby    // resulting in a deadlock.  This situation is actually quite plausible because the    // listener is actually the input dispatcher, which calls into the window manager,    // which occasionally calls into the input reader.    mQueuedListener->flush();}
flush()的实现

void QueuedInputListener::flush() {    size_t count = mArgsQueue.size();    for (size_t i = 0; i < count; i++) {        NotifyArgs* args = mArgsQueue[i];        args->notify(mInnerListener);        delete args;    }    mArgsQueue.clear();}
呵呵,这个mInnerListener就是InputDispatcher对象,也就inputReader是接收到消息后就通知InputDispatcher
查看以下NotifyArgs的notify实现

void NotifyKeyArgs::notify(const sp& listener) const {    listener->notifyKey(this);}


void NotifySwitchArgs::notify(const sp& listener) const {    listener->notifySwitch(this);}


void NotifyMotionArgs::notify(const sp& listener) const {    listener->notifyMotion(this);}

void NotifyDeviceResetArgs::notify(const sp& listener) const {    listener->notifyDeviceReset(this);}


void NotifyConfigurationChangedArgs::notify(const sp& listener) const {    listener->notifyConfigurationChanged(this);}

呀,这么多实现呀,会调用哪个呀,其实在收到消息loopOnce被调用的时候,会根据消息类型构造不同的NotifyArgs对象入队,如果是配置发生改变就构造NotifyConfigurationChangedArgs对象入队,调用然后扫描这个队列挨个对象执行notify,有点像观察者模式的变形。

几经波折就是为了告诉你消息的走向为InputReaderThread->InputReader->InputDispatcher  不同的消息回掉InputDispatcher 的不同方法。下面介绍一下这两个线程

InputReaderThread:一个独立的循环线程,不断的轮询设备相关设备节点是否有新的事情发生

/* Reads raw events from the event hub and processes them, endlessly. */class InputReaderThread : public Thread {public:    InputReaderThread(const sp& reader);    virtual ~InputReaderThread();private:    sp mReader;    virtual bool threadLoop();};

注意它上面的注视/* Reads raw events from the event hub and processes them, endlessly. */  无止境的读取原始设备信息然后处理之


InputDispatcherThread:与InputReaderThread协同工作,以保证事件正确的派发和处理

/* Enqueues and dispatches input events, endlessly. */class InputDispatcherThread : public Thread {public:    explicit InputDispatcherThread(const sp& dispatcher);    ~InputDispatcherThread();private:    virtual bool threadLoop();    sp mDispatcher;};

注意它上面的注视 /* Enqueues and dispatches input events, endlessly. */无止境的分发输入消息


InputDispatcherThread能源源不断的获知系统设备中实时发生的时间,而且它还可以向InputReader注册监听多种事件
notifyConfigurationChanged()notifyInputChannelBroken()notifyANR()......

notifyConfigurationChanged()就是我们要分析的,我们已经分析到notifyConfigurationChanged()被调用的过程

void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {#if DEBUG_INBOUND_EVENT_DETAILS    ALOGD("notifyConfigurationChanged - eventTime=%lld", args->eventTime);#endif    bool needWake;    { // acquire lock        AutoMutex _l(mLock);        ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime);        needWake = enqueueInboundEventLocked(newEntry);    } // release lock    if (needWake) {        mLooper->wake();    }}
notifyConfigurationChanged中,构造一个消息实体入队了,当队列有消息入队时thredLoop就会执行,具体thredLoop怎么被调用的还不知道

bool InputDispatcherThread::threadLoop() {    mDispatcher->dispatchOnce();    return true;}


void InputDispatcher::dispatchOnce() {        ......        // Run a dispatch loop if there are no pending commands.        // The dispatch loop might enqueue commands to run afterwards.        if (!haveCommandsLocked()) {            dispatchOnceInnerLocked(&nextWakeupTime);        }        // Run all pending commands if there are any.        // If any commands were run then force the next poll to wake up immediately.        if (runCommandsLockedInterruptible()) {            nextWakeupTime = LONG_LONG_MIN;        }    } // release lock......}

进而调用到dispatchOnceInnerLocked()

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime){    ......    switch (mPendingEvent->type) {    case EventEntry::TYPE_CONFIGURATION_CHANGED: {        ConfigurationChangedEntry* typedEntry =                static_cast(mPendingEvent);        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);        dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped        break;    }    ......}
如果获取到的消息是TYPE_CONFIGURATION_CHANGED则调用dispatchConfigurationChangedLocked

bool InputDispatcher::dispatchConfigurationChangedLocked(        nsecs_t currentTime, ConfigurationChangedEntry* entry) {#if DEBUG_OUTBOUND_EVENT_DETAILS    ALOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);#endif    // Reset key repeating in case a keyboard device was added or removed or something.    resetKeyRepeatLocked();    // Enqueue a command to run outside the lock to tell the policy that the configuration changed.    CommandEntry* commandEntry = postCommandLocked(            & InputDispatcher::doNotifyConfigurationChangedInterruptible);    commandEntry->eventTime = entry->eventTime;    return true;}
void InputDispatcher::doNotifyConfigurationChangedInterruptible(        CommandEntry* commandEntry) {    mLock.unlock();    mPolicy->notifyConfigurationChanged(commandEntry->eventTime);    mLock.lock();}
mPolicy->notifyConfigurationChanged(commandEntry->eventTime)会回调到InputManagerService.java的notifyConfigurationChanged

    // Native callback.    private void notifyConfigurationChanged(long whenNanos) {        mWindowManagerCallbacks.notifyConfigurationChanged();    }
如上源码里面已经注释了这是native的回调

mWindowManagerCallbacks是什么,回到SystemService的main中有这么一句话

            wm = WindowManagerService.main(context, inputManager,                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,                    !mFirstBoot, mOnlyCore);            ServiceManager.addService(Context.WINDOW_SERVICE, wm);            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);            mActivityManagerService.setWindowManager(wm);            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());            inputManager.start();
mWindowManagerCallbacks是WindowManagerService中的一个InputMonitor成员,所以又进一步调用到了InputMonitor的notifyConfigurationChanged方法

    public void notifyConfigurationChanged() {        mService.sendNewConfiguration();        synchronized (mInputDevicesReadyMonitor) {            if (!mInputDevicesReady) {                mInputDevicesReady = true;                mInputDevicesReadyMonitor.notifyAll();            }        }    }

mService为WindowManagerService,sendNewConfiguration实现

    void sendNewConfiguration() {        try {            mActivityManager.updateConfiguration(null);        } catch (RemoteException e) {        }    }
mActivityManager为ActivityManagerService,并调用到它的updateConfiguration

    public void updateConfiguration(Configuration values) {        enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,                "updateConfiguration()");        synchronized(this) {            if (values == null && mWindowManager != null) {                // sentinel: fetch the current configuration from the window manager                values = mWindowManager.computeNewConfiguration();            }            if (mWindowManager != null) {                mProcessList.applyDisplaySize(mWindowManager);            }            final long origId = Binder.clearCallingIdentity();            if (values != null) {                Settings.System.clearConfiguration(values);            }            updateConfigurationLocked(values, null, false, false);            Binder.restoreCallingIdentity(origId);        }    }

   boolean updateConfigurationLocked(Configuration values,            ActivityRecord starting, boolean persistent, boolean initLocale)                for (int i=mLruProcesses.size()-1; i>=0; i--) {                    ProcessRecord app = mLruProcesses.get(i);                    try {                        if (app.thread != null) {                            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "                                    + app.processName + " new config " + mConfiguration);                            app.thread.scheduleConfigurationChanged(configCopy);                        }                    } catch (Exception e) {                    }                }}
app.thread.scheduleConfigurationChanged(configCopy);这是一个binder远程调用,会调用到ActivityThread的scheduleConfigurationChanged,这就总算调用到我们的应用程序了

大家跟着标红的函数放下走

        public void scheduleConfigurationChanged(Configuration config) {            updatePendingConfiguration(config);            sendMessage(H.CONFIGURATION_CHANGED, config);        }
发了一个CONFIGURATION_CHANGED,处理过程在handle中

                case CONFIGURATION_CHANGED:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");                    mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;                    handleConfigurationChanged((Configuration)msg.obj, null);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;

    final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {......        ArrayList callbacks = collectComponentCallbacks(false, config);        if (callbacks != null) {            final int N = callbacks.size();            for (int i=0; i

对每个callback执行performConfigurationChanged方法

ArrayList callbacks = collectComponentCallbacks(false, config);

callbacks 是本进程所有的application、activity、service、contentprovider的集合,看它的实现就知道了

    ArrayList collectComponentCallbacks(            boolean allActivities, Configuration newConfig) {        ArrayList callbacks                = new ArrayList();        synchronized (mResourcesManager) {            final int NAPP = mAllApplications.size();            for (int i=0; i                    if (!ar.activity.mFinished && (allActivities || !ar.paused)) {                                           callbacks.add(a);                    } else if (thisConfig != null) {         .                        if (DEBUG_CONFIGURATION) {                            Slog.v(TAG, "Setting activity "                                    + ar.activityInfo.name + " newConfig=" + thisConfig);                        }                        ar.newConfig = thisConfig;                    }                }            }            final int NSVC = mServices.size();            for (int i=0; i

因为application、activity、service、contentprovider都实现了ComponentCallbacks2接口。

根据条件可知

          if (!ar.activity.mFinished && (allActivities || !ar.paused)) {                        callbacks.add(a);                    } 
只有没有finish()掉的和没有paused掉的Acitivity才会被加到callbacks当中。

    private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) {      ......        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb                + ": shouldChangeConfig=" + shouldChangeConfig);        if (shouldChangeConfig) {            cb.onConfigurationChanged(config);            if (activity != null) {                if (!activity.mCalled) {                    throw new SuperNotCalledException(                            "Activity " + activity.getLocalClassName() +                        " did not call through to super.onConfigurationChanged()");                }                activity.mConfigChangeFlags = 0;                activity.mCurrentConfig = new Configuration(config);            }        }    }

cb是从callbacks集合中取出来的,cb.onConfigurationChanged(config);总算看到onConfigurationChanged方法被调用到了,这个cb就是activity、application、service、contentProvider中的一个。当然在callbacks里面的activity不一定都会毁掉onConfigurationChanged,还要根据一些activity的配置项去决定是否回调onConfigurationChanged


这就是整个onConfigureChange回凋流程。


其实不仅仅是onConfigureChange遵循这个流程,像按键消息、触摸消息也是这么一个流程












更多相关文章

  1. Android(安卓)文件绝对路径和Content开头的Uri互相转换
  2. Android(安卓)-- Activity值传递
  3. [Android] 在程序中实现延时的常用的两种方式
  4. Android(安卓)AccessibilityDelegate的使用
  5. Android开发常见的问题
  6. Android与js的交互方式
  7. JNI 防混淆 Android(安卓)proguard
  8. Android(安卓)开发工具(以后持续更新)
  9. Android如何获取屏幕的分辨

随机推荐

  1. Android中Message机制的灵活应用(二)
  2. Android如何通过scheme跳转界面
  3. fanfou(饭否) android客户端 代码学习2
  4. Android(安卓)File.listFiles()返回null
  5. http上传文件到网络核心代码
  6. android全格式多媒体播放器(三:基于ffmpeg
  7. ViewPager和ViewFlipperV冲突
  8. Android(安卓)APP 应用分析
  9. android 中的一些小case
  10. Android变形(Transform)之Camera使用介绍