diff options
Diffstat (limited to 'services')
14 files changed, 414 insertions, 199 deletions
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index b70a34e..5ae9a6d 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -577,16 +577,14 @@ class AlarmManagerService extends IAlarmManager.Stub { operation, workSource); removeLocked(operation); - boolean reschedule; int whichBatch = (isStandalone) ? -1 : attemptCoalesceLocked(whenElapsed, maxWhen); if (whichBatch < 0) { Batch batch = new Batch(a); batch.standalone = isStandalone; - reschedule = addBatchLocked(mAlarmBatches, batch); + addBatchLocked(mAlarmBatches, batch); } else { Batch batch = mAlarmBatches.get(whichBatch); - reschedule = batch.add(a); - if (reschedule) { + if (batch.add(a)) { // The start time of this batch advanced, so batch ordering may // have just been broken. Move it to where it now belongs. mAlarmBatches.remove(whichBatch); @@ -602,13 +600,10 @@ class AlarmManagerService extends IAlarmManager.Stub { + " interval=" + interval + " op=" + operation + " standalone=" + isStandalone); rebatchAllAlarmsLocked(false); - reschedule = true; } } - if (reschedule) { - rescheduleKernelAlarmsLocked(); - } + rescheduleKernelAlarmsLocked(); } private void logBatchesLocked() { diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 794d274..562a50f 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -879,8 +879,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final boolean isScreenSecurelyLocked = isScreenLocked && mKeyguardManager.isKeyguardSecure(); final boolean inputShown = mInputShown && (!isScreenLocked || mInputBoundToKeyguard); - mImeWindowVis = (!isScreenSecurelyLocked && (inputShown || hardKeyShown)) ? - (InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE) : 0; + final boolean inputActive = !isScreenSecurelyLocked && (inputShown || hardKeyShown); + // We assume the softkeyboard is shown when the input is active as long as the + // hard keyboard is not shown. + final boolean inputVisible = inputActive && !hardKeyShown; + mImeWindowVis = (inputActive ? InputMethodService.IME_ACTIVE : 0) + | (inputVisible ? InputMethodService.IME_VISIBLE : 0); updateImeWindowStatusLocked(); } diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java index dfffd2e..e17f42d 100644 --- a/services/java/com/android/server/Watchdog.java +++ b/services/java/com/android/server/Watchdog.java @@ -58,7 +58,14 @@ public class Watchdog extends Thread { // Set this to true to have the watchdog record kernel thread stacks when it fires static final boolean RECORD_KERNEL_THREADS = true; - static final int TIME_TO_WAIT = DB ? 5*1000 : 30*1000; + static final long DEFAULT_TIMEOUT = DB ? 10*1000 : 60*1000; + static final long CHECK_INTERVAL = DEFAULT_TIMEOUT / 2; + + // These are temporally ordered: larger values as lateness increases + static final int COMPLETED = 0; + static final int WAITING = 1; + static final int WAITED_HALF = 2; + static final int OVERDUE = 3; // Which native processes to dump into dropbox's stack traces public static final String[] NATIVE_STACKS_OF_INTEREST = new String[] { @@ -88,13 +95,17 @@ public class Watchdog extends Thread { public final class HandlerChecker implements Runnable { private final Handler mHandler; private final String mName; + private final long mWaitMax; private final ArrayList<Monitor> mMonitors = new ArrayList<Monitor>(); private boolean mCompleted; private Monitor mCurrentMonitor; + private long mStartTime; - HandlerChecker(Handler handler, String name) { + HandlerChecker(Handler handler, String name, long waitMaxMillis) { mHandler = handler; mName = name; + mWaitMax = waitMaxMillis; + mCompleted = true; } public void addMonitor(Monitor monitor) { @@ -112,13 +123,34 @@ public class Watchdog extends Thread { mCompleted = true; return; } + + if (!mCompleted) { + // we already have a check in flight, so no need + return; + } + mCompleted = false; mCurrentMonitor = null; + mStartTime = SystemClock.uptimeMillis(); mHandler.postAtFrontOfQueue(this); } - public boolean isCompletedLocked() { - return mCompleted; + public boolean isOverdueLocked() { + return (!mCompleted) && (SystemClock.uptimeMillis() > mStartTime + mWaitMax); + } + + public int getCompletionStateLocked() { + if (mCompleted) { + return COMPLETED; + } else { + long latency = SystemClock.uptimeMillis() - mStartTime; + if (latency < mWaitMax/2) { + return WAITING; + } else if (latency < mWaitMax) { + return WAITED_HALF; + } + } + return OVERDUE; } public Thread getThread() { @@ -187,16 +219,19 @@ public class Watchdog extends Thread { // The shared foreground thread is the main checker. It is where we // will also dispatch monitor checks and do other work. - mMonitorChecker = new HandlerChecker(FgThread.getHandler(), "foreground thread"); + mMonitorChecker = new HandlerChecker(FgThread.getHandler(), + "foreground thread", DEFAULT_TIMEOUT); mHandlerCheckers.add(mMonitorChecker); // Add checker for main thread. We only do a quick check since there // can be UI running on the thread. mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()), - "main thread")); + "main thread", DEFAULT_TIMEOUT)); // Add checker for shared UI thread. - mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(), "ui thread")); + mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(), + "ui thread", DEFAULT_TIMEOUT)); // And also check IO thread. - mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(), "i/o thread")); + mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(), + "i/o thread", DEFAULT_TIMEOUT)); } public void init(Context context, BatteryService battery, @@ -243,11 +278,15 @@ public class Watchdog extends Thread { } public void addThread(Handler thread, String name) { + addThread(thread, name, DEFAULT_TIMEOUT); + } + + public void addThread(Handler thread, String name, long timeoutMillis) { synchronized (this) { if (isAlive()) { throw new RuntimeException("Threads can't be added once the Watchdog is running"); } - mHandlerCheckers.add(new HandlerChecker(thread, name)); + mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis)); } } @@ -260,21 +299,20 @@ public class Watchdog extends Thread { pms.reboot(false, reason, false); } - private boolean haveAllCheckersCompletedLocked() { + private int evaluateCheckerCompletionLocked() { + int state = COMPLETED; for (int i=0; i<mHandlerCheckers.size(); i++) { HandlerChecker hc = mHandlerCheckers.get(i); - if (!hc.isCompletedLocked()) { - return false; - } + state = Math.max(state, hc.getCompletionStateLocked()); } - return true; + return state; } private ArrayList<HandlerChecker> getBlockedCheckersLocked() { ArrayList<HandlerChecker> checkers = new ArrayList<HandlerChecker>(); for (int i=0; i<mHandlerCheckers.size(); i++) { HandlerChecker hc = mHandlerCheckers.get(i); - if (!hc.isCompletedLocked()) { + if (hc.isOverdueLocked()) { checkers.add(hc); } } @@ -300,14 +338,12 @@ public class Watchdog extends Thread { final String subject; final boolean allowRestart; synchronized (this) { - long timeout = TIME_TO_WAIT; - if (!waitedHalf) { - // If we are not at the half-point of waiting, perform a - // new set of checks. Otherwise we are still waiting for a previous set. - for (int i=0; i<mHandlerCheckers.size(); i++) { - HandlerChecker hc = mHandlerCheckers.get(i); - hc.scheduleCheckLocked(); - } + long timeout = CHECK_INTERVAL; + // Make sure we (re)spin the checkers that have become idle within + // this wait-and-check interval + for (int i=0; i<mHandlerCheckers.size(); i++) { + HandlerChecker hc = mHandlerCheckers.get(i); + hc.scheduleCheckLocked(); } // NOTE: We use uptimeMillis() here because we do not want to increment the time we @@ -321,26 +357,31 @@ public class Watchdog extends Thread { } catch (InterruptedException e) { Log.wtf(TAG, e); } - timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start); + timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start); } - if (haveAllCheckersCompletedLocked()) { - // The monitors have returned. + final int waitState = evaluateCheckerCompletionLocked(); + if (waitState == COMPLETED) { + // The monitors have returned; reset waitedHalf = false; continue; - } - - if (!waitedHalf) { - // We've waited half the deadlock-detection interval. Pull a stack - // trace and wait another half. - ArrayList<Integer> pids = new ArrayList<Integer>(); - pids.add(Process.myPid()); - ActivityManagerService.dumpStackTraces(true, pids, null, null, - NATIVE_STACKS_OF_INTEREST); - waitedHalf = true; + } else if (waitState == WAITING) { + // still waiting but within their configured intervals; back off and recheck + continue; + } else if (waitState == WAITED_HALF) { + if (!waitedHalf) { + // We've waited half the deadlock-detection interval. Pull a stack + // trace and wait another half. + ArrayList<Integer> pids = new ArrayList<Integer>(); + pids.add(Process.myPid()); + ActivityManagerService.dumpStackTraces(true, pids, null, null, + NATIVE_STACKS_OF_INTEREST); + waitedHalf = true; + } continue; } + // something is overdue! blockedCheckers = getBlockedCheckersLocked(); subject = describeCheckersLocked(blockedCheckers); allowRestart = mAllowRestart; diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index e7ddd80..d75fe5e 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -7229,7 +7229,13 @@ public final class ActivityManagerService extends ActivityManagerNative if (DEBUG_MU) Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid); app.pubProviders.put(cpi.name, cpr); - app.addPackage(cpi.applicationInfo.packageName, mProcessStats); + if (!cpi.multiprocess || !"android".equals(cpi.packageName)) { + // Don't add this if it is a platform component that is marked + // to run in multiple processes, because this is actually + // part of the framework so doesn't make sense to track as a + // separate apk in the process. + app.addPackage(cpi.applicationInfo.packageName, mProcessStats); + } ensurePackageDexOpt(cpi.applicationInfo.packageName); } } @@ -11503,7 +11509,6 @@ public final class ActivityManagerService extends ActivityManagerNative try { pid = Integer.parseInt(args[start]); } catch (NumberFormatException e) { - } for (int i=mLruProcesses.size()-1; i>=0; i--) { ProcessRecord proc = mLruProcesses.get(i); @@ -11514,7 +11519,6 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (procs.size() <= 0) { - pw.println("No process found for: " + args[start]); return null; } } else { @@ -11528,6 +11532,7 @@ public final class ActivityManagerService extends ActivityManagerNative PrintWriter pw, String[] args) { ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args); if (procs == null) { + pw.println("No process found for: " + args[0]); return; } @@ -11563,6 +11568,7 @@ public final class ActivityManagerService extends ActivityManagerNative final void dumpDbInfo(FileDescriptor fd, PrintWriter pw, String[] args) { ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args); if (procs == null) { + pw.println("No process found for: " + args[0]); return; } @@ -11709,6 +11715,17 @@ public final class ActivityManagerService extends ActivityManagerNative "prev", "serviceb", "cached" }; + private final void dumpApplicationMemoryUsageHeader(PrintWriter pw, long uptime, + long realtime, boolean isCheckinRequest, boolean isCompact) { + if (isCheckinRequest || isCompact) { + // short checkin version + pw.print("time,"); pw.print(uptime); pw.print(","); pw.println(realtime); + } else { + pw.println("Applications Memory Usage (kB):"); + pw.println("Uptime: " + uptime + " Realtime: " + realtime); + } + } + final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix, String[] args, boolean brief, PrintWriter categoryPw) { boolean dumpDetails = false; @@ -11748,26 +11765,71 @@ public final class ActivityManagerService extends ActivityManagerNative } } + final boolean isCheckinRequest = scanArgs(args, "--checkin"); + long uptime = SystemClock.uptimeMillis(); + long realtime = SystemClock.elapsedRealtime(); + final long[] tmpLong = new long[1]; + ArrayList<ProcessRecord> procs = collectProcesses(pw, opti, args); if (procs == null) { + // No Java processes. Maybe they want to print a native process. + if (args != null && args.length > opti + && args[opti].charAt(0) != '-') { + ArrayList<ProcessCpuTracker.Stats> nativeProcs + = new ArrayList<ProcessCpuTracker.Stats>(); + updateCpuStatsNow(); + int findPid = -1; + try { + findPid = Integer.parseInt(args[opti]); + } catch (NumberFormatException e) { + } + synchronized (mProcessCpuThread) { + final int N = mProcessCpuTracker.countStats(); + for (int i=0; i<N; i++) { + ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); + if (st.pid == findPid || (st.baseName != null + && st.baseName.equals(args[opti]))) { + nativeProcs.add(st); + } + } + } + if (nativeProcs.size() > 0) { + dumpApplicationMemoryUsageHeader(pw, uptime, realtime, isCheckinRequest, + isCompact); + Debug.MemoryInfo mi = null; + for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) { + final ProcessCpuTracker.Stats r = nativeProcs.get(i); + final int pid = r.pid; + if (!isCheckinRequest && dumpDetails) { + pw.println("\n** MEMINFO in pid " + pid + " [" + r.baseName + "] **"); + } + if (mi == null) { + mi = new Debug.MemoryInfo(); + } + if (dumpDetails || (!brief && !oomOnly)) { + Debug.getMemoryInfo(pid, mi); + } else { + mi.dalvikPss = (int)Debug.getPss(pid, tmpLong); + mi.dalvikPrivateDirty = (int)tmpLong[0]; + } + ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails, + dumpDalvik, pid, r.baseName, 0, 0, 0, 0, 0, 0); + if (isCheckinRequest) { + pw.println(); + } + } + return; + } + } + pw.println("No process found for: " + args[opti]); return; } - final boolean isCheckinRequest = scanArgs(args, "--checkin"); - long uptime = SystemClock.uptimeMillis(); - long realtime = SystemClock.elapsedRealtime(); - if (!brief && !oomOnly && (procs.size() == 1 || isCheckinRequest)) { dumpDetails = true; } - if (isCheckinRequest || isCompact) { - // short checkin version - pw.print("time,"); pw.print(uptime); pw.print(","); pw.println(realtime); - } else { - pw.println("Applications Memory Usage (kB):"); - pw.println("Uptime: " + uptime + " Realtime: " + realtime); - } + dumpApplicationMemoryUsageHeader(pw, uptime, realtime, isCheckinRequest, isCompact); String[] innerArgs = new String[args.length-opti]; System.arraycopy(args, opti, innerArgs, 0, args.length-opti); @@ -11780,7 +11842,6 @@ public final class ActivityManagerService extends ActivityManagerNative long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length]; ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[]) new ArrayList[DUMP_MEM_OOM_LABEL.length]; - final long[] tmpLong = new long[1]; long totalPss = 0; long cachedPss = 0; @@ -12367,7 +12428,6 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); - checkValidCaller(callingUid, userId); final long origId = Binder.clearCallingIdentity(); ComponentName res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, userId); @@ -12397,8 +12457,6 @@ public final class ActivityManagerService extends ActivityManagerNative throw new IllegalArgumentException("File descriptors passed in Intent"); } - checkValidCaller(Binder.getCallingUid(), userId); - synchronized(this) { return mServices.stopServiceLocked(caller, service, resolvedType, userId); } @@ -12783,7 +12841,8 @@ public final class ActivityManagerService extends ActivityManagerNative + ") when registering receiver " + receiver); } if (callerApp.info.uid != Process.SYSTEM_UID && - !callerApp.pkgList.containsKey(callerPackage)) { + !callerApp.pkgList.containsKey(callerPackage) && + !"android".equals(callerPackage)) { throw new SecurityException("Given caller package " + callerPackage + " is not running in process " + callerApp); } @@ -16388,13 +16447,6 @@ public final class ActivityManagerService extends ActivityManagerNative return mUserManager; } - private void checkValidCaller(int uid, int userId) { - if (UserHandle.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0) return; - - throw new SecurityException("Caller uid=" + uid - + " is not privileged to communicate with user=" + userId); - } - private int applyUserId(int uid, int userId) { return UserHandle.getUid(userId, uid); } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 22daaf3..2e5dedf 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -740,7 +740,10 @@ final class ActivityStack { prev.state = ActivityState.PAUSING; prev.task.touchActiveTime(); clearLaunchTime(prev); - prev.updateThumbnail(screenshotActivities(prev), null); + final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(); + if (next == null || next.task != prev.task) { + prev.updateThumbnail(screenshotActivities(prev), null); + } stopFullyDrawnTraceIfNeeded(); mService.updateCpuStats(); @@ -977,6 +980,40 @@ final class ActivityStack { } /** + * Determine if home should be visible below the passed record. + * @param record activity we are querying for. + * @return true if home is visible below the passed activity, false otherwise. + */ + boolean isActivityOverHome(ActivityRecord record) { + // Start at record and go down, look for either home or a visible fullscreen activity. + final TaskRecord recordTask = record.task; + for (int taskNdx = mTaskHistory.indexOf(recordTask); taskNdx >= 0; --taskNdx) { + TaskRecord task = mTaskHistory.get(taskNdx); + final ArrayList<ActivityRecord> activities = task.mActivities; + final int startNdx = + task == recordTask ? activities.indexOf(record) : activities.size() - 1; + for (int activityNdx = startNdx; activityNdx >= 0; --activityNdx) { + final ActivityRecord r = activities.get(activityNdx); + if (r.isHomeActivity()) { + return true; + } + if (!r.finishing && r.visible && r.fullscreen) { + // Passed activity is over a visible fullscreen activity. + return false; + } + } + if (task.mOnTopOfHome) { + // Got to the bottom of a task on top of home without finding a visible fullscreen + // activity. Home is visible. + return true; + } + } + // Got to the bottom of this stack and still don't know. If this is over the home stack + // then record is over home. May not work if we ever get more than two layers. + return mStackSupervisor.isFrontStack(this); + } + + /** * Version of ensureActivitiesVisible that can easily be called anywhere. */ final boolean ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) { @@ -1101,24 +1138,10 @@ final class ActivityStack { // At this point, nothing else needs to be shown if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r); behindFullscreen = true; - } else if (task.mOnTopOfHome) { - // Work our way down from r to bottom of task and see if there are any - // visible activities below r. - int rIndex = task.mActivities.indexOf(r); - for ( --rIndex; rIndex >= 0; --rIndex) { - final ActivityRecord blocker = task.mActivities.get(rIndex); - if (!blocker.finishing) { - if (DEBUG_VISBILITY) Slog.v(TAG, "Home visibility for " + - r + " blocked by " + blocker); - break; - } - } - if (rIndex < 0) { - // Got to task bottom without finding a visible activity, show home. - if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r); - showHomeBehindStack = true; - behindFullscreen = true; - } + } else if (isActivityOverHome(r)) { + if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r); + showHomeBehindStack = true; + behindFullscreen = true; } } else { if (DEBUG_VISBILITY) Slog.v( diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index 14312b6..7650a65 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -1051,7 +1051,14 @@ public final class ActivityStackSupervisor { if (app != null && app.thread != null) { try { - app.addPackage(r.info.packageName, mService.mProcessStats); + if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 + || !"android".equals(r.info.packageName)) { + // Don't add this if it is a platform component that is marked + // to run in multiple processes, because this is actually + // part of the framework so doesn't make sense to track as a + // separate apk in the process. + app.addPackage(r.info.packageName, mService.mProcessStats); + } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { @@ -1464,13 +1471,13 @@ public final class ActivityStackSupervisor { // We really do want to push this one into the // user's face, right now. movedHome = true; + targetStack.moveTaskToFrontLocked(intentActivity.task, r, options); if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity. intentActivity.task.mOnTopOfHome = true; } - targetStack.moveTaskToFrontLocked(intentActivity.task, r, options); options = null; } } diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java index 50a7b5c..8d16880 100644 --- a/services/java/com/android/server/am/ProcessStatsService.java +++ b/services/java/com/android/server/am/ProcessStatsService.java @@ -529,6 +529,33 @@ public final class ProcessStatsService extends IProcessStats.Stub { } } + private void dumpAggregatedStats(PrintWriter pw, long aggregateHours, long now, + String reqPackage, boolean isCompact, boolean dumpDetails, boolean dumpFullDetails, + boolean dumpAll, boolean activeOnly) { + ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000 + - (ProcessStats.COMMIT_PERIOD/2)); + if (pfd == null) { + pw.println("Unable to build stats!"); + return; + } + ProcessStats stats = new ProcessStats(false); + InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + stats.read(stream); + if (stats.mReadError != null) { + pw.print("Failure reading: "); pw.println(stats.mReadError); + return; + } + if (isCompact) { + stats.dumpCheckinLocked(pw, reqPackage); + } else { + if (dumpDetails || dumpFullDetails) { + stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly); + } else { + stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly); + } + } + } + static private void dumpHelp(PrintWriter pw) { pw.println("Process stats (procstats) dump options:"); pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]"); @@ -789,28 +816,8 @@ public final class ProcessStatsService extends IProcessStats.Stub { } return; } else if (aggregateHours != 0) { - ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000 - - (ProcessStats.COMMIT_PERIOD/2)); - if (pfd == null) { - pw.println("Unable to build stats!"); - return; - } - ProcessStats stats = new ProcessStats(false); - InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd); - stats.read(stream); - if (stats.mReadError != null) { - pw.print("Failure reading: "); pw.println(stats.mReadError); - return; - } - if (isCompact) { - stats.dumpCheckinLocked(pw, reqPackage); - } else { - if (dumpDetails || dumpFullDetails) { - stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly); - } else { - stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly); - } - } + dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact, + dumpDetails, dumpFullDetails, dumpAll, activeOnly); return; } @@ -875,6 +882,19 @@ public final class ProcessStatsService extends IProcessStats.Stub { } } if (!isCheckin) { + if (dumpAll) { + if (sepNeeded) { + pw.println(); + pw.println("AGGREGATED OVER LAST 24 HOURS:"); + } + dumpAggregatedStats(pw, 24, now, reqPackage, isCompact, + dumpDetails, dumpFullDetails, dumpAll, activeOnly); + pw.println(); + pw.println("AGGREGATED OVER LAST 3 HOURS:"); + dumpAggregatedStats(pw, 3, now, reqPackage, isCompact, + dumpDetails, dumpFullDetails, dumpAll, activeOnly); + sepNeeded = true; + } synchronized (mAm) { if (isCompact) { mProcessStats.dumpCheckinLocked(pw, reqPackage); diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index e075862..a781d5f 100755 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -221,6 +221,14 @@ public class PackageManagerService extends IPackageManager.Stub { static final int REMOVE_CHATTY = 1<<16; /** + * Timeout (in milliseconds) after which the watchdog should declare that + * our handler thread is wedged. The usual default for such things is one + * minute but we sometimes do very lengthy I/O operations on this thread, + * such as installing multi-gigabyte applications, so ours needs to be longer. + */ + private static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes + + /** * Whether verification is enabled by default. */ private static final boolean DEFAULT_VERIFY_ENABLE = true; @@ -1115,7 +1123,8 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { mHandlerThread.start(); mHandler = new PackageHandler(mHandlerThread.getLooper()); - Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName()); + Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName(), + WATCHDOG_TIMEOUT); File dataDir = Environment.getDataDirectory(); mAppDataDir = new File(dataDir, "data"); diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java index b0cfd7e..d3ccba6 100644 --- a/services/java/com/android/server/pm/Settings.java +++ b/services/java/com/android/server/pm/Settings.java @@ -2070,8 +2070,10 @@ final class Settings { if (intent.getAction() != null) { filter.addAction(intent.getAction()); } - for (String cat : intent.getCategories()) { - filter.addCategory(cat); + if (intent.getCategories() != null) { + for (String cat : intent.getCategories()) { + filter.addCategory(cat); + } } if ((flags&PackageManager.MATCH_DEFAULT_ONLY) != 0) { filter.addCategory(Intent.CATEGORY_DEFAULT); @@ -2088,6 +2090,13 @@ final class Settings { if (path != null) { filter.addDataPath(path); } + if (intent.getType() != null) { + try { + filter.addDataType(intent.getType()); + } catch (IntentFilter.MalformedMimeTypeException ex) { + Slog.w(TAG, "Malformed mimetype " + intent.getType() + " for " + cn); + } + } PreferredActivity pa = new PreferredActivity(filter, match, set, cn, true); editPreferredActivitiesLPw(userId).addFilter(pa); } else if (!haveNonSys) { diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java index 8fbde14..da9548f 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/java/com/android/server/power/PowerManagerService.java @@ -747,6 +747,21 @@ public final class PowerManagerService extends IPowerManager.Stub } @Override // Binder call + public void updateWakeLockUids(IBinder lock, int[] uids) { + WorkSource ws = null; + + if (uids != null) { + ws = new WorkSource(); + // XXX should WorkSource have a way to set uids as an int[] instead of adding them + // one at a time? + for (int i = 0; i < uids.length; i++) { + ws.add(uids[i]); + } + } + updateWakeLockWorkSource(lock, ws); + } + + @Override // Binder call public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) { if (lock == null) { throw new IllegalArgumentException("lock must not be null"); diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java index b69dcee..f23a992 100644 --- a/services/java/com/android/server/print/UserState.java +++ b/services/java/com/android/server/print/UserState.java @@ -231,10 +231,10 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks { for (int i = 0; i < cachedPrintJobCount; i++) { PrintJobInfo cachedPrintJob = cachedPrintJobs.get(i); result.put(cachedPrintJob.getId(), cachedPrintJob); - // Strip out the tag - it is visible only to print services. - // Also the cached print jobs are delivered only to apps, so - // stripping the tag of a cached print job is fine. + // Strip out the tag and the advanced print options. + // They are visible only to print services. cachedPrintJob.setTag(null); + cachedPrintJob.setAdvancedOptions(null); } // Add everything else the spooler knows about. @@ -245,8 +245,10 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks { for (int i = 0; i < printJobCount; i++) { PrintJobInfo printJob = printJobs.get(i); result.put(printJob.getId(), printJob); - // Strip out the tag - it is visible only to print services. + // Strip out the tag and the advanced print options. + // They are visible only to print services. printJob.setTag(null); + printJob.setAdvancedOptions(null); } } @@ -255,10 +257,16 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks { public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) { PrintJobInfo printJob = mPrintJobForAppCache.getPrintJob(printJobId, appId); + if (printJob == null) { + printJob = mSpooler.getPrintJobInfo(printJobId, appId); + } if (printJob != null) { - return printJob; + // Strip out the tag and the advanced print options. + // They are visible only to print services. + printJob.setTag(null); + printJob.setAdvancedOptions(null); } - return mSpooler.getPrintJobInfo(printJobId, appId); + return printJob; } public void cancelPrintJob(PrintJobId printJobId, int appId) { diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java index afa4f78..52f2325 100644 --- a/services/java/com/android/server/wm/DisplayContent.java +++ b/services/java/com/android/server/wm/DisplayContent.java @@ -107,7 +107,7 @@ class DisplayContent { Region mTouchExcludeRegion = new Region(); /** Save allocating when retrieving tasks */ - ArrayList<Task> mTmpTasks = new ArrayList<Task>(); + ArrayList<Task> mTaskHistory = new ArrayList<Task>(); /** Save allocating when calculating rects */ Rect mTmpRect = new Rect(); @@ -163,7 +163,7 @@ class DisplayContent { void moveStack(TaskStack stack, boolean toTop) { mStackHistory.remove(stack); mStackHistory.add(toTop ? mStackHistory.size() : 0, stack); - mService.moveStackWindowsLocked(stack); + mService.moveStackWindowsLocked(this); } public boolean isPrivate() { @@ -175,14 +175,35 @@ class DisplayContent { * @return All the Tasks, in order, on this display. */ ArrayList<Task> getTasks() { - mTmpTasks.clear(); - final int numStacks = mStackHistory.size(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - mTmpTasks.addAll(mStackHistory.get(stackNdx).getTasks()); + return mTaskHistory; + } + + void addTask(Task task, boolean toTop) { + mTaskHistory.remove(task); + + final int userId = task.mUserId; + int taskNdx; + final int numTasks = mTaskHistory.size(); + if (toTop) { + for (taskNdx = numTasks - 1; taskNdx >= 0; --taskNdx) { + if (mTaskHistory.get(taskNdx).mUserId == userId) { + break; + } + } + ++taskNdx; + } else { + for (taskNdx = 0; taskNdx < numTasks; ++taskNdx) { + if (mTaskHistory.get(taskNdx).mUserId == userId) { + break; + } + } } - if (WindowManagerService.DEBUG_LAYERS) Slog.i(TAG, "getTasks: mStackHistory=" + - mStackHistory); - return mTmpTasks; + + mTaskHistory.add(taskNdx, task); + } + + void removeTask(Task task) { + mTaskHistory.remove(task); } TaskStack getHomeStack() { @@ -205,10 +226,9 @@ class DisplayContent { /** @return The number of tokens in all of the Tasks on this display. */ int numTokens() { - getTasks(); int count = 0; - for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) { - count += mTmpTasks.get(taskNdx).mAppTokens.size(); + for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { + count += mTaskHistory.get(taskNdx).mAppTokens.size(); } return count; } @@ -469,8 +489,8 @@ class DisplayContent { pw.println(); pw.println(" Application tokens in Z order:"); getTasks(); - for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) { - AppTokenList tokens = mTmpTasks.get(taskNdx).mAppTokens; + for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { + AppTokenList tokens = mTaskHistory.get(taskNdx).mAppTokens; for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { final AppWindowToken wtoken = tokens.get(tokenNdx); pw.print(" App #"); pw.print(ndx--); diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java index 2347a19..34bef68 100644 --- a/services/java/com/android/server/wm/TaskStack.java +++ b/services/java/com/android/server/wm/TaskStack.java @@ -120,6 +120,7 @@ public class TaskStack { mTasks.add(stackNdx, task); task.mStack = this; + mDisplayContent.addTask(task, toTop); return mDisplayContent.moveHomeStackBox(mStackId == HOME_STACK_ID); } @@ -145,6 +146,7 @@ public class TaskStack { if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "removeTask: task=" + task); mStackBox.makeDirty(); mTasks.remove(task); + mDisplayContent.removeTask(task); } int remove() { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index f2a0cbd..63e09db 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -4733,11 +4733,9 @@ public class WindowManagerService extends IWindowManager.Stub return index; } - void moveStackWindowsLocked(TaskStack stack) { - DisplayContent displayContent = stack.getDisplayContent(); - + void moveStackWindowsLocked(DisplayContent displayContent) { // First remove all of the windows from the list. - final ArrayList<Task> tasks = stack.getTasks(); + final ArrayList<Task> tasks = displayContent.getTasks(); final int numTasks = tasks.size(); for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { AppTokenList tokens = tasks.get(taskNdx).mAppTokens; @@ -4813,7 +4811,7 @@ public class WindowManagerService extends IWindowManager.Stub } final TaskStack stack = task.mStack; stack.moveTaskToBottom(task); - moveStackWindowsLocked(stack); + moveStackWindowsLocked(stack.getDisplayContent()); } } finally { Binder.restoreCallingIdentity(origId); @@ -5724,7 +5722,7 @@ public class WindowManagerService extends IWindowManager.Stub canvas.drawBitmap(rawss, matrix, null); canvas.setBitmap(null); - if (true || DEBUG_SCREENSHOT) { + if (DEBUG_SCREENSHOT) { // TEST IF IT's ALL BLACK int[] buffer = new int[bm.getWidth() * bm.getHeight()]; bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); @@ -7637,22 +7635,27 @@ public class WindowManagerService extends IWindowManager.Stub if (displayId != Display.DEFAULT_DISPLAY) { throw new IllegalArgumentException("Can only set the default display"); } - synchronized(mWindowMap) { - // Set some sort of reasonable bounds on the size of the display that we - // will try to emulate. - final int MIN_WIDTH = 200; - final int MIN_HEIGHT = 200; - final int MAX_SCALE = 2; - final DisplayContent displayContent = getDisplayContentLocked(displayId); - if (displayContent != null) { - width = Math.min(Math.max(width, MIN_WIDTH), - displayContent.mInitialDisplayWidth * MAX_SCALE); - height = Math.min(Math.max(height, MIN_HEIGHT), - displayContent.mInitialDisplayHeight * MAX_SCALE); - setForcedDisplaySizeLocked(displayContent, width, height); - Settings.Global.putString(mContext.getContentResolver(), - Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized(mWindowMap) { + // Set some sort of reasonable bounds on the size of the display that we + // will try to emulate. + final int MIN_WIDTH = 200; + final int MIN_HEIGHT = 200; + final int MAX_SCALE = 2; + final DisplayContent displayContent = getDisplayContentLocked(displayId); + if (displayContent != null) { + width = Math.min(Math.max(width, MIN_WIDTH), + displayContent.mInitialDisplayWidth * MAX_SCALE); + height = Math.min(Math.max(height, MIN_HEIGHT), + displayContent.mInitialDisplayHeight * MAX_SCALE); + setForcedDisplaySizeLocked(displayContent, width, height); + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); + } } + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -7723,14 +7726,19 @@ public class WindowManagerService extends IWindowManager.Stub if (displayId != Display.DEFAULT_DISPLAY) { throw new IllegalArgumentException("Can only set the default display"); } - synchronized(mWindowMap) { - final DisplayContent displayContent = getDisplayContentLocked(displayId); - if (displayContent != null) { - setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, - displayContent.mInitialDisplayHeight); - Settings.Global.putString(mContext.getContentResolver(), - Settings.Global.DISPLAY_SIZE_FORCED, ""); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized(mWindowMap) { + final DisplayContent displayContent = getDisplayContentLocked(displayId); + if (displayContent != null) { + setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, + displayContent.mInitialDisplayHeight); + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.DISPLAY_SIZE_FORCED, ""); + } } + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -7771,13 +7779,18 @@ public class WindowManagerService extends IWindowManager.Stub if (displayId != Display.DEFAULT_DISPLAY) { throw new IllegalArgumentException("Can only set the default display"); } - synchronized(mWindowMap) { - final DisplayContent displayContent = getDisplayContentLocked(displayId); - if (displayContent != null) { - setForcedDisplayDensityLocked(displayContent, density); - Settings.Global.putString(mContext.getContentResolver(), - Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized(mWindowMap) { + final DisplayContent displayContent = getDisplayContentLocked(displayId); + if (displayContent != null) { + setForcedDisplayDensityLocked(displayContent, density); + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); + } } + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -7802,13 +7815,19 @@ public class WindowManagerService extends IWindowManager.Stub if (displayId != Display.DEFAULT_DISPLAY) { throw new IllegalArgumentException("Can only set the default display"); } - synchronized(mWindowMap) { - final DisplayContent displayContent = getDisplayContentLocked(displayId); - if (displayContent != null) { - setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity); - Settings.Global.putString(mContext.getContentResolver(), - Settings.Global.DISPLAY_DENSITY_FORCED, ""); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized(mWindowMap) { + final DisplayContent displayContent = getDisplayContentLocked(displayId); + if (displayContent != null) { + setForcedDisplayDensityLocked(displayContent, + displayContent.mInitialDisplayDensity); + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.DISPLAY_DENSITY_FORCED, ""); + } } + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -7856,11 +7875,16 @@ public class WindowManagerService extends IWindowManager.Stub throw new SecurityException("Must hold permission " + android.Manifest.permission.WRITE_SECURE_SETTINGS); } - synchronized(mWindowMap) { - DisplayContent displayContent = getDisplayContentLocked(displayId); - if (displayContent != null) { - setOverscanLocked(displayContent, left, top, right, bottom); + final long ident = Binder.clearCallingIdentity(); + try { + synchronized(mWindowMap) { + DisplayContent displayContent = getDisplayContentLocked(displayId); + if (displayContent != null) { + setOverscanLocked(displayContent, left, top, right, bottom); + } } + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -8408,20 +8432,6 @@ public class WindowManagerService extends IWindowManager.Stub && !mWallpaperTarget.mWinAnimator.isDummyAnimation() ? null : mWallpaperTarget; - // If there is a wallpaper target and the target is neither opening nor closing, then - // there exists an app on top of the wallpaper target that has a translucent - // background. - // If the pending transition is an exit, we should add the wallpaper target to the list - // of opening apps so that the translucent app on top of it will animate correctly. - final AppWindowToken wallpaperTargetAppToken = - mWallpaperTarget != null ? mWallpaperTarget.mAppToken : null; - if (wallpaperTargetAppToken != null - && !mClosingApps.contains(wallpaperTargetAppToken) - && !mOpeningApps.contains(wallpaperTargetAppToken) - && (transit & AppTransition.TRANSIT_EXIT_MASK) != 0) { - mOpeningApps.add(wallpaperTargetAppToken); - NN++; - } mInnerFields.mWallpaperMayChange = false; // The top-most window will supply the layout params, @@ -8507,7 +8517,8 @@ public class WindowManagerService extends IWindowManager.Stub break; } if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); - } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) { + } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() + && !mOpeningApps.contains(oldWallpaper.mAppToken)) { // We are transitioning from an activity with // a wallpaper to one without. transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; @@ -8576,8 +8587,7 @@ public class WindowManagerService extends IWindowManager.Stub wtoken.mAppAnimator.clearThumbnail(); wtoken.inPendingTransaction = false; wtoken.mAppAnimator.animation = null; - setTokenVisibilityLocked(wtoken, animLp, false, - transit, false); + setTokenVisibilityLocked(wtoken, animLp, false, transit, false); wtoken.updateReportedVisibilityLocked(); wtoken.waitingToHide = false; // Force the allDrawn flag, because we want to start |