Android onConfigureChanges 是如何被调用的

此次分析基于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> 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<jlong>(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<NativeInputManager*>(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<InputReaderInterface>& reader,
        const sp<InputDispatcherInterface>& 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<InputListenerInterface>& listener) const {
    listener->notifyKey(this);
}


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


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

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


void NotifyConfigurationChangedArgs::notify(const sp<InputListenerInterface>& 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<InputReaderInterface>& reader);
    virtual ~InputReaderThread();

private:
    sp<InputReaderInterface> 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<InputDispatcherInterface>& dispatcher);
    ~InputDispatcherThread();

private:
    virtual bool threadLoop();

    sp<InputDispatcherInterface> 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<ConfigurationChangedEntry*>(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::<span style="color:#ff0000;">doNotifyConfigurationChangedInterruptible</span>);
    commandEntry->eventTime = entry->eventTime;
    return true;
}
void InputDispatcher::doNotifyConfigurationChangedInterruptible(
        CommandEntry* commandEntry) {
    mLock.unlock();

    mPolicy-><span style="color:#ff0000;">notifyConfigurationChanged</span>(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<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);</span>
        if (callbacks != null) {
            final int N = callbacks.size();
            for (int i=0; i<N; i++) {
                performConfigurationChanged(callbacks.get(i), config);
            }
        }
    }

对每个callback执行performConfigurationChanged方法

ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);

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

    ArrayList<ComponentCallbacks2> collectComponentCallbacks(
            boolean allActivities, Configuration newConfig) {
        ArrayList<ComponentCallbacks2> callbacks
                = new ArrayList<ComponentCallbacks2>();

        synchronized (mResourcesManager) {
            final int NAPP = mAllApplications.size();
            for (int i=0; i<NAPP; i++) {
                callbacks.add(mAllApplications.get(i));
            }
            final int NACT = mActivities.size();
            for (int i=0; i<NACT; i++) {
                ActivityClientRecord ar = mActivities.valueAt(i);
                Activity a = ar.activity;
                if (a != null) {
                    Configuration thisConfig = applyConfigCompatMainThread(
                            mCurDefaultDisplayDpi, newConfig,
                            ar.packageInfo.getCompatibilityInfo());
<span style="color:#ff0000;">                    if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
                   
                        callbacks.add(a);
                    } </span>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<NSVC; i++) {
                callbacks.add(mServices.valueAt(i));
            }
        }
        synchronized (mProviderMap) {
            final int NPRV = mLocalProviders.size();
            for (int i=0; i<NPRV; i++) {
                callbacks.add(mLocalProviders.valueAt(i).mLocalProvider);
            }
        }

        return callbacks;
    }

因为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遵循这个流程,像按键消息、触摸消息也是这么一个流程












  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android开发中,有时我们需要限制某个方法的频繁调用,以免耗费过多的系统资源或造成其他问题。以下是一些可以用来防止方法被频繁调用的方法: 1. 使用计时器:可以使用Timer类或Handler类来设置一个计时器,在方法被调用后的一段时间内,暂时禁用该方法。通过设置一个延迟时间和间隔时间,我们可以控制方法的调用频率。 2. 状态标志位:可以设置一个标志位,用来记录方法的调用状态。每次方法被调用时,首先判断标志位的状态,如果标志位已经被设置为true,则忽略该次调用;如果标志位为false,则执行方法,并将标志位设置为true。当方法执行完毕后,可以通过异步任务或其他方式将标志位重置为false,以便下一次方法调用。 3. 使用消息队列:可以通过Handler类或HandlerThread类来创建一个消息队列,将方法调用封装在消息中,然后将消息添加到消息队列中。通过设置一个方法执行的最小间隔时间,可以控制方法的调用频率。当消息队列中存在未处理的消息时,可以忽略新的方法调用。 4. 使用RxJava:RxJava是一种响应式编程库,可以通过设置debounce(防抖动)操作符来限制方法的调用频率。debounce操作符会在指定的时间内(如100ms)内忽略所有方法调用,只接受最后一次方法调用。 通过以上方法,我们可以有效地限制方法的调用频率,避免出现频繁调用的问题。同时,我们还需要根据具体的业务需求和场景选择合适的方法来进行开发。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值