[SYSTEM-SERVER] Avoid a dead lock between ActivityManager and PowerManager services
"main" prio=5 tid=1 Blocked | group="main"
sCount=1 dsCount=0 obj=0x73fbbfa8 self=0x7ff7b3024000
| sysTid=3219 nice=-2 cgrp=default sched=0/0 handle=0x7ff7b6f853e0
| state=S schedstat=( 2270057780 115981310 8889 ) utm=149 stm=77 core=0 HZ=100 |
stack=0x7fff62c6e000-0x7fff62c70000 stackSize=8MB
| held mutexes= at com.android.server.am.ActivityManagerService.registerReceiver(ActivityManagerService.java:15583) - waiting to lock <0x016a0e36> (a com.android.server.am.ActivityManagerService) -->
synchronized(this): lock held by thread 29 at
android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1655)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1623)
at com.android.server.power.PowerManagerService.systemReady(PowerManagerService.java:522) - locked <0x1e40b137> (a java.lang.Object) -->
synchronized(mLock) at com.android.server.SystemServer.startOtherServices(SystemServer.java:1054) at com.android.server.SystemServer.run(SystemServer.java:263)
at com.android.server.SystemServer.main(SystemServer.java:177) at java.lang.reflect.Method.invoke!(Native method) at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
"InputDispatcher" prio=10 tid=29 Blocked | group="main"
sCount=1 dsCount=0 obj=0x12fb50a0 self=0x7ff7a9656200
| sysTid=3418 nice=-8 cgrp=default sched=0/0 handle=0x7ff7a9511400
| state=S schedstat=( 3081453 618956 33 ) utm=0 stm=0 core=0 HZ=100
| stack=0x7ff79f104000-0x7ff79f106000 stackSize=1012KB
| held mutexes= at com.android.server.power.PowerManagerService.setUserActivityTimeoutOverrideFromWindowManagerInternal(PowerManagerService.java:2317)
- waiting to lock <0x1e40b137> (a java.lang.Object --> synchronized(mLock):
lock held by thread 1 at com.android.server.power.PowerManagerService.access$5600(PowerManagerService.java:84)
at com.android.server.power.PowerManagerService$LocalService.setUserActivityTimeoutOverrideFromWindowManager(PowerManagerService.java:3277)
at com.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLockedInner(WindowManagerService.java:10110)
at com.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLockedLoop(WindowManagerService.java:8789)
at com.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLocked(WindowManagerService.java:8731)
at com.android.server.wm.WindowManagerService.setNewConfiguration(WindowManagerService.java:3934)
- locked <0x0b892c09> (a java.util.HashMap) at com.android.server.am.ActivityManagerService.updateConfigurationLocked(ActivityManagerService.java:16785)
at com.android.server.am.ActivityManagerService.updateConfiguration(ActivityManagerService.java:16668)
- locked <0x016a0e36> (a com.android.server.am.ActivityManagerService) --> synchronized(this)
at com.android.server.wm.WindowManagerService.sendNewConfiguration(WindowManagerService.java:7053)
at com.android.server.wm.InputMonitor.notifyConfigurationChanged(InputMonitor.java:331)
at com.android.server.input.InputManagerService.notifyConfigurationChanged(InputManagerService.java:1385)
修改方法
frameworks/base / services/java/com/android/server/SystemServer.java
添加synchronred线程同步
try {
// Need to synchronize with ActivityManagerService before locking on mPowerManagerService.mlock
// to avoid a possible dead lock with InputDispatcher.
synchronized (mActivityManagerService) {
// TODO: use boot phase
mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
}
} catch (Throwable e) {
reportWtf("making Power Manager Service ready", e);
}
问题2:
Root cause: This is a abnormal case.The system will kill the process even if the activity which belong to the process is being launched.
If the appDiedLock function is caled after the startActivityMayWait function.
AMS will consider the process is still alive.But the process is died in fact. So there is an exception when AMS call scheduleLaunchActivity
.and then AMS will restart the process. But before do it,
AMS will clean all the activity records which belong to the old process. After do this,
There will be no activity belongs to the process in AMS's history. After the process restart,
we can see AMS want to start activity which is the top of the AMS's history stack.
And the activity should belong to the process.But from the analysis before,
There is no activity belongs to the process.So there is no activity to launch.
This will lead there is no focuse activity in system then cause ANR.
Solution: this is workaround fix. Add a flag in ActivityRecord,When this abnormal case appear,
set the flag.and when AMS clean the activity stack,Reserve the ActivityRecord object according to the added flag.
修改代码路径
services/java/com/android/server/am/ActivityManagerService.java |
services/java/com/android/server/am/ActivityStack.java
思路:因为OOM的时候杀死了一些进程导致OOM
添加判断条件在handleAppDiedLocked不kill掉一些进程。
问题3:清除掉已经被kill的应用的资源
JAVACRASH on system.server java.lang.OutOfMemoryError at android.os.FileUtils.readTextFile
WindowManagerService: Cleanup the starting window resources
When an application dies very early after being launched, some resources ViewRootImpl are left in system_server.
This patch removes those resources when the window is removed from WindowManagerService.
</pre><pre>
public void removeWindowLocked(Session session, WindowState win) {
...
if ( (win.mAppToken != null) && (win.mAppToken.startingView != null) ) {
View view = win.mAppToken.startingView;
win.mAppToken.startingView = null;
mPolicy.removeStartingWindow(null, view);
}
...
<pre name="code" class="html">}
问题4:当一个应用升级了,应该删除对应之前不需要的apk的odex文件
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f645d42..1525d35 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1826,23 +1826,21 @@
1826 1826
1827 1827 if (systemServerClassPath != null) {
1828 1828 String[] systemServerClassPathElements = splitString(systemServerClassPath, ':');
1829 1829 for (String element : systemServerClassPathElements) {
1830 1830 alreadyDexOpted.add(element);
1831 1831 }
1832 1832 } else {
1833 1833 Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
1834 1834 }
1835 1835
1836 - final List<String> allInstructionSets = getAllInstructionSets();
1837 - final String[] dexCodeInstructionSets =
1838 - getDexCodeInstructionSets(allInstructionSets.toArray(new String[allInstructionSets.s
ize()]));
1836 + final String[] dexCodeInstructionSets = InstructionSets.getAllDexCodeInstructionSets();
1839 1837
1840 1838 /**
1841 1839 * Ensure all external libraries have had dexopt run on them.
1842 1840 */
1843 1841 if (mSharedLibraries.size() > 0) {
1844 1842 // NOTE: For now, we're compiling these system "shared libraries"
1845 1843 // (and framework jars) into all available architectures. It's possible
1846 1844 // to compile them only when we come across an app that uses them (there's
1847 1845 // already logic for that in scanPackageLI) but that adds some complexity.
1848 1846 SELECTIVE_ENABLED = SystemProperties.getBoolean("persist.selective.enabled", DEFAULT
_SELECTIVE_ENABLED);
@@ -11262,20 +11260,27 @@
11262 11260 res.setError(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
11263 11261 "Forbidding shared user change from " + oldPkgSetting.sharedUser
11264 11262 + " to " + newPkgSetting.sharedUser);
11265 11263 updatedSettings = true;
11266 11264 }
11267 11265 }
11268 11266
11269 11267 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
11270 11268 updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
11271 11269 updatedSettings = true;
11270 +
11271 + // Remove existing odex in /data
11272 + final String[] dexCodeIsas = InstructionSets.getAllDexCodeInstructionSets();
11273 + for (String dexCodeIsa : dexCodeIsas) {
11274 + mInstaller.rmdex(deletedPackage.applicationInfo.sourceDir,
11275 + dexCodeIsa);
11276 + }
11272 11277 }
11273 11278
11274 11279 } catch (PackageManagerException e) {
11275 11280 res.setError("Package couldn't be installed in " + pkg.codePath, e);
11276 11281 }
11277 11282
11278 11283 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
11279 11284 // Re installation failed. Restore old information
11280 11285 // Remove new pkg information
11281 11286 if (newPackage != null) {