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 = 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. */ 无止境的读取原始设备信息然后处理之
/* 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. */无止境的分发输入消息
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 是本进程所有的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遵循这个流程,像按键消息、触摸消息也是这么一个流程
更多相关文章
- Android(安卓)文件绝对路径和Content开头的Uri互相转换
- Android(安卓)-- Activity值传递
- [Android] 在程序中实现延时的常用的两种方式
- Android(安卓)AccessibilityDelegate的使用
- Android开发常见的问题
- Android与js的交互方式
- JNI 防混淆 Android(安卓)proguard
- Android(安卓)开发工具(以后持续更新)
- Android如何获取屏幕的分辨