分析lg
通过log发现插入usb鼠标后,触发了onConfigChange界面重新走生命周期了
02-28 14:45:09.089 813 1263 I configuration_changed: 96
02-28 14:45:09.100 813 1263 I am_relaunch_resume_activity: [0,12574405,406,com.gwm.app.media.usbvideo/.UsbVideoMainActivity]
02-28 14:45:09.123 14985 14985 I am_on_paused_called: [0,com.gwm.app.media.usbvideo.UsbVideoMainActivity,performPause]
02-28 14:45:09.125 14985 14985 I am_on_stop_called: [0,com.gwm.app.media.usbvideo.UsbVideoMainActivity,handleRelaunchActivity]
02-28 14:45:09.133 14985 14985 I am_on_destroy_called: [0,com.gwm.app.media.usbvideo.UsbVideoMainActivity,performDestroy]
02-28 14:45:09.206 14985 14985 I am_on_create_called: [0,com.gwm.app.media.usbvideo.UsbVideoMainActivity,performCreate]
02-28 14:45:09.247 14985 14985 I am_on_start_called: [0,com.gwm.app.media.usbvideo.UsbVideoMainActivity,handleStartActivity]
02-28 14:45:09.248 14985 14985 I am_on_resume_called: [0,com.gwm.app.media.usbvideo.UsbVideoMainActivity,RESUME_ACTIVITY]
查看configuration属性
configuration_changed: 96,将96换成16进制是0X60,但是在实际使用中,我们通常会从log中查看到configChanges,但不确定到底是哪个config的变更导致的,这就需要从framework中查看。
文件路径:frameworks/base/core/res/res/values/attrs_manifest.xml
<attr name="configChanges">
<flag name="keyboard" value="0x0010" />
<!-- The keyboard or navigation accessibility has changed, for example
the user has slid the keyboard out to expose it. Note that
despite its name, this applied to any accessibility: keyboard
or navigation. -->
<flag name="keyboardHidden" value="0x0020" />
<!-- The navigation type has changed. Should never normally happen. -->
<flag name="navigation" value="0x0040" />
<!-- The screen orientation has changed, that is the user has
rotated the device. -->
<flag name="orientation" value="0x0080" />
但是在attrs_manifest.xml中并没有找到0x60这个数值,那可能是两个数值的和是0x60,0x20+0x40=0x60
2.3 为了验证该想法,让App在AndroidManifest.xml中, 发生闪烁的activity的定义加上:
android:configChanges="keyboardHidden|navigation" 发现竟然不闪烁了。
原因追溯,代码跟踪:
|–frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
mInputManager = new InputManager(eventHub, this, this);
1
|-- frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::doNotifyConfigurationChangedInterruptible(
CommandEntry* commandEntry) {
mLock.unlock();
#ifndef INPUT_BOX
//-----------mPolicy来自 new InputManager(eventHub, this, this);---------
mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
#endif
mLock.lock();
}
|–frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
#if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyConfigurationChanged - when=%lld", when);
#endif
JNIEnv* env = jniEnv();
env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyConfigurationChanged, when);
checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
}
1
|–frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
// Native callback.
private void notifyConfigurationChanged(long whenNanos) {
mWindowManagerCallbacks.notifyConfigurationChanged();
}
|–frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
/* Notifies that the input device configuration has changed. */
@Override
public void notifyConfigurationChanged() {
mService.sendNewConfiguration();
synchronized (mInputDevicesReadyMonitor) {
if (!mInputDevicesReady) {
mInputDevicesReady = true;
mInputDevicesReadyMonitor.notifyAll();
}
}
}
1
|-- frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
1
/*
* Instruct the Activity Manager to fetch the current configuration and broadcast
* that to config-changed listeners if appropriate.
*/
void sendNewConfiguration() {
try {
mActivityManager.updateConfiguration(null);
} catch (RemoteException e) {
}
}
public Configuration computeNewConfiguration() {
synchronized (mWindowMap) {
return computeNewConfigurationLocked();
}
}
|-- frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
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);
Binder.restoreCallingIdentity(origId);
}
}