Boost thread priority when holding the WM lock
Test: Take systrace of open app, make sure thead is boosted while
doing stuff in WM
Test: Run WmSlam with and without boosting. Observe an
improvement.
Bug: 36631902
Change-Id: Iadb036f8d12bbf59091466500e82207cf6fa85d5
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 099f557..8003d21 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -39,8 +39,8 @@
LOCAL_JACK_FLAGS := \
-D jack.transformations.boost-locked-region-priority=true \
- -D jack.transformations.boost-locked-region-priority.classname=com.android.server.am.ActivityManagerService \
- -D jack.transformations.boost-locked-region-priority.request=com.android.server.am.ActivityManagerService\#boostPriorityForLockedSection \
- -D jack.transformations.boost-locked-region-priority.reset=com.android.server.am.ActivityManagerService\#resetPriorityAfterLockedSection
+ -D jack.transformations.boost-locked-region-priority.classname=com.android.server.am.ActivityManagerService,com.android.server.wm.WindowHashMap \
+ -D jack.transformations.boost-locked-region-priority.request=com.android.server.am.ActivityManagerService\#boostPriorityForLockedSection,com.android.server.wm.WindowManagerService\#boostPriorityForLockedSection \
+ -D jack.transformations.boost-locked-region-priority.reset=com.android.server.am.ActivityManagerService\#resetPriorityAfterLockedSection,com.android.server.wm.WindowManagerService\#resetPriorityAfterLockedSection
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/ThreadPriorityBooster.java b/services/core/java/com/android/server/ThreadPriorityBooster.java
new file mode 100644
index 0000000..17965d0
--- /dev/null
+++ b/services/core/java/com/android/server/ThreadPriorityBooster.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server;
+
+import android.os.Process;
+
+/**
+ * Utility class to boost threads in sections where important locks are held.
+ */
+public class ThreadPriorityBooster {
+
+ private final int mBoostToPriority;
+ private final int mLockGuardIndex;
+
+ private final ThreadLocal<PriorityState> mThreadState = new ThreadLocal<PriorityState>() {
+ @Override protected PriorityState initialValue() {
+ return new PriorityState();
+ }
+ };
+
+ public ThreadPriorityBooster(int boostToPriority, int lockGuardIndex) {
+ mBoostToPriority = boostToPriority;
+ mLockGuardIndex = lockGuardIndex;
+ }
+
+ public void boost() {
+ final int tid = Process.myTid();
+ final int prevPriority = Process.getThreadPriority(tid);
+ PriorityState state = mThreadState.get();
+ if (state.regionCounter == 0 && prevPriority > mBoostToPriority) {
+ state.prevPriority = prevPriority;
+ Process.setThreadPriority(tid, mBoostToPriority);
+ }
+ state.regionCounter++;
+ if (LockGuard.ENABLED) {
+ LockGuard.guard(mLockGuardIndex);
+ }
+ }
+
+ public void reset() {
+ PriorityState state = mThreadState.get();
+ state.regionCounter--;
+ if (state.regionCounter == 0 && state.prevPriority > mBoostToPriority) {
+ Process.setThreadPriority(Process.myTid(), state.prevPriority);
+ }
+ }
+
+ private static class PriorityState {
+
+ /**
+ * Acts as counter for number of synchronized region that needs to acquire 'this' as a lock
+ * the current thread is currently in. When it drops down to zero, we will no longer boost
+ * the thread's priority.
+ */
+ int regionCounter;
+
+ /**
+ * The thread's previous priority before boosting.
+ */
+ int prevPriority;
+ }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4c747a1..19fc2b8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17,12 +17,12 @@
package com.android.server.am;
import static android.Manifest.permission.CHANGE_CONFIGURATION;
+import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
-import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
@@ -42,13 +42,49 @@
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
import static android.os.Build.VERSION_CODES.N;
+import static android.os.Process.BLUETOOTH_UID;
+import static android.os.Process.FIRST_APPLICATION_UID;
+import static android.os.Process.FIRST_ISOLATED_UID;
+import static android.os.Process.LAST_ISOLATED_UID;
+import static android.os.Process.NFC_UID;
+import static android.os.Process.PHONE_UID;
import static android.os.Process.PROC_CHAR;
import static android.os.Process.PROC_OUT_LONG;
import static android.os.Process.PROC_PARENS;
import static android.os.Process.PROC_SPACE_TERM;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
+import static android.os.Process.ProcessStartResult;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SCHED_FIFO;
+import static android.os.Process.SCHED_OTHER;
+import static android.os.Process.SCHED_RESET_ON_FORK;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SIGNAL_QUIT;
+import static android.os.Process.SIGNAL_USR1;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.THREAD_GROUP_BG_NONINTERACTIVE;
+import static android.os.Process.THREAD_GROUP_DEFAULT;
+import static android.os.Process.THREAD_GROUP_TOP_APP;
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
+import static android.os.Process.getFreeMemory;
+import static android.os.Process.getThreadPriority;
+import static android.os.Process.getTotalMemory;
+import static android.os.Process.isThreadInProcess;
+import static android.os.Process.killProcess;
+import static android.os.Process.killProcessQuiet;
+import static android.os.Process.myPid;
+import static android.os.Process.myUid;
+import static android.os.Process.readProcFile;
+import static android.os.Process.removeAllProcessGroups;
+import static android.os.Process.sendSignal;
+import static android.os.Process.setProcessGroup;
+import static android.os.Process.setThreadPriority;
+import static android.os.Process.setThreadScheduler;
+import static android.os.Process.startWebView;
+import static android.os.Process.zygoteProcess;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
@@ -323,7 +359,6 @@
import android.view.View;
import android.view.WindowManager;
-import com.android.internal.notification.SystemNotificationChannels;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -341,6 +376,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.IResultReceiver;
@@ -367,6 +403,7 @@
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
+import com.android.server.ThreadPriorityBooster;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.firewall.IntentFirewall;
@@ -409,7 +446,6 @@
import java.util.concurrent.atomic.AtomicLong;
import dalvik.system.VMRuntime;
-
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
@@ -547,7 +583,7 @@
// Maximum number of persisted Uri grants a package is allowed
static final int MAX_PERSISTED_URI_GRANTS = 128;
- static final int MY_PID = Process.myPid();
+ static final int MY_PID = myPid();
static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -680,13 +716,13 @@
if (mTopAppVrThreadTid > 0) {
// Ensure that when entering persistent VR mode the last top-app loses
// SCHED_FIFO.
- Process.setThreadScheduler(mTopAppVrThreadTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(mTopAppVrThreadTid, SCHED_OTHER, 0);
mTopAppVrThreadTid = 0;
}
} else if (mPersistentVrThreadTid > 0) {
// Ensure that when leaving persistent VR mode we reschedule the high priority
// persistent thread.
- Process.setThreadScheduler(mPersistentVrThreadTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(mPersistentVrThreadTid, SCHED_OTHER, 0);
mPersistentVrThreadTid = 0;
}
}
@@ -773,42 +809,15 @@
&& !mKeyguardController.isKeyguardShowing();
}
- private static final class PriorityState {
- // Acts as counter for number of synchronized region that needs to acquire 'this' as a lock
- // the current thread is currently in. When it drops down to zero, we will no longer boost
- // the thread's priority.
- private int regionCounter = 0;
-
- // The thread's previous priority before boosting.
- private int prevPriority = Integer.MIN_VALUE;
- }
-
- static ThreadLocal<PriorityState> sThreadPriorityState = new ThreadLocal<PriorityState>() {
- @Override protected PriorityState initialValue() {
- return new PriorityState();
- }
- };
+ private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
+ THREAD_PRIORITY_FOREGROUND, LockGuard.INDEX_ACTIVITY);
static void boostPriorityForLockedSection() {
- int tid = Process.myTid();
- int prevPriority = Process.getThreadPriority(tid);
- PriorityState state = sThreadPriorityState.get();
- if (state.regionCounter == 0 && prevPriority > -2) {
- state.prevPriority = prevPriority;
- Process.setThreadPriority(tid, -2);
- }
- state.regionCounter++;
- if (LockGuard.ENABLED) {
- LockGuard.guard(LockGuard.INDEX_ACTIVITY);
- }
+ sThreadPriorityBooster.boost();
}
static void resetPriorityAfterLockedSection() {
- PriorityState state = sThreadPriorityState.get();
- state.regionCounter--;
- if (state.regionCounter == 0 && state.prevPriority > -2) {
- Process.setThreadPriority(Process.myTid(), state.prevPriority);
- }
+ sThreadPriorityBooster.reset();
}
public class PendingAssistExtras extends Binder implements Runnable {
@@ -889,7 +898,7 @@
* Non-persistent app uid whitelist for background restrictions
*/
int[] mBackgroundUidWhitelist = new int[] {
- Process.BLUETOOTH_UID
+ BLUETOOTH_UID
};
/**
@@ -2467,12 +2476,12 @@
if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
try {
if (mVrState == VR_MODE) {
- Process.setThreadScheduler(proc.vrThreadTid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(proc.vrThreadTid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
mTopAppVrThreadTid = proc.vrThreadTid;
} else {
- Process.setThreadScheduler(proc.vrThreadTid,
- Process.SCHED_OTHER, 0);
+ setThreadScheduler(proc.vrThreadTid,
+ SCHED_OTHER, 0);
mTopAppVrThreadTid = 0;
}
} catch (IllegalArgumentException e) {
@@ -2529,7 +2538,7 @@
final List<ProcessCpuTracker.Stats> stats;
synchronized (mProcessCpuTracker) {
stats = mProcessCpuTracker.getStats( (st)-> {
- return st.vsize > 0 && st.uid < Process.FIRST_APPLICATION_UID;
+ return st.vsize > 0 && st.uid < FIRST_APPLICATION_UID;
});
}
final int N = stats.size();
@@ -2780,7 +2789,7 @@
com.android.internal.R.bool.config_permissionReviewRequired);
mHandlerThread = new ServiceThread(TAG,
- android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
+ THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
mUiHandler = mInjector.getUiHandler(this);
@@ -2801,7 +2810,7 @@
/* static; one-time init here */
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill",
- android.os.Process.THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
+ THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
sKillThread.start();
sKillHandler = new KillHandler(sKillThread.getLooper());
}
@@ -2919,7 +2928,7 @@
}
private void start() {
- Process.removeAllProcessGroups();
+ removeAllProcessGroups();
mProcessCpuThread.start();
mBatteryStatsService.publish(mContext);
@@ -3127,7 +3136,7 @@
synchronized (this) {
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
AppOpsManager.OP_NONE, null, false, false,
- -1, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ -1, SYSTEM_UID, UserHandle.USER_ALL);
}
}
@@ -3399,7 +3408,7 @@
if (lrui >= 0) {
if (!app.killed) {
Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
- Process.killProcessQuiet(app.pid);
+ killProcessQuiet(app.pid);
killProcessGroup(app.uid, app.pid);
}
if (lrui <= mLruProcessActivityStart) {
@@ -3608,7 +3617,7 @@
}
final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
- if (uid == Process.SYSTEM_UID) {
+ if (uid == SYSTEM_UID) {
// The system gets to run in any process. If there are multiple
// processes with the same uid, just pick the first (this
// should never happen).
@@ -3674,7 +3683,7 @@
// closest thing to a parent's uid is SYSTEM_UID.
// The only important thing here is to keep AI.uid != PR.uid, in order to trigger
// the |isolated| logic in the ProcessRecord constructor.
- info.uid = Process.SYSTEM_UID;
+ info.uid = SYSTEM_UID;
info.processName = processName;
info.className = entryPoint;
info.packageName = "android";
@@ -3969,9 +3978,9 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
- Process.ProcessStartResult startResult;
+ ProcessStartResult startResult;
if (hostingType.equals("webview_service")) {
- startResult = Process.startWebView(entryPoint,
+ startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, entryPointArgs);
@@ -4208,7 +4217,7 @@
}
void enforceShellRestriction(String restriction, int userHandle) {
- if (Binder.getCallingUid() == Process.SHELL_UID) {
+ if (Binder.getCallingUid() == SHELL_UID) {
if (userHandle < 0 || mUserController.hasUserRestriction(restriction, userHandle)) {
throw new SecurityException("Shell does not have permission to access user "
+ userHandle);
@@ -4574,7 +4583,7 @@
if (sourceRecord.app == null) {
throw new SecurityException("Called without a process attached to activity");
}
- if (UserHandle.getAppId(sourceRecord.app.uid) != Process.SYSTEM_UID) {
+ if (UserHandle.getAppId(sourceRecord.app.uid) != SYSTEM_UID) {
// This is still okay, as long as this activity is running under the
// uid of the original calling activity.
if (sourceRecord.app.uid != sourceRecord.launchedFromUid) {
@@ -5426,7 +5435,7 @@
if (!app.killed) {
if (!fromBinderDied) {
- Process.killProcessQuiet(pid);
+ killProcessQuiet(pid);
}
killProcessGroup(app.uid, pid);
app.killed = true;
@@ -5521,7 +5530,7 @@
}
public void dumpWithTimeout(int pid) {
- Process.sendSignal(pid, Process.SIGNAL_QUIT);
+ sendSignal(pid, SIGNAL_QUIT);
synchronized (this) {
try {
wait(TRACE_DUMP_TIMEOUT_MS); // Wait for traces file to be closed.
@@ -5776,7 +5785,7 @@
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(Intent.EXTRA_UID, pkgUidF);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF));
- broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
+ broadcastIntentInPackage("android", SYSTEM_UID, intent,
null, null, 0, null, null, null, null, false, false, userIdF);
if (observer != null) {
@@ -5994,7 +6003,7 @@
public void addPackageDependency(String packageName) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
- if (callingPid == Process.myPid()) {
+ if (callingPid == myPid()) {
// Yeah, um, no.
return;
}
@@ -6026,7 +6035,7 @@
}
int callerUid = Binder.getCallingUid();
// Only the system server can kill an application
- if (UserHandle.getAppId(callerUid) == Process.SYSTEM_UID) {
+ if (UserHandle.getAppId(callerUid) == SYSTEM_UID) {
// Post an aysnc message to kill the application
Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
msg.arg1 = appId;
@@ -6053,7 +6062,7 @@
synchronized (this) {
// Only allow this from foreground processes, so that background
// applications can't abuse it to prevent system UI from being shown.
- if (uid >= Process.FIRST_APPLICATION_UID) {
+ if (uid >= FIRST_APPLICATION_UID) {
ProcessRecord proc;
synchronized (mPidsSelfLocked) {
proc = mPidsSelfLocked.get(pid);
@@ -6084,7 +6093,7 @@
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
AppOpsManager.OP_NONE, null, false, false,
- -1, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ -1, SYSTEM_UID, UserHandle.USER_ALL);
}
@Override
@@ -6150,7 +6159,7 @@
int callerUid = Binder.getCallingUid();
// Only the system server can kill an application
- if (callerUid == Process.SYSTEM_UID) {
+ if (callerUid == SYSTEM_UID) {
synchronized (this) {
ProcessRecord app = getProcessRecordLocked(processName, uid, true);
if (app != null && app.thread != null) {
@@ -6186,7 +6195,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.getUserId(uid));
+ null, false, false, MY_PID, SYSTEM_UID, UserHandle.getUserId(uid));
}
@@ -6703,7 +6712,7 @@
+ " (IApplicationThread " + thread + "); dropping process");
EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
if (pid > 0 && pid != MY_PID) {
- Process.killProcessQuiet(pid);
+ killProcessQuiet(pid);
//TODO: killProcessGroup(app.info.uid, pid);
} else {
try {
@@ -6811,7 +6820,7 @@
// If the app is being launched for restore or full backup, set it up specially
boolean isRestrictedBackupMode = false;
if (mBackupTarget != null && mBackupAppName.equals(processName)) {
- isRestrictedBackupMode = mBackupTarget.appInfo.uid >= Process.FIRST_APPLICATION_UID
+ isRestrictedBackupMode = mBackupTarget.appInfo.uid >= FIRST_APPLICATION_UID
&& ((mBackupTarget.backupMode == BackupRecord.RESTORE)
|| (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
|| (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
@@ -7034,7 +7043,7 @@
@Override
public void showBootMessage(final CharSequence msg, final boolean always) {
- if (Binder.getCallingUid() != Process.myUid()) {
+ if (Binder.getCallingUid() != myUid()) {
throw new SecurityException();
}
mWindowManager.showBootMessage(msg, always);
@@ -7071,7 +7080,7 @@
ArraySet<String> completedIsas = new ArraySet<String>();
for (String abi : Build.SUPPORTED_ABIS) {
- Process.zygoteProcess.establishZygoteConnectionForAbi(abi);
+ zygoteProcess.establishZygoteConnectionForAbi(abi);
final String instructionSet = VMRuntime.getInstructionSet(abi);
if (!completedIsas.contains(instructionSet)) {
try {
@@ -7412,7 +7421,7 @@
userId = UserHandle.USER_CURRENT;
}
try {
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+ if (callingUid != 0 && callingUid != SYSTEM_UID) {
final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid));
if (!UserHandle.isSameApp(callingUid, uid)) {
@@ -8679,7 +8688,7 @@
// Third... does the caller itself have permission to access
// this uri?
final int callingAppId = UserHandle.getAppId(callingUid);
- if ((callingAppId == Process.SYSTEM_UID) || (callingAppId == Process.ROOT_UID)) {
+ if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
if ("com.android.settings.files".equals(grantUri.uri.getAuthority())) {
// Exempted authority for cropping user photos in Settings app
} else {
@@ -9165,7 +9174,7 @@
throw new IllegalArgumentException("Unknown owner: " + token);
}
if (fromUid != Binder.getCallingUid()) {
- if (Binder.getCallingUid() != Process.myUid()) {
+ if (Binder.getCallingUid() != myUid()) {
// Only system code can grant URI permissions on behalf
// of other users.
throw new SecurityException("nice try");
@@ -9549,8 +9558,8 @@
public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
final long cachedAppMem = mProcessList.getMemLevel(ProcessList.CACHED_APP_MIN_ADJ);
- outInfo.availMem = Process.getFreeMemory();
- outInfo.totalMem = Process.getTotalMemory();
+ outInfo.availMem = getFreeMemory();
+ outInfo.totalMem = getTotalMemory();
outInfo.threshold = homeAppMem;
outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((cachedAppMem-homeAppMem)/2));
outInfo.hiddenAppThreshold = cachedAppMem;
@@ -10693,7 +10702,7 @@
@Override
public void updateDeviceOwner(String packageName) {
final int callingUid = Binder.getCallingUid();
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+ if (callingUid != 0 && callingUid != SYSTEM_UID) {
throw new SecurityException("updateDeviceOwner called from non-system process");
}
synchronized (this) {
@@ -10704,7 +10713,7 @@
@Override
public void updateLockTaskPackages(int userId, String[] packages) {
final int callingUid = Binder.getCallingUid();
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+ if (callingUid != 0 && callingUid != SYSTEM_UID) {
enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
"updateLockTaskPackages()");
}
@@ -10727,7 +10736,7 @@
// is initiated by system after the pinning request was shown and locked mode is initiated
// by an authorized app directly
final int callingUid = Binder.getCallingUid();
- boolean isSystemInitiated = callingUid == Process.SYSTEM_UID;
+ boolean isSystemInitiated = callingUid == SYSTEM_UID;
long ident = Binder.clearCallingIdentity();
try {
if (!isSystemInitiated) {
@@ -11206,7 +11215,7 @@
proc.procStatFile = "/proc/" + proc.pid + "/stat";
}
mProcessStateStatsLongs[0] = 0;
- if (!Process.readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
+ if (!readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
mProcessStateStatsLongs, null)) {
if (DEBUG_OOM_ADJ) Slog.d(TAG, "UNABLE TO RETRIEVE STATE FOR " + proc.procStatFile);
return false;
@@ -11908,7 +11917,7 @@
public final void installSystemProviders() {
List<ProviderInfo> providers;
synchronized (this) {
- ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
+ ProcessRecord app = mProcessNames.get("system", SYSTEM_UID);
providers = generateApplicationProvidersLocked(app);
if (providers != null) {
for (int i=providers.size()-1; i>=0; i--) {
@@ -12081,11 +12090,11 @@
int uid = info.uid;
if (isolated) {
if (isolatedUid == 0) {
- int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1;
+ int stepsLeft = LAST_ISOLATED_UID - FIRST_ISOLATED_UID + 1;
while (true) {
- if (mNextIsolatedProcessUid < Process.FIRST_ISOLATED_UID
- || mNextIsolatedProcessUid > Process.LAST_ISOLATED_UID) {
- mNextIsolatedProcessUid = Process.FIRST_ISOLATED_UID;
+ if (mNextIsolatedProcessUid < FIRST_ISOLATED_UID
+ || mNextIsolatedProcessUid > LAST_ISOLATED_UID) {
+ mNextIsolatedProcessUid = FIRST_ISOLATED_UID;
}
uid = UserHandle.getUid(userId, mNextIsolatedProcessUid);
mNextIsolatedProcessUid++;
@@ -13274,7 +13283,7 @@
synchronized (this) {
// Disable any existing VR thread.
if (mTopAppVrThreadTid > 0) {
- Process.setThreadScheduler(mTopAppVrThreadTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(mTopAppVrThreadTid, SCHED_OTHER, 0);
mTopAppVrThreadTid = 0;
}
@@ -13298,15 +13307,15 @@
*/
private int updateVrThreadLocked(ProcessRecord proc, int lastTid, int pid, int tid) {
// ensure the tid belongs to the process
- if (!Process.isThreadInProcess(pid, tid)) {
+ if (!isThreadInProcess(pid, tid)) {
throw new IllegalArgumentException("VR thread does not belong to process");
}
// reset existing VR thread to CFS if this thread still exists and belongs to
// the calling process
- if (lastTid != 0 && Process.isThreadInProcess(pid, lastTid)) {
+ if (lastTid != 0 && isThreadInProcess(pid, lastTid)) {
try {
- Process.setThreadScheduler(lastTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(lastTid, SCHED_OTHER, 0);
} catch (IllegalArgumentException e) {
// Ignore this. Only occurs in race condition where previous VR thread
// was destroyed during this method call.
@@ -13317,8 +13326,8 @@
try {
if ((proc == null || proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP)
&& tid > 0) {
- Process.setThreadScheduler(tid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(tid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
}
return tid;
} catch (IllegalArgumentException e) {
@@ -13337,7 +13346,7 @@
proc = mPidsSelfLocked.get(pid);
if (proc != null && proc.renderThreadTid == 0 && tid > 0) {
// ensure the tid belongs to the process
- if (!Process.isThreadInProcess(pid, tid)) {
+ if (!isThreadInProcess(pid, tid)) {
throw new IllegalArgumentException(
"Render thread does not belong to process");
}
@@ -13349,10 +13358,10 @@
if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
if (DEBUG_OOM_ADJ) Slog.d("UI_FIFO", "Promoting " + tid + "out of band");
if (mUseFifoUiScheduling) {
- Process.setThreadScheduler(proc.renderThreadTid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(proc.renderThreadTid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
} else {
- Process.setThreadPriority(proc.renderThreadTid, -10);
+ setThreadPriority(proc.renderThreadTid, -10);
}
}
} else {
@@ -13513,7 +13522,7 @@
if (sender == null) {
uid = sourceUid;
} else {
- uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+ uid = rec.uid == MY_UID ? SYSTEM_UID : rec.uid;
}
BatteryStatsImpl.Uid.Pkg pkg =
stats.getPackageStatsLocked(sourceUid >= 0 ? sourceUid : uid,
@@ -13536,7 +13545,7 @@
if (sender == null) {
uid = sourceUid;
} else {
- uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+ uid = rec.uid == MY_UID ? SYSTEM_UID : rec.uid;
}
mBatteryStatsService.noteAlarmStart(tag, sourceUid >= 0 ? sourceUid : uid);
}
@@ -13555,14 +13564,14 @@
if (sender == null) {
uid = sourceUid;
} else {
- uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+ uid = rec.uid == MY_UID ? SYSTEM_UID : rec.uid;
}
mBatteryStatsService.noteAlarmFinish(tag, sourceUid >= 0 ? sourceUid : uid);
}
}
public boolean killPids(int[] pids, String pReason, boolean secure) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (Binder.getCallingUid() != SYSTEM_UID) {
throw new SecurityException("killPids only available to the system");
}
String reason = (pReason == null) ? "Unknown" : pReason;
@@ -13628,7 +13637,7 @@
@Override
public boolean killProcessesBelowForeground(String reason) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (Binder.getCallingUid() != SYSTEM_UID) {
throw new SecurityException("killProcessesBelowForeground() only available to system");
}
@@ -13636,7 +13645,7 @@
}
private boolean killProcessesBelowAdj(int belowAdj, String reason) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (Binder.getCallingUid() != SYSTEM_UID) {
throw new SecurityException("killProcessesBelowAdj() only available to system");
}
@@ -13713,7 +13722,7 @@
Log.i(TAG, "Shutting down activity manager...");
shutdown(10000);
Log.i(TAG, "Shutdown complete, restarting!");
- Process.killProcess(Process.myPid());
+ killProcess(myPid());
System.exit(10);
}
};
@@ -14057,7 +14066,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, Process.SYSTEM_UID,
+ null, false, false, MY_PID, SYSTEM_UID,
currentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -14071,7 +14080,7 @@
}
}, 0, null, null,
new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
- null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed sending first user broadcasts", t);
} finally {
@@ -16716,22 +16725,22 @@
private final long[] getKsmInfo() {
long[] longOut = new long[4];
final int[] SINGLE_LONG_FORMAT = new int[] {
- Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG
+ PROC_SPACE_TERM| PROC_OUT_LONG
};
long[] longTmp = new long[1];
- Process.readProcFile("/sys/kernel/mm/ksm/pages_shared",
+ readProcFile("/sys/kernel/mm/ksm/pages_shared",
SINGLE_LONG_FORMAT, null, longTmp, null);
longOut[KSM_SHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
longTmp[0] = 0;
- Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing",
+ readProcFile("/sys/kernel/mm/ksm/pages_sharing",
SINGLE_LONG_FORMAT, null, longTmp, null);
longOut[KSM_SHARING] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
longTmp[0] = 0;
- Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared",
+ readProcFile("/sys/kernel/mm/ksm/pages_unshared",
SINGLE_LONG_FORMAT, null, longTmp, null);
longOut[KSM_UNSHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
longTmp[0] = 0;
- Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile",
+ readProcFile("/sys/kernel/mm/ksm/pages_volatile",
SINGLE_LONG_FORMAT, null, longTmp, null);
longOut[KSM_VOLATILE] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
return longOut;
@@ -18007,7 +18016,7 @@
String className, int flags) {
boolean result = false;
// For apps that don't have pre-defined UIDs, check for permission
- if (UserHandle.getAppId(aInfo.uid) >= Process.FIRST_APPLICATION_UID) {
+ if (UserHandle.getAppId(aInfo.uid) >= FIRST_APPLICATION_UID) {
if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) {
if (ActivityManager.checkUidPermission(
INTERACT_ACROSS_USERS,
@@ -18026,7 +18035,7 @@
result = true;
} else if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) {
// Phone app and persistent apps are allowed to export singleuser providers.
- result = UserHandle.isSameApp(aInfo.uid, Process.PHONE_UID)
+ result = UserHandle.isSameApp(aInfo.uid, PHONE_UID)
|| (aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0;
}
if (DEBUG_MU) Slog.v(TAG_MU,
@@ -18044,8 +18053,8 @@
boolean isValidSingletonCall(int callingUid, int componentUid) {
int componentAppId = UserHandle.getAppId(componentUid);
return UserHandle.isSameApp(callingUid, componentUid)
- || componentAppId == Process.SYSTEM_UID
- || componentAppId == Process.PHONE_UID
+ || componentAppId == SYSTEM_UID
+ || componentAppId == PHONE_UID
|| ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, componentUid)
== PackageManager.PERMISSION_GRANTED;
}
@@ -18286,7 +18295,7 @@
// =========================================================
private boolean isInstantApp(ProcessRecord record, String callerPackage, int uid) {
- if (UserHandle.getAppId(uid) < Process.FIRST_APPLICATION_UID) {
+ if (UserHandle.getAppId(uid) < FIRST_APPLICATION_UID) {
return false;
}
// Easy case -- we have the app's ProcessRecord.
@@ -18347,7 +18356,7 @@
+ " (pid=" + Binder.getCallingPid()
+ ") when registering receiver " + receiver);
}
- if (callerApp.info.uid != Process.SYSTEM_UID &&
+ if (callerApp.info.uid != SYSTEM_UID &&
!callerApp.pkgList.containsKey(callerPackage) &&
!"android".equals(callerPackage)) {
throw new SecurityException("Given caller package " + callerPackage
@@ -18564,7 +18573,7 @@
for (int user : users) {
// Skip users that have Shell restrictions, with exception of always permitted
// Shell broadcasts
- if (callingUid == Process.SHELL_UID
+ if (callingUid == SHELL_UID
&& mUserController.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, user)
&& !isPermittedShellBroadcast(intent)) {
@@ -18748,7 +18757,7 @@
// and upgrade steps.
if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) {
- if ((callingUid != Process.SYSTEM_UID
+ if ((callingUid != SYSTEM_UID
|| (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
&& !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
Slog.w(TAG, "Skipping broadcast of " + intent
@@ -18792,11 +18801,11 @@
final boolean isCallerSystem;
switch (UserHandle.getAppId(callingUid)) {
- case Process.ROOT_UID:
- case Process.SYSTEM_UID:
- case Process.PHONE_UID:
- case Process.BLUETOOTH_UID:
- case Process.NFC_UID:
+ case ROOT_UID:
+ case SYSTEM_UID:
+ case PHONE_UID:
+ case BLUETOOTH_UID:
+ case NFC_UID:
isCallerSystem = true;
break;
default:
@@ -19172,7 +19181,7 @@
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) {
- if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
+ if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
// Query one target user at a time, excluding shell-restricted users
for (int i = 0; i < users.length; i++) {
if (mUserController.hasUserRestriction(
@@ -19414,8 +19423,8 @@
if ((flags & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
switch (Binder.getCallingUid()) {
- case Process.ROOT_UID:
- case Process.SHELL_UID:
+ case ROOT_UID:
+ case SHELL_UID:
break;
default:
Slog.w(TAG, "Removing FLAG_RECEIVER_FROM_SHELL because caller is UID "
@@ -19870,7 +19879,7 @@
private void enforceWriteSettingsPermission(String func) {
int uid = Binder.getCallingUid();
- if (uid == Process.ROOT_UID) {
+ if (uid == ROOT_UID) {
return;
}
@@ -20068,7 +20077,7 @@
| Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
+ AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
UserHandle.USER_ALL);
if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
@@ -20079,7 +20088,7 @@
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
+ AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
UserHandle.USER_ALL);
}
@@ -21553,27 +21562,27 @@
int processGroup;
switch (app.curSchedGroup) {
case ProcessList.SCHED_GROUP_BACKGROUND:
- processGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ processGroup = THREAD_GROUP_BG_NONINTERACTIVE;
break;
case ProcessList.SCHED_GROUP_TOP_APP:
case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
- processGroup = Process.THREAD_GROUP_TOP_APP;
+ processGroup = THREAD_GROUP_TOP_APP;
break;
default:
- processGroup = Process.THREAD_GROUP_DEFAULT;
+ processGroup = THREAD_GROUP_DEFAULT;
break;
}
long oldId = Binder.clearCallingIdentity();
try {
- Process.setProcessGroup(app.pid, processGroup);
+ setProcessGroup(app.pid, processGroup);
if (app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
// do nothing if we already switched to RT
if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
// Switch VR thread for app to SCHED_FIFO
if (mVrState == VR_MODE && app.vrThreadTid != 0) {
try {
- Process.setThreadScheduler(app.vrThreadTid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(app.vrThreadTid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
mTopAppVrThreadTid = app.vrThreadTid;
} catch (IllegalArgumentException e) {
// thread died, ignore
@@ -21581,17 +21590,17 @@
}
if (mUseFifoUiScheduling) {
// Switch UI pipeline for app to SCHED_FIFO
- app.savedPriority = Process.getThreadPriority(app.pid);
+ app.savedPriority = getThreadPriority(app.pid);
try {
- Process.setThreadScheduler(app.pid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(app.pid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
} catch (IllegalArgumentException e) {
// thread died, ignore
}
if (app.renderThreadTid != 0) {
try {
- Process.setThreadScheduler(app.renderThreadTid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(app.renderThreadTid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
} catch (IllegalArgumentException e) {
// thread died, ignore
}
@@ -21606,10 +21615,10 @@
}
} else {
// Boost priority for top app UI and render threads
- Process.setThreadPriority(app.pid, -10);
+ setThreadPriority(app.pid, -10);
if (app.renderThreadTid != 0) {
try {
- Process.setThreadPriority(app.renderThreadTid, -10);
+ setThreadPriority(app.renderThreadTid, -10);
} catch (IllegalArgumentException e) {
// thread died, ignore
}
@@ -21621,23 +21630,23 @@
// Reset VR thread to SCHED_OTHER
// Safe to do even if we're not in VR mode
if (app.vrThreadTid != 0) {
- Process.setThreadScheduler(app.vrThreadTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(app.vrThreadTid, SCHED_OTHER, 0);
mTopAppVrThreadTid = 0;
}
if (mUseFifoUiScheduling) {
// Reset UI pipeline to SCHED_OTHER
- Process.setThreadScheduler(app.pid, Process.SCHED_OTHER, 0);
- Process.setThreadPriority(app.pid, app.savedPriority);
+ setThreadScheduler(app.pid, SCHED_OTHER, 0);
+ setThreadPriority(app.pid, app.savedPriority);
if (app.renderThreadTid != 0) {
- Process.setThreadScheduler(app.renderThreadTid,
- Process.SCHED_OTHER, 0);
- Process.setThreadPriority(app.renderThreadTid, -4);
+ setThreadScheduler(app.renderThreadTid,
+ SCHED_OTHER, 0);
+ setThreadPriority(app.renderThreadTid, -4);
}
} else {
// Reset priority for top app UI and render threads
- Process.setThreadPriority(app.pid, 0);
+ setThreadPriority(app.pid, 0);
if (app.renderThreadTid != 0) {
- Process.setThreadPriority(app.renderThreadTid, 0);
+ setThreadPriority(app.renderThreadTid, 0);
}
}
}
@@ -22747,7 +22756,7 @@
/** This method sends the specified signal to each of the persistent apps */
public void signalPersistentProcesses(int sig) throws RemoteException {
- if (sig != Process.SIGNAL_USR1) {
+ if (sig != SIGNAL_USR1) {
throw new SecurityException("Only SIGNAL_USR1 is allowed");
}
@@ -22761,7 +22770,7 @@
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
ProcessRecord r = mLruProcesses.get(i);
if (r.thread != null && r.persistent) {
- Process.sendSignal(r.pid, sig);
+ sendSignal(r.pid, sig);
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowContainerController.java b/services/core/java/com/android/server/wm/WindowContainerController.java
index 84ffc35..c4a6837 100644
--- a/services/core/java/com/android/server/wm/WindowContainerController.java
+++ b/services/core/java/com/android/server/wm/WindowContainerController.java
@@ -33,7 +33,7 @@
final WindowManagerService mService;
final RootWindowContainer mRoot;
- final HashMap<IBinder, WindowState> mWindowMap;
+ final WindowHashMap mWindowMap;
// The window container this controller owns.
E mContainer;
diff --git a/services/core/java/com/android/server/wm/WindowHashMap.java b/services/core/java/com/android/server/wm/WindowHashMap.java
new file mode 100644
index 0000000..49bba41
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowHashMap.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.os.IBinder;
+
+import java.util.HashMap;
+
+/**
+ * Subclass of HashMap such that we can instruct the compiler to boost our thread priority when
+ * locking this class. See makefile.
+ */
+class WindowHashMap extends HashMap<IBinder, WindowState> {
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f1796de..1be0512 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
+import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
@@ -25,6 +26,11 @@
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.EXTRA_USER_HANDLE;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.THREAD_PRIORITY_DISPLAY;
+import static android.os.Process.myPid;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.DOCKED_INVALID;
@@ -60,6 +66,8 @@
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.LockGuard.INDEX_WINDOW;
+import static com.android.server.LockGuard.installLock;
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
@@ -125,7 +133,6 @@
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.InputManager;
import android.net.Uri;
-import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -139,7 +146,7 @@
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
-import android.os.Process;
+import android.os.PowerSaveState;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
@@ -151,10 +158,10 @@
import android.os.WorkSource;
import android.provider.Settings;
import android.util.ArraySet;
-import android.util.MergedConfiguration;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.MergedConfiguration;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -215,7 +222,7 @@
import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.LocalServices;
-import com.android.server.LockGuard;
+import com.android.server.ThreadPriorityBooster;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.input.InputManagerService;
@@ -239,10 +246,7 @@
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
-import java.util.HashMap;
import java.util.List;
-
-import static android.Manifest.permission.READ_FRAME_BUFFER;
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
@@ -408,7 +412,7 @@
* This is also used as the lock for all of our state.
* NOTE: Never call into methods that lock ActivityManagerService while holding this object.
*/
- final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
+ final WindowHashMap mWindowMap = new WindowHashMap();
/**
* List of window tokens that have finished starting their application,
@@ -848,6 +852,16 @@
// since they won't be notified through the app window animator.
final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
+ private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
+ THREAD_PRIORITY_DISPLAY, INDEX_WINDOW);
+
+ static void boostPriorityForLockedSection() {
+ sThreadPriorityBooster.boost();
+ }
+
+ static void resetPriorityAfterLockedSection() {
+ sThreadPriorityBooster.reset();
+ }
void openSurfaceTransaction() {
synchronized (mWindowMap) {
@@ -936,7 +950,7 @@
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy) {
- LockGuard.installLock(this, LockGuard.INDEX_WINDOW);
+ installLock(this, INDEX_WINDOW);
mRoot = new RootWindowContainer(this);
mContext = context;
mHaveInputMethods = haveInputMethods;
@@ -1581,7 +1595,7 @@
@Override
public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
final int callingUid = Binder.getCallingUid();
- if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
+ if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
throw new SecurityException("Only shell can call enableSurfaceTrace");
}
@@ -1593,8 +1607,8 @@
@Override
public void disableSurfaceTrace() {
final int callingUid = Binder.getCallingUid();
- if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID &&
- callingUid != Process.SYSTEM_UID) {
+ if (callingUid != SHELL_UID && callingUid != ROOT_UID &&
+ callingUid != SYSTEM_UID) {
throw new SecurityException("Only shell can call disableSurfaceTrace");
}
synchronized (mWindowMap) {
@@ -1608,7 +1622,7 @@
@Override
public void setScreenCaptureDisabled(int userId, boolean disabled) {
int callingUid = Binder.getCallingUid();
- if (callingUid != Process.SYSTEM_UID) {
+ if (callingUid != SYSTEM_UID) {
throw new SecurityException("Only system can call setScreenCaptureDisabled.");
}
@@ -2264,7 +2278,7 @@
boolean checkCallingPermission(String permission, String func) {
// Quick check: if the calling permission is me, it's all okay.
- if (Binder.getCallingPid() == Process.myPid()) {
+ if (Binder.getCallingPid() == myPid()) {
return true;
}
@@ -2917,7 +2931,7 @@
}
// If this isn't coming from the system then don't allow disabling the lockscreen
// to bypass security.
- if (Binder.getCallingUid() != Process.SYSTEM_UID && isKeyguardSecure()) {
+ if (Binder.getCallingUid() != SYSTEM_UID && isKeyguardSecure()) {
Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
return;
}
@@ -7058,7 +7072,7 @@
throw new IllegalStateException("Magnification callbacks not set!");
}
}
- if (Binder.getCallingPid() != android.os.Process.myPid()) {
+ if (Binder.getCallingPid() != myPid()) {
spec.recycle();
}
}
diff --git a/tests/WindowManagerStressTest/Android.mk b/tests/WindowManagerStressTest/Android.mk
new file mode 100644
index 0000000..e4cbe93
--- /dev/null
+++ b/tests/WindowManagerStressTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := WindowManagerStressTest
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/WindowManagerStressTest/AndroidManifest.xml b/tests/WindowManagerStressTest/AndroidManifest.xml
new file mode 100644
index 0000000..17e0f15
--- /dev/null
+++ b/tests/WindowManagerStressTest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.windowmanagerstresstest">
+
+ <application
+ android:allowBackup="false"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+ <activity android:name=".MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/WindowManagerStressTest/res/layout/activity_main.xml b/tests/WindowManagerStressTest/res/layout/activity_main.xml
new file mode 100644
index 0000000..6cf8269
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/layout/activity_main.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="test.amslam.MainActivity">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/run"
+ android:text="@string/run" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/output" />
+
+</LinearLayout>
diff --git a/tests/WindowManagerStressTest/res/mipmap-hdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-mdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-xhdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-xxhdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-xxxhdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/values/colors.xml b/tests/WindowManagerStressTest/res/values/colors.xml
new file mode 100644
index 0000000..4270ca6
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <color name="colorPrimary">#3F51B5</color>
+ <color name="colorPrimaryDark">#303F9F</color>
+ <color name="colorAccent">#FF4081</color>
+</resources>
diff --git a/tests/WindowManagerStressTest/res/values/dimens.xml b/tests/WindowManagerStressTest/res/values/dimens.xml
new file mode 100644
index 0000000..ed4ccbc
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/dimens.xml
@@ -0,0 +1,19 @@
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/tests/WindowManagerStressTest/res/values/strings.xml b/tests/WindowManagerStressTest/res/values/strings.xml
new file mode 100644
index 0000000..cef05dc
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+ <string name="app_name">WmSlam</string>
+ <string name="run">Run</string>
+</resources>
diff --git a/tests/WindowManagerStressTest/res/values/styles.xml b/tests/WindowManagerStressTest/res/values/styles.xml
new file mode 100644
index 0000000..0983b25
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/styles.xml
@@ -0,0 +1,23 @@
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="android:colorPrimary">@color/colorPrimary</item>
+ <item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="android:colorAccent">@color/colorAccent</item>
+ </style>
+</resources>
diff --git a/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
new file mode 100644
index 0000000..6b9bb31
--- /dev/null
+++ b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package test.windowmanagerstresstest;
+
+import android.app.Activity;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.MergedConfiguration;
+import android.view.Display;
+import android.view.IWindowSession;
+import android.view.Surface;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerGlobal;
+import android.widget.TextView;
+
+import com.android.internal.view.BaseIWindow;
+
+import java.util.ArrayList;
+
+public class MainActivity extends Activity {
+
+ private static final String TAG = "WmSlam";
+
+ private TextView mOutput;
+ private volatile boolean finished;
+ private final ArrayList<BaseIWindow> mWindows = new ArrayList<>();
+ private final LayoutParams mLayoutParams = new LayoutParams();
+ private final Rect mTmpRect = new Rect();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ mOutput = (TextView) findViewById(R.id.output);
+
+ findViewById(R.id.run).setOnClickListener(view -> {
+ view.setEnabled(false);
+ mOutput.setText("");
+ startBatch();
+ });
+ mLayoutParams.token = getActivityToken();
+ }
+
+ void startBatch() {
+ new Thread(() -> {
+ finished = false;
+ addWindows();
+ startCpuRunnables();
+ for (int i = 0; i < 5; i++) {
+ final long time = SystemClock.uptimeMillis();
+ slamWm();
+ log("Total: " + (SystemClock.uptimeMillis() - time) + " ms");
+ }
+ removeWindows();
+ finished = true;
+ }).start();
+ }
+
+ void startCpuRunnables() {
+ for (int i = 0; i < 10; i++) {
+ new Thread(mUseCpuRunnable).start();
+ }
+ }
+
+ private final Runnable mUseCpuRunnable = new Runnable() {
+ @Override
+ public void run() {
+ while (!finished) {
+ }
+ }
+ };
+
+ private void log(String text) {
+ mOutput.post(() -> mOutput.append(text + "\n"));
+ Log.d(TAG, text);
+ }
+
+ private void slamWm() {
+ ArrayList<Thread> threads = new ArrayList<>();
+ for (int i = 0; i < 20; i++) {
+ for (BaseIWindow window : mWindows) {
+ Thread t = new Thread(() -> {
+ try {
+ WindowManagerGlobal.getWindowSession().relayout(window,
+ window.mSeq, mLayoutParams, -1, -1, View.VISIBLE, 0, mTmpRect,
+ mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect,
+ new MergedConfiguration(), new Surface());
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ });
+ threads.add(t);
+ t.start();
+ }
+ }
+ for (Thread t : threads) {
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ void addWindows() {
+ for (int i = 0; i < 50; i++) {
+ final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
+ layoutParams.token = getActivityToken();
+ final BaseIWindow window = new BaseIWindow();
+ final IWindowSession session = WindowManagerGlobal.getWindowSession();
+ final Rect tmpRect = new Rect();
+ try {
+ final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq, layoutParams,
+ View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ mWindows.add(window);
+ }
+ }
+
+ void removeWindows() {
+ for (BaseIWindow window : mWindows) {
+ try {
+ WindowManagerGlobal.getWindowSession().remove(window);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}