import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
import static android.provider.Settings.System.FONT_SCALE;
import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
+import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_URI_PERMISSION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBLE_BEHIND;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_WHITELISTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BACKUP;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBLE_BEHIND;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.FORCE_NEW_TASK_FLAGS;
import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
import android.app.BroadcastOptions;
import android.app.ContentProviderHolder;
import android.app.Dialog;
-import android.app.IActivityContainer;
-import android.app.IActivityContainerCallback;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IAppTask;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
-import android.util.BootTimingsTraceLog;
+import android.util.TimingsTraceLog;
import android.util.DebugUtils;
import android.util.DisplayMetrics;
import android.util.EventLog;
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.WindowManagerService;
+import java.text.SimpleDateFormat;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE;
- private static final String TAG_LOCKSCREEN = TAG + POSTFIX_LOCKSCREEN;
private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
private static final String TAG_LRU = TAG + POSTFIX_LRU;
private static final String TAG_MU = TAG + POSTFIX_MU;
private static final String TAG_UID_OBSERVERS = TAG + POSTFIX_UID_OBSERVERS;
private static final String TAG_URI_PERMISSION = TAG + POSTFIX_URI_PERMISSION;
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
- private static final String TAG_VISIBLE_BEHIND = TAG + POSTFIX_VISIBLE_BEHIND;
// Mock "pretend we're idle now" broadcast action to the job scheduler; declared
// here so that while the job scheduler can depend on AMS, the other way around
static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
- static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
-
// Amount of time after a call to stopAppSwitches() during which we will
// prevent further untrusted switches from happening.
static final long APP_SWITCH_DELAY_TIME = 5*1000;
// the notification will not be legible to the user.
private static final int MAX_BUGREPORT_TITLE_SIZE = 50;
+ private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds;
+
/** All system services */
SystemServiceManager mSystemServiceManager;
AssistUtils mAssistUtils;
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
- && !mKeyguardController.isKeyguardShowing();
+ && !mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)
+ && !(UserManager.isDeviceInDemoMode(mContext)
+ && mUserController.getCurrentUser().isDemo());
}
private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
boolean mDidAppSwitch;
/**
- * Last time (in realtime) at which we checked for power usage.
- */
- long mLastPowerCheckRealtime;
-
- /**
* Last time (in uptime) at which we checked for power usage.
*/
long mLastPowerCheckUptime;
* Set while we are running a voice interaction. This overrides
* sleeping while it is active.
*/
- private IVoiceInteractionSession mRunningVoice;
+ IVoiceInteractionSession mRunningVoice;
/**
* For some direct access we need to power manager.
private int mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
/**
- * A list of tokens that cause the top activity to be put to sleep.
- * They are used by components that may hide and block interaction with underlying
- * activities.
- */
- final ArrayList<SleepToken> mSleepTokens = new ArrayList<SleepToken>();
-
- /**
* Set if we are shutting down the system, similar to sleeping.
*/
boolean mShuttingDown = false;
= new ProcessMap<ArrayList<ProcessRecord>>();
/**
- * This is set if we had to do a delayed dexopt of an app before launching
- * it, to increase the ANR timeouts in that case.
- */
- boolean mDidDexOpt;
-
- /**
* Set if the systemServer made a call to enterSafeMode.
*/
boolean mSafeMode;
* Flag that indicates if multi-window is enabled.
*
* For any particular form of multi-window to be enabled, generic multi-window must be enabled
- * in {@link com.android.internal.R.bool.config_supportsMultiWindow} config or
+ * in {@link com.android.internal.R.bool#config_supportsMultiWindow} config or
* {@link Settings.Global#DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES} development option set.
* At least one of the forms of multi-window must be enabled in order for this flag to be
* initialized to 'true'.
boolean mControllerIsAMonkey = false;
String mProfileApp = null;
ProcessRecord mProfileProc = null;
- String mProfileFile;
- ParcelFileDescriptor mProfileFd;
- int mSamplingInterval = 0;
- boolean mAutoStopProfiler = false;
- boolean mStreamingOutput = false;
+ ProfilerInfo mProfilerInfo = null;
int mProfileType = 0;
final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
String mMemWatchDumpProcName;
final ArrayList<UidRecord.ChangeItem> mPendingUidChanges = new ArrayList<>();
final ArrayList<UidRecord.ChangeItem> mAvailUidChanges = new ArrayList<>();
+ OomAdjObserver mCurOomAdjObserver;
+ int mCurOomAdjUid;
+
+ interface OomAdjObserver {
+ void onOomAdjMessage(String msg);
+ }
+
/**
* Runtime CPU use collection thread. This object's lock is used to
* perform synchronization with the thread (notifying it to run).
static final int POST_HEAVY_NOTIFICATION_MSG = 24;
static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
static final int SHOW_STRICT_MODE_VIOLATION_UI_MSG = 26;
- static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
+ static final int CHECK_EXCESSIVE_POWER_USE_MSG = 27;
static final int CLEAR_DNS_CACHE_MSG = 28;
static final int UPDATE_HTTP_PROXY_MSG = 29;
static final int SHOW_COMPAT_MODE_DIALOG_UI_MSG = 30;
static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67;
static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
+ static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
static final int START_USER_SWITCH_FG_MSG = 712;
+ static final int NOTIFY_VR_KEYGUARD_MSG = 74;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
final boolean mPermissionReviewRequired;
+ private static String sTheRealBuildSerial = Build.UNKNOWN;
+
/**
* Current global configuration information. Contains general settings for the entire system,
* also corresponds to the merged configuration of the default display.
case DISPATCH_UIDS_CHANGED_UI_MSG: {
dispatchUidsChanged();
} break;
+ case DISPATCH_OOM_ADJ_OBSERVER_MSG: {
+ dispatchOomAdjObserver((String)msg.obj);
+ } break;
case PUSH_TEMP_WHITELIST_UI_MSG: {
pushTempWhitelist();
} break;
}
} break;
case SERVICE_TIMEOUT_MSG: {
- if (mDidDexOpt) {
- mDidDexOpt = false;
- Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
- nmsg.obj = msg.obj;
- mHandler.sendMessageDelayed(nmsg, ActiveServices.SERVICE_TIMEOUT);
- return;
- }
mServices.serviceTimeout((ProcessRecord)msg.obj);
} break;
case SERVICE_FOREGROUND_TIMEOUT_MSG: {
}
} break;
case PROC_START_TIMEOUT_MSG: {
- if (mDidDexOpt) {
- mDidDexOpt = false;
- Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
- nmsg.obj = msg.obj;
- mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
- return;
- }
ProcessRecord app = (ProcessRecord)msg.obj;
synchronized (ActivityManagerService.this) {
processStartTimedOutLocked(app);
} catch (RemoteException e) {
}
} break;
- case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
+ case CHECK_EXCESSIVE_POWER_USE_MSG: {
synchronized (ActivityManagerService.this) {
- checkExcessivePowerUsageLocked(true);
- removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- sendMessageDelayed(nmsg, mConstants.POWER_CHECK_DELAY);
+ checkExcessivePowerUsageLocked();
+ removeMessages(CHECK_EXCESSIVE_POWER_USE_MSG);
+ Message nmsg = obtainMessage(CHECK_EXCESSIVE_POWER_USE_MSG);
+ sendMessageDelayed(nmsg, mConstants.POWER_CHECK_INTERVAL);
}
} break;
case REPORT_MEM_USAGE_MSG: {
case NOTIFY_VR_SLEEPING_MSG: {
notifyVrManagerOfSleepState(msg.arg1 != 0);
} break;
+ case NOTIFY_VR_KEYGUARD_MSG: {
+ notifyVrManagerOfKeyguardState(msg.arg1 != 0);
+ } break;
case HANDLE_TRUST_STORAGE_UPDATE_MSG: {
synchronized (ActivityManagerService.this) {
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
mService.start();
}
+ @Override
+ public void onCleanupUser(int userId) {
+ mService.mBatteryStatsService.onCleanupUser(userId);
+ }
+
public ActivityManagerService getService() {
return mService;
}
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
systemDir.mkdirs();
- mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
+ mBatteryStatsService = new BatteryStatsService(systemContext, systemDir, mHandler);
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.scheduleWriteToDisk();
mOnBattery = DEBUG_POWER ? true
removeAllProcessGroups();
mProcessCpuThread.start();
- mBatteryStatsService.publish(mContext);
+ mBatteryStatsService.publish();
mAppOpsService.publish(mContext);
Slog.d("AppOps", "AppOpsService published");
LocalServices.addService(ActivityManagerInternal.class, new LocalService());
}
ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
pr.curCpuTime += st.rel_utime + st.rel_stime;
+ if (pr.lastCpuTime == 0) {
+ pr.lastCpuTime = pr.curCpuTime;
+ }
} else {
BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
if (ps == null || !ps.isActive()) {
}
final void applyUpdateVrModeLocked(ActivityRecord r) {
+ // VR apps are expected to run in a main display. If an app is turning on VR for
+ // itself, but lives in a dynamic stack, then make sure that it is moved to the main
+ // fullscreen stack before enabling VR Mode.
+ // TODO: The goal of this code is to keep the VR app on the main display. When the
+ // stack implementation changes in the future, keep in mind that the use of the fullscreen
+ // stack is a means to move the activity to the main display and a moveActivityToDisplay()
+ // option would be a better choice here.
+ if (r.requestedVrComponent != null && r.getStackId() >= FIRST_DYNAMIC_STACK_ID) {
+ Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
+ + " to main stack for VR");
+ moveTaskToStack(r.getTask().taskId, FULLSCREEN_WORKSPACE_STACK_ID, true /* toTop */);
+ }
mHandler.sendMessage(
mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
}
vrService.onSleepStateChanged(isSleeping);
}
+ private void sendNotifyVrManagerOfKeyguardState(boolean isShowing) {
+ mHandler.sendMessage(
+ mHandler.obtainMessage(NOTIFY_VR_KEYGUARD_MSG, isShowing ? 1 : 0, 0));
+ }
+
+ private void notifyVrManagerOfKeyguardState(boolean isShowing) {
+ final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
+ if (vrService == null) {
+ return;
+ }
+ vrService.onKeyguardStateChanged(isShowing);
+ }
+
final void showAskCompatModeDialogLocked(ActivityRecord r) {
Message msg = Message.obtain();
msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
}
void notifyPackageUse(String packageName, int reason) {
- IPackageManager pm = AppGlobals.getPackageManager();
- try {
- pm.notifyPackageUse(packageName, reason);
- } catch (RemoteException e) {
+ synchronized(this) {
+ getPackageManagerInternalLocked().notifyPackageUse(packageName, reason);
}
}
ri.activityInfo.packageName, ri.activityInfo.name));
mActivityStarter.startActivityLocked(null, intent, null /*ephemeralIntent*/,
null, ri.activityInfo, null /*rInfo*/, null, null, null, null, 0, 0, 0,
- null, 0, 0, 0, null, false, false, null, null, null,
- "startSetupActivity");
+ null, 0, 0, 0, null, false, false, null, null, "startSetupActivity");
}
}
}
if (VALIDATE_UID_STATES && mUidObservers.getRegisteredCallbackCount() > 0) {
for (int j = 0; j < N; ++j) {
final UidRecord.ChangeItem item = mActiveUidChanges[j];
- if (item.change == UidRecord.CHANGE_GONE
- || item.change == UidRecord.CHANGE_GONE_IDLE) {
+ if ((item.change & UidRecord.CHANGE_GONE) != 0) {
mValidateUids.remove(item.uid);
} else {
UidRecord validateUid = mValidateUids.get(item.uid);
validateUid = new UidRecord(item.uid);
mValidateUids.put(item.uid, validateUid);
}
- if (item.change == UidRecord.CHANGE_IDLE) {
+ if ((item.change & UidRecord.CHANGE_IDLE) != 0) {
validateUid.idle = true;
- } else if (item.change == UidRecord.CHANGE_ACTIVE) {
+ } else if ((item.change & UidRecord.CHANGE_ACTIVE) != 0) {
validateUid.idle = false;
}
validateUid.curProcState = validateUid.setProcState = item.processState;
for (int j = 0; j < changesSize; j++) {
UidRecord.ChangeItem item = mActiveUidChanges[j];
final int change = item.change;
- if (change == UidRecord.CHANGE_IDLE
- || change == UidRecord.CHANGE_GONE_IDLE) {
+ if (change == UidRecord.CHANGE_PROCSTATE &&
+ (reg.which & ActivityManager.UID_OBSERVER_PROCSTATE) == 0) {
+ // No-op common case: no significant change, the observer is not
+ // interested in all proc state changes.
+ continue;
+ }
+ if ((change & UidRecord.CHANGE_IDLE) != 0) {
if ((reg.which & ActivityManager.UID_OBSERVER_IDLE) != 0) {
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"UID idle uid=" + item.uid);
observer.onUidIdle(item.uid, item.ephemeral);
}
- } else if (change == UidRecord.CHANGE_ACTIVE) {
+ } else if ((change & UidRecord.CHANGE_ACTIVE) != 0) {
if ((reg.which & ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"UID active uid=" + item.uid);
observer.onUidActive(item.uid);
}
}
- if (change == UidRecord.CHANGE_GONE
- || change == UidRecord.CHANGE_GONE_IDLE) {
+ if ((reg.which & ActivityManager.UID_OBSERVER_CACHED) != 0) {
+ if ((change & UidRecord.CHANGE_CACHED) != 0) {
+ if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
+ "UID cached uid=" + item.uid);
+ observer.onUidCachedChanged(item.uid, true);
+ } else if ((change & UidRecord.CHANGE_UNCACHED) != 0) {
+ if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
+ "UID active uid=" + item.uid);
+ observer.onUidCachedChanged(item.uid, false);
+ }
+ }
+ if ((change & UidRecord.CHANGE_GONE) != 0) {
if ((reg.which & ActivityManager.UID_OBSERVER_GONE) != 0) {
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"UID gone uid=" + item.uid);
}
}
+ void dispatchOomAdjObserver(String msg) {
+ OomAdjObserver observer;
+ synchronized (this) {
+ observer = mCurOomAdjObserver;
+ }
+
+ if (observer != null) {
+ observer.onOomAdjMessage(msg);
+ }
+ }
+
+ void setOomAdjObserver(int uid, OomAdjObserver observer) {
+ synchronized (this) {
+ mCurOomAdjUid = uid;
+ mCurOomAdjObserver = observer;
+ }
+ }
+
+ void clearOomAdjObserver() {
+ synchronized (this) {
+ mCurOomAdjUid = -1;
+ mCurOomAdjObserver = null;
+ }
+ }
+
+ void reportOomAdjMessageLocked(String tag, String msg) {
+ Slog.d(tag, msg);
+ if (mCurOomAdjObserver != null) {
+ mUiHandler.obtainMessage(DISPATCH_OOM_ADJ_OBSERVER_MSG, msg).sendToTarget();
+ }
+ }
+
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
UserHandle.getCallingUserId());
}
- final int startActivity(Intent intent, ActivityStackSupervisor.ActivityContainer container) {
- enforceNotIsolatedCaller("ActivityContainer.startActivity");
- final int userId = mUserController.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), mStackSupervisor.mCurrentUser, false,
- ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
-
- // TODO: Switch to user app stacks here.
- String mimeType = intent.getType();
- final Uri data = intent.getData();
- if (mimeType == null && data != null && "content".equals(data.getScheme())) {
- mimeType = getProviderMimeType(data, userId);
- }
- container.checkEmbeddedAllowedInner(userId, intent, mimeType);
-
- intent.addFlags(FORCE_NEW_TASK_FLAGS);
- return mActivityStarter.startActivityMayWait(null, -1, null, intent, mimeType, null, null,
- null, null, 0, 0, null, null, null, null, false, userId, container, null,
- "startActivity");
- }
-
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- profilerInfo, null, null, bOptions, false, userId, null, null,
- "startActivityAsUser");
+ profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
}
@Override
try {
int ret = mActivityStarter.startActivityMayWait(null, targetUid, targetPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, null,
- null, null, bOptions, ignoreTargetSecurity, userId, null, null,
+ null, null, bOptions, ignoreTargetSecurity, userId, null,
"startActivityAsCaller");
return ret;
} catch (SecurityException e) {
// TODO: Switch to user app stacks here.
mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, res, null,
- bOptions, false, userId, null, null, "startActivityAndWait");
+ bOptions, false, userId, null, "startActivityAndWait");
return res;
}
// TODO: Switch to user app stacks here.
int ret = mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- null, null, config, bOptions, false, userId, null, null, "startActivityWithConfig");
+ null, null, config, bOptions, false, userId, null, "startActivityWithConfig");
return ret;
}
}
}
int ret = pir.sendInner(0, fillInIntent, resolvedType, whitelistToken, null, null,
- resultTo, resultWho, requestCode, flagsMask, flagsValues, bOptions, null);
+ resultTo, resultWho, requestCode, flagsMask, flagsValues, bOptions);
return ret;
}
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(null, callingUid, callingPackage, intent,
resolvedType, session, interactor, null, null, 0, startFlags, profilerInfo, null,
- null, bOptions, false, userId, null, null, "startVoiceActivity");
+ null, bOptions, false, userId, null, "startVoiceActivity");
}
@Override
ALLOW_FULL_ONLY, "startAssistantActivity", null);
return mActivityStarter.startActivityMayWait(null, callingUid, callingPackage, intent,
resolvedType, null, null, null, null, 0, 0, null, null, null, bOptions, false,
- userId, null, null, "startAssistantActivity");
+ userId, null, "startAssistantActivity");
}
@Override
null /*ephemeralIntent*/, r.resolvedType, aInfo, null /*rInfo*/, null,
null, resultTo != null ? resultTo.appToken : null, resultWho, requestCode, -1,
r.launchedFromUid, r.launchedFromPackage, -1, r.launchedFromUid, 0, options,
- false, false, null, null, null, "startNextMatchingActivity");
+ false, false, null, null, "startNextMatchingActivity");
Binder.restoreCallingIdentity(origId);
r.finishing = wasFinishing;
final int startActivityInPackage(int uid, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, Bundle bOptions, int userId,
- IActivityContainer container, TaskRecord inTask, String reason) {
+ TaskRecord inTask, String reason) {
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivityInPackage", null);
// TODO: Switch to user app stacks here.
- int ret = mActivityStarter.startActivityMayWait(null, uid, callingPackage, intent,
- resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- null, null, null, bOptions, false, userId, container, inTask, reason);
- return ret;
+ return mActivityStarter.startActivityMayWait(null, uid, ActivityStarter.PID_NULL, uid,
+ callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode,
+ startFlags, null, null, null, bOptions, false, userId, inTask, reason);
}
@Override
final int startActivitiesInPackage(int uid, String callingPackage,
Intent[] intents, String[] resolvedTypes, IBinder resultTo,
Bundle bOptions, int userId) {
+ return startActivitiesInPackage(uid, ActivityStarter.PID_NULL, UserHandle.USER_NULL,
+ callingPackage, intents, resolvedTypes, resultTo, bOptions, userId);
+ }
+
+ final int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid,
+ String callingPackage, Intent[] intents, String[] resolvedTypes,
+ IBinder resultTo, Bundle bOptions, int userId) {
final String reason = "startActivityInPackage";
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, reason, null);
// TODO: Switch to user app stacks here.
- int ret = mActivityStarter.startActivities(null, uid, callingPackage, intents, resolvedTypes,
- resultTo, bOptions, userId, reason);
+ int ret = mActivityStarter.startActivities(null, uid, realCallingPid, realCallingUid,
+ callingPackage, intents, resolvedTypes, resultTo, bOptions, userId, reason);
return ret;
}
@Override
- public void reportActivityFullyDrawn(IBinder token) {
+ public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) {
synchronized (this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
return;
}
- r.reportFullyDrawnLocked();
+ r.reportFullyDrawnLocked(restoredFromBundle);
}
}
* @param firstPids of dalvik VM processes to dump stack traces for first
* @param lastPids of dalvik VM processes to dump stack traces for last
* @param nativePids optional list of native pids to dump stack crawls
- * @return file containing stack traces, or null if no dump file is configured
*/
public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids,
ArrayList<Integer> nativePids) {
- String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
- if (tracesPath == null || tracesPath.length() == 0) {
- return null;
+ ArrayList<Integer> extraPids = null;
+
+ // Measure CPU usage as soon as we're called in order to get a realistic sampling
+ // of the top users at the time of the request.
+ if (processCpuTracker != null) {
+ processCpuTracker.init();
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException ignored) {
+ }
+
+ processCpuTracker.update();
+
+ // We'll take the stack crawls of just the top apps using CPU.
+ final int N = processCpuTracker.countWorkingStats();
+ extraPids = new ArrayList<>();
+ for (int i = 0; i < N && extraPids.size() < 5; i++) {
+ ProcessCpuTracker.Stats stats = processCpuTracker.getWorkingStats(i);
+ if (lastPids.indexOfKey(stats.pid) >= 0) {
+ if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid " + stats.pid);
+
+ extraPids.add(stats.pid);
+ } else if (DEBUG_ANR) {
+ Slog.d(TAG, "Skipping next CPU consuming process, not a java proc: "
+ + stats.pid);
+ }
+ }
}
- File tracesFile = new File(tracesPath);
- try {
- if (clearTraces && tracesFile.exists()) tracesFile.delete();
- tracesFile.createNewFile();
- FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
- } catch (IOException e) {
- Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
- return null;
+ boolean useTombstonedForJavaTraces = false;
+ File tracesFile;
+
+ final String tracesDirProp = SystemProperties.get("dalvik.vm.stack-trace-dir", "");
+ if (tracesDirProp.isEmpty()) {
+ // When dalvik.vm.stack-trace-dir is not set, we are using the "old" trace
+ // dumping scheme. All traces are written to a global trace file (usually
+ // "/data/anr/traces.txt") so the code below must take care to unlink and recreate
+ // the file if requested.
+ //
+ // This mode of operation will be removed in the near future.
+
+
+ String globalTracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
+ if (globalTracesPath.isEmpty()) {
+ Slog.w(TAG, "dumpStackTraces: no trace path configured");
+ return null;
+ }
+
+ tracesFile = new File(globalTracesPath);
+ try {
+ if (clearTraces && tracesFile.exists()) {
+ tracesFile.delete();
+ }
+
+ tracesFile.createNewFile();
+ FileUtils.setPermissions(globalTracesPath, 0666, -1, -1); // -rw-rw-rw-
+ } catch (IOException e) {
+ Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesFile, e);
+ return null;
+ }
+ } else {
+ File tracesDir = new File(tracesDirProp);
+ // When dalvik.vm.stack-trace-dir is set, we use the "new" trace dumping scheme.
+ // Each set of ANR traces is written to a separate file and dumpstate will process
+ // all such files and add them to a captured bug report if they're recent enough.
+ maybePruneOldTraces(tracesDir);
+
+ // NOTE: We should consider creating the file in native code atomically once we've
+ // gotten rid of the old scheme of dumping and lot of the code that deals with paths
+ // can be removed.
+ tracesFile = createAnrDumpFile(tracesDir);
+ if (tracesFile == null) {
+ return null;
+ }
+
+ useTombstonedForJavaTraces = true;
}
- dumpStackTraces(tracesPath, firstPids, processCpuTracker, lastPids, nativePids);
+ dumpStackTraces(tracesFile.getAbsolutePath(), firstPids, nativePids, extraPids,
+ useTombstonedForJavaTraces);
return tracesFile;
}
+ @GuardedBy("ActivityManagerService.class")
+ private static SimpleDateFormat sAnrFileDateFormat;
+
+ private static synchronized File createAnrDumpFile(File tracesDir) {
+ if (sAnrFileDateFormat == null) {
+ sAnrFileDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");
+ }
+
+ final String formattedDate = sAnrFileDateFormat.format(new Date());
+ final File anrFile = new File(tracesDir, "anr_" + formattedDate);
+
+ try {
+ if (anrFile.createNewFile()) {
+ FileUtils.setPermissions(anrFile.getAbsolutePath(), 0600, -1, -1); // -rw-------
+ return anrFile;
+ } else {
+ Slog.w(TAG, "Unable to create ANR dump file: createNewFile failed");
+ }
+ } catch (IOException ioe) {
+ Slog.w(TAG, "Exception creating ANR dump file:", ioe);
+ }
+
+ return null;
+ }
+
+ /**
+ * Prune all trace files that are more than a day old.
+ *
+ * NOTE: It might make sense to move this functionality to tombstoned eventually, along with a
+ * shift away from anr_XX and tombstone_XX to a more descriptive name. We do it here for now
+ * since it's the system_server that creates trace files for most ANRs.
+ */
+ private static void maybePruneOldTraces(File tracesDir) {
+ final long now = System.currentTimeMillis();
+ final File[] traceFiles = tracesDir.listFiles();
+
+ if (traceFiles != null) {
+ for (File file : traceFiles) {
+ if ((now - file.lastModified()) > DAY_IN_MILLIS) {
+ if (!file.delete()) {
+ Slog.w(TAG, "Unable to prune stale trace file: " + file);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Legacy code, do not use. Existing users will be deleted.
+ *
+ * @deprecated
+ */
+ @Deprecated
public static class DumpStackFileObserver extends FileObserver {
// Keep in sync with frameworks/native/cmds/dumpstate/utils.cpp
private static final int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
- static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds;
private final String mTracesPath;
private boolean mClosed;
}
}
- private static void dumpStackTraces(String tracesPath, ArrayList<Integer> firstPids,
- ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids,
- ArrayList<Integer> nativePids) {
- // Use a FileObserver to detect when traces finish writing.
- // The order of traces is considered important to maintain for legibility.
- DumpStackFileObserver observer = new DumpStackFileObserver(tracesPath);
+ /**
+ * Dump java traces for process {@code pid} to the specified file. If java trace dumping
+ * fails, a native backtrace is attempted. Note that the timeout {@code timeoutMs} only applies
+ * to the java section of the trace, a further {@code NATIVE_DUMP_TIMEOUT_MS} might be spent
+ * attempting to obtain native traces in the case of a failure. Returns the total time spent
+ * capturing traces.
+ */
+ private static long dumpJavaTracesTombstoned(int pid, String fileName, long timeoutMs) {
+ final long timeStart = SystemClock.elapsedRealtime();
+ if (!Debug.dumpJavaBacktraceToFileTimeout(pid, fileName, (int) (timeoutMs / 1000))) {
+ Debug.dumpNativeBacktraceToFileTimeout(pid, fileName,
+ (NATIVE_DUMP_TIMEOUT_MS / 1000));
+ }
+
+ return SystemClock.elapsedRealtime() - timeStart;
+ }
+
+ private static void dumpStackTraces(String tracesFile, ArrayList<Integer> firstPids,
+ ArrayList<Integer> nativePids, ArrayList<Integer> extraPids,
+ boolean useTombstonedForJavaTraces) {
+
+ // We don't need any sort of inotify based monitoring when we're dumping traces via
+ // tombstoned. Data is piped to an "intercept" FD installed in tombstoned so we're in full
+ // control of all writes to the file in question.
+ final DumpStackFileObserver observer;
+ if (useTombstonedForJavaTraces) {
+ observer = null;
+ } else {
+ // Use a FileObserver to detect when traces finish writing.
+ // The order of traces is considered important to maintain for legibility.
+ observer = new DumpStackFileObserver(tracesFile);
+ }
// We must complete all stack dumps within 20 seconds.
long remainingTime = 20 * 1000;
try {
- observer.startWatching();
+ if (observer != null) {
+ observer.startWatching();
+ }
// First collect all of the stacks of the most important pids.
if (firstPids != null) {
for (int i = 0; i < num; i++) {
if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for pid "
+ firstPids.get(i));
- final long timeTaken = observer.dumpWithTimeout(firstPids.get(i), remainingTime);
+ final long timeTaken;
+ if (useTombstonedForJavaTraces) {
+ timeTaken = dumpJavaTracesTombstoned(firstPids.get(i), tracesFile, remainingTime);
+ } else {
+ timeTaken = observer.dumpWithTimeout(firstPids.get(i), remainingTime);
+ }
remainingTime -= timeTaken;
if (remainingTime <= 0) {
if (nativePids != null) {
for (int pid : nativePids) {
if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
- final long nativeDumpTimeoutMs = Math.min(
- DumpStackFileObserver.NATIVE_DUMP_TIMEOUT_MS, remainingTime);
+ final long nativeDumpTimeoutMs = Math.min(NATIVE_DUMP_TIMEOUT_MS, remainingTime);
final long start = SystemClock.elapsedRealtime();
Debug.dumpNativeBacktraceToFileTimeout(
- pid, tracesPath, (int) (nativeDumpTimeoutMs / 1000));
+ pid, tracesFile, (int) (nativeDumpTimeoutMs / 1000));
final long timeTaken = SystemClock.elapsedRealtime() - start;
remainingTime -= timeTaken;
}
}
- // Lastly, measure CPU usage.
- if (processCpuTracker != null) {
- processCpuTracker.init();
- System.gc();
- processCpuTracker.update();
- try {
- synchronized (processCpuTracker) {
- processCpuTracker.wait(500); // measure over 1/2 second.
- }
- } catch (InterruptedException e) {
- }
- processCpuTracker.update();
-
- // We'll take the stack crawls of just the top apps using CPU.
- final int N = processCpuTracker.countWorkingStats();
- int numProcs = 0;
- for (int i=0; i<N && numProcs<5; i++) {
- ProcessCpuTracker.Stats stats = processCpuTracker.getWorkingStats(i);
- if (lastPids.indexOfKey(stats.pid) >= 0) {
- numProcs++;
+ // Lastly, dump stacks for all extra PIDs from the CPU tracker.
+ if (extraPids != null) {
+ for (int pid : extraPids) {
+ if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid " + pid);
- if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid " + stats.pid);
+ final long timeTaken;
+ if (useTombstonedForJavaTraces) {
+ timeTaken = dumpJavaTracesTombstoned(pid, tracesFile, remainingTime);
+ } else {
+ timeTaken = observer.dumpWithTimeout(pid, remainingTime);
+ }
- final long timeTaken = observer.dumpWithTimeout(stats.pid, remainingTime);
- remainingTime -= timeTaken;
- if (remainingTime <= 0) {
- Slog.e(TAG, "Aborting stack trace dump (current extra pid=" + stats.pid +
+ remainingTime -= timeTaken;
+ if (remainingTime <= 0) {
+ Slog.e(TAG, "Aborting stack trace dump (current extra pid=" + pid +
"); deadline exceeded.");
- return;
- }
+ return;
+ }
- if (DEBUG_ANR) {
- Slog.d(TAG, "Done with extra pid " + stats.pid + " in " + timeTaken + "ms");
- }
- } else if (DEBUG_ANR) {
- Slog.d(TAG, "Skipping next CPU consuming process, not a java proc: "
- + stats.pid);
+ if (DEBUG_ANR) {
+ Slog.d(TAG, "Done with extra pid " + pid + " in " + timeTaken + "ms");
}
}
}
} finally {
- observer.stopWatching();
+ if (observer != null) {
+ observer.stopWatching();
+ }
}
}
final void logAppTooSlow(ProcessRecord app, long startTime, String msg) {
- if (true || IS_USER_BUILD) {
+ if (true || Build.IS_USER) {
return;
}
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
if (app != null) {
ArrayList<Integer> firstPids = new ArrayList<Integer>();
firstPids.add(app.pid);
- dumpStackTraces(tracesPath, firstPids, null, null, null);
+ dumpStackTraces(tracesPath, firstPids, null, null, true /* useTombstoned */);
}
File lastTracesFile = null;
enforceNotIsolatedCaller("clearApplicationUserData");
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
- userId = mUserController.handleIncomingUser(pid, uid, userId, false,
+ final int resolvedUserId = mUserController.handleIncomingUser(pid, uid, userId, false,
ALLOW_FULL_ONLY, "clearApplicationUserData", null);
+ final ApplicationInfo appInfo;
+ final boolean isInstantApp;
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
- int pkgUid = -1;
synchronized(this) {
+ // Instant packages are not protected
if (getPackageManagerInternalLocked().isPackageDataProtected(
- userId, packageName)) {
+ resolvedUserId, packageName)) {
throw new SecurityException(
"Cannot clear data for a protected package: " + packageName);
}
+ ApplicationInfo applicationInfo = null;
try {
- pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES, userId);
+ applicationInfo = pm.getApplicationInfo(packageName,
+ MATCH_UNINSTALLED_PACKAGES, resolvedUserId);
} catch (RemoteException e) {
+ /* ignore */
}
- if (pkgUid == -1) {
+ appInfo = applicationInfo;
+
+ final boolean clearingOwnUidData = appInfo != null && appInfo.uid == uid;
+
+ if (!clearingOwnUidData && checkComponentPermission(permission.CLEAR_APP_USER_DATA,
+ pid, uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("PID " + pid + " does not have permission "
+ + android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data"
+ + " of package " + packageName);
+ }
+
+ final boolean hasInstantMetadata = getPackageManagerInternalLocked()
+ .hasInstantApplicationMetadata(packageName, resolvedUserId);
+ final boolean isUninstalledAppWithoutInstantMetadata =
+ (appInfo == null && !hasInstantMetadata);
+ isInstantApp = (appInfo != null && appInfo.isInstantApp())
+ || hasInstantMetadata;
+ final boolean canAccessInstantApps = checkComponentPermission(
+ permission.ACCESS_INSTANT_APPS, pid, uid, -1, true)
+ == PackageManager.PERMISSION_GRANTED;
+
+ if (isUninstalledAppWithoutInstantMetadata || (isInstantApp
+ && !canAccessInstantApps)) {
Slog.w(TAG, "Invalid packageName: " + packageName);
if (observer != null) {
try {
}
return false;
}
- if (uid == pkgUid || checkComponentPermission(
- android.Manifest.permission.CLEAR_APP_USER_DATA,
- pid, uid, -1, true)
- == PackageManager.PERMISSION_GRANTED) {
- forceStopPackageLocked(packageName, pkgUid, "clear data");
- } else {
- throw new SecurityException("PID " + pid + " does not have permission "
- + android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data"
- + " of package " + packageName);
- }
- // Remove all tasks match the cleared application package and user
- for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
- final TaskRecord tr = mRecentTasks.get(i);
- final String taskPackageName =
- tr.getBaseIntent().getComponent().getPackageName();
- if (tr.userId != userId) continue;
- if (!taskPackageName.equals(packageName)) continue;
- mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS);
+ if (appInfo != null) {
+ forceStopPackageLocked(packageName, appInfo.uid, "clear data");
+ // Remove all tasks match the cleared application package and user
+ for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+ final TaskRecord tr = mRecentTasks.get(i);
+ final String taskPackageName =
+ tr.getBaseIntent().getComponent().getPackageName();
+ if (tr.userId != resolvedUserId) continue;
+ if (!taskPackageName.equals(packageName)) continue;
+ mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
+ REMOVE_FROM_RECENTS);
+ }
}
}
- final int pkgUidF = pkgUid;
- final int userIdF = userId;
final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() {
@Override
public void onRemoveCompleted(String packageName, boolean succeeded)
throws RemoteException {
- synchronized (ActivityManagerService.this) {
- finishForceStopPackageLocked(packageName, pkgUidF);
+ if (appInfo != null) {
+ synchronized (ActivityManagerService.this) {
+ finishForceStopPackageLocked(packageName, appInfo.uid);
+ }
}
-
final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
- intent.putExtra(Intent.EXTRA_UID, pkgUidF);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF));
- broadcastIntentInPackage("android", SYSTEM_UID, intent,
- null, null, 0, null, null, null, null, false, false, userIdF);
+ intent.putExtra(Intent.EXTRA_UID, (appInfo != null) ? appInfo.uid : -1);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, resolvedUserId);
+ if (isInstantApp) {
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+ broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0,
+ null, null, permission.ACCESS_INSTANT_APPS, null, false, false,
+ resolvedUserId);
+ } else {
+ broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0,
+ null, null, null, null, false, false, resolvedUserId);
+ }
if (observer != null) {
observer.onRemoveCompleted(packageName, succeeded);
try {
// Clear application user data
- pm.clearApplicationUserData(packageName, localObserver, userId);
+ pm.clearApplicationUserData(packageName, localObserver, resolvedUserId);
- synchronized(this) {
- // Remove all permissions granted from/to this package
- removeUriPermissionsForPackageLocked(packageName, userId, true);
- }
+ if (appInfo != null) {
+ synchronized (this) {
+ // Remove all permissions granted from/to this package
+ removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true);
+ }
- // Reset notification settings.
- INotificationManager inm = NotificationManager.getService();
- inm.clearData(packageName, pkgUidF, uid == pkgUidF);
+ // Reset notification settings.
+ INotificationManager inm = NotificationManager.getService();
+ inm.clearData(packageName, appInfo.uid, uid == appInfo.uid);
+ }
} catch (RemoteException e) {
}
} finally {
mActiveUids.put(proc.uid, uidRec);
EventLogTags.writeAmUidRunning(uidRec.uid);
noteUidProcessState(uidRec.uid, uidRec.curProcState);
- enqueueUidChangeLocked(uidRec, -1, UidRecord.CHANGE_ACTIVE);
}
proc.uidRecord = uidRec;
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
- if (app.isolated) {
- mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
- getPackageManagerInternalLocked().removeIsolatedUid(app.uid);
- }
boolean willRestart = false;
if (app.persistent && !app.isolated) {
if (!callerWillRestart) {
}
}
app.kill(reason, true);
+ if (app.isolated) {
+ mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
+ getPackageManagerInternalLocked().removeIsolatedUid(app.uid);
+ }
handleAppDiedLocked(app, willRestart, allowRestart);
if (willRestart) {
removeLruProcessLocked(app);
mHeavyWeightProcess = null;
}
mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
- if (app.isolated) {
- mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
- }
// Take care of any launching providers waiting for this process.
cleanupAppInLaunchingProvidersLocked(app, true);
// Take care of any services that are waiting for the process.
mServices.processStartTimedOutLocked(app);
app.kill("start timeout", true);
+ if (app.isolated) {
+ mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
+ }
removeLruProcessLocked(app);
if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Slog.w(TAG, "Unattached app died before backup, skipping");
mWaitForDebugger = mOrigWaitForDebugger;
}
}
- String profileFile = app.instr != null ? app.instr.mProfileFile : null;
- ParcelFileDescriptor profileFd = null;
- int samplingInterval = 0;
- boolean profileAutoStop = false;
- boolean profileStreamingOutput = false;
+
+ ProfilerInfo profilerInfo = null;
+ String agent = null;
if (mProfileApp != null && mProfileApp.equals(processName)) {
mProfileProc = app;
- profileFile = mProfileFile;
- profileFd = mProfileFd;
- samplingInterval = mSamplingInterval;
- profileAutoStop = mAutoStopProfiler;
- profileStreamingOutput = mStreamingOutput;
+ profilerInfo = (mProfilerInfo != null && mProfilerInfo.profileFile != null) ?
+ new ProfilerInfo(mProfilerInfo) : null;
+ agent = mProfilerInfo != null ? mProfilerInfo.agent : null;
+ } else if (app.instr != null && app.instr.mProfileFile != null) {
+ profilerInfo = new ProfilerInfo(app.instr.mProfileFile, null, 0, false, false,
+ null);
}
+
boolean enableTrackAllocation = false;
if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
enableTrackAllocation = true;
+ processName + " with config " + getGlobalConfiguration());
ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
app.compat = compatibilityInfoForPackageLocked(appInfo);
- if (profileFd != null) {
- profileFd = profileFd.dup();
+
+ if (profilerInfo != null && profilerInfo.profileFd != null) {
+ profilerInfo.profileFd = profilerInfo.profileFd.dup();
}
- ProfilerInfo profilerInfo = profileFile == null ? null
- : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop,
- profileStreamingOutput);
// We deprecated Build.SERIAL and it is not accessible to
// apps that target the v2 security sandbox. Since access to
// the serial is now behind a permission we push down the value.
- String buildSerial = Build.UNKNOWN;
- if (appInfo.targetSandboxVersion != 2) {
- buildSerial = IDeviceIdentifiersPolicyService.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_IDENTIFIERS_SERVICE))
- .getSerial();
- }
+ String buildSerial = appInfo.targetSandboxVersion < 2
+ ? sTheRealBuildSerial : Build.UNKNOWN;
// Check if this is a secondary process that should be incorporated into some
// currently active instrumentation. (Note we do this AFTER all of the profiling
}
}
+ // If we were asked to attach an agent on startup, do so now, before we're binding
+ // application code.
+ if (agent != null) {
+ thread.attachAgent(agent);
+ }
+
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
mStackSupervisor.mActivityMetricsLogger.notifyBindApplication(app);
if (app.instr != null) {
mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
false /* processPausingActivities */, config);
if (stopProfiling) {
- if ((mProfileProc == r.app) && (mProfileFd != null)) {
- try {
- mProfileFd.close();
- } catch (IOException e) {
- }
+ if ((mProfileProc == r.app) && mProfilerInfo != null) {
clearProfilerLocked();
}
}
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
// Start looking for apps that are abusing wake locks.
- Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- mHandler.sendMessageDelayed(nmsg, mConstants.POWER_CHECK_DELAY);
+ Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_POWER_USE_MSG);
+ mHandler.sendMessageDelayed(nmsg, mConstants.POWER_CHECK_INTERVAL);
// Tell anyone interested that we are done booting!
SystemProperties.set("sys.boot_completed", "1");
}
@Override
- public final void backgroundResourcesReleased(IBinder token) {
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (this) {
- ActivityStack stack = ActivityRecord.getStackLocked(token);
- if (stack != null) {
- stack.backgroundResourcesReleased();
- }
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- @Override
public final void notifyLaunchTaskBehindComplete(IBinder token) {
mStackSupervisor.scheduleLaunchTaskBehindComplete(token);
}
@Override
public boolean isAppForeground(int uid) throws RemoteException {
+ int callerUid = Binder.getCallingUid();
+ if (UserHandle.isCore(callerUid) || callerUid == uid) {
+ return isAppForegroundInternal(uid);
+ }
+ return false;
+ }
+
+ private boolean isAppForegroundInternal(int uid) {
synchronized (this) {
UidRecord uidRec = mActiveUids.get(uid);
if (uidRec == null || uidRec.idle) {
// Activity supports picture-in-picture, now check that we can enter PiP at this
// point, if it is
if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode",
- false /* noThrow */, false /* beforeStopping */)) {
+ false /* beforeStopping */)) {
return false;
}
stack.setPictureInPictureActions(actions);
MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_ENTERED,
- r.supportsPictureInPictureWhilePausing);
+ r.supportsEnterPipOnTaskSwitch);
logPictureInPictureArgs(params);
};
}
}
- // If we're extending a persistable grant, then we always need to create
- // the grant data structure so that take/release APIs work
+ // Figure out the value returned when access is allowed
+ final int allowedResult;
if ((modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) {
- return targetUid;
+ // If we're extending a persistable grant, then we need to return
+ // "targetUid" so that we always create a grant data structure to
+ // support take/release APIs
+ allowedResult = targetUid;
+ } else {
+ // Otherwise, we can return "-1" to indicate that no grant data
+ // structures need to be created
+ allowedResult = -1;
}
if (targetUid >= 0) {
// No need to grant the target this permission.
if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
"Target " + targetPkg + " already has full permission to " + grantUri);
- return -1;
+ return allowedResult;
}
} else {
// First... there is no target package, so can anyone access it?
}
}
if (allowed) {
- return -1;
+ return allowedResult;
}
}
}
@Override
- public IActivityContainer createVirtualActivityContainer(IBinder parentActivityToken,
- IActivityContainerCallback callback) throws RemoteException {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "createActivityContainer()");
- synchronized (this) {
- if (parentActivityToken == null) {
- throw new IllegalArgumentException("parent token must not be null");
- }
- ActivityRecord r = ActivityRecord.forTokenLocked(parentActivityToken);
- if (r == null) {
- return null;
- }
- if (callback == null) {
- throw new IllegalArgumentException("callback must not be null");
- }
- return mStackSupervisor.createVirtualActivityContainer(r, callback);
- }
- }
-
- @Override
- public IActivityContainer createStackOnDisplay(int displayId) throws RemoteException {
+ public int createStackOnDisplay(int displayId) throws RemoteException {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "createStackOnDisplay()");
synchronized (this) {
final int stackId = mStackSupervisor.getNextStackId();
final ActivityStack stack =
mStackSupervisor.createStackOnDisplay(stackId, displayId, true /*onTop*/);
if (stack == null) {
- return null;
+ return INVALID_STACK_ID;
}
- return stack.mActivityContainer;
+ return stack.mStackId;
}
}
@Override
public int getActivityDisplayId(IBinder activityToken) throws RemoteException {
synchronized (this) {
- ActivityStack stack = ActivityRecord.getStackLocked(activityToken);
- if (stack != null && stack.mActivityContainer.isAttachedLocked()) {
- return stack.mActivityContainer.getDisplayId();
+ final ActivityStack stack = ActivityRecord.getStackLocked(activityToken);
+ if (stack != null && stack.mDisplayId != INVALID_DISPLAY) {
+ return stack.mDisplayId;
}
return DEFAULT_DISPLAY;
}
void onWakefulnessChanged(int wakefulness) {
synchronized(this) {
+ boolean wasAwake = mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE;
+ boolean isAwake = wakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE;
mWakefulness = wakefulness;
- updateSleepIfNeededLocked();
+
+ if (wasAwake != isAwake) {
+ // Also update state in a special way for running foreground services UI.
+ mServices.updateScreenStateLocked(isAwake);
+ sendNotifyVrManagerOfSleepState(!isAwake);
+ }
}
}
}
void updateSleepIfNeededLocked() {
- final boolean shouldSleep = shouldSleepLocked();
- if (mSleeping && !shouldSleep) {
- mSleeping = false;
- startTimeTrackingFocusedActivityLocked();
- mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
- mStackSupervisor.comeOutOfSleepIfNeededLocked();
- sendNotifyVrManagerOfSleepState(false);
- updateOomAdjLocked();
+ final boolean shouldSleep = !mStackSupervisor.hasAwakeDisplay();
+ final boolean wasSleeping = mSleeping;
+
+ if (!shouldSleep) {
+ // If wasSleeping is true, we need to wake up activity manager state from when
+ // we started sleeping. In either case, we need to apply the sleep tokens, which
+ // will wake up stacks or put them to sleep as appropriate.
+ if (wasSleeping) {
+ mSleeping = false;
+ startTimeTrackingFocusedActivityLocked();
+ mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
+ mStackSupervisor.comeOutOfSleepIfNeededLocked();
+ }
+ mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */);
+ if (wasSleeping) {
+ updateOomAdjLocked();
+ }
} else if (!mSleeping && shouldSleep) {
mSleeping = true;
if (mCurAppTimeTracker != null) {
}
mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
mStackSupervisor.goingToSleepLocked();
- sendNotifyVrManagerOfSleepState(true);
updateOomAdjLocked();
-
- // Initialize the wake times of all processes.
- checkExcessivePowerUsageLocked(false);
- mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- mHandler.sendMessageDelayed(nmsg, mConstants.POWER_CHECK_DELAY);
- }
-
- // Also update state in a special way for running foreground services UI.
- switch (mWakefulness) {
- case PowerManagerInternal.WAKEFULNESS_ASLEEP:
- case PowerManagerInternal.WAKEFULNESS_DREAMING:
- case PowerManagerInternal.WAKEFULNESS_DOZING:
- mServices.updateScreenStateLocked(false);
- break;
- case PowerManagerInternal.WAKEFULNESS_AWAKE:
- default:
- mServices.updateScreenStateLocked(true);
- break;
- }
- }
-
- private boolean shouldSleepLocked() {
- // Resume applications while running a voice interactor.
- if (mRunningVoice != null) {
- return false;
- }
-
- // TODO: Transform the lock screen state into a sleep token instead.
- switch (mWakefulness) {
- case PowerManagerInternal.WAKEFULNESS_AWAKE:
- case PowerManagerInternal.WAKEFULNESS_DREAMING:
- case PowerManagerInternal.WAKEFULNESS_DOZING:
- // Pause applications whenever the lock screen is shown or any sleep
- // tokens have been acquired.
- return mKeyguardController.isKeyguardShowing() || !mSleepTokens.isEmpty();
- case PowerManagerInternal.WAKEFULNESS_ASLEEP:
- default:
- // If we're asleep then pause applications unconditionally.
- return true;
}
}
synchronized(this) {
mShuttingDown = true;
+ mStackSupervisor.prepareForShutdownLocked();
updateEventDispatchingLocked();
timedout = mStackSupervisor.shutdownLocked(timeout);
}
}
@Override
- public void setLockScreenShown(boolean showing) {
+ public void setLockScreenShown(boolean showing, int secondaryDisplayShowing) {
if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
synchronized(this) {
long ident = Binder.clearCallingIdentity();
try {
- mKeyguardController.setKeyguardShown(showing);
+ mKeyguardController.setKeyguardShown(showing, secondaryDisplayShowing);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
+ sendNotifyVrManagerOfKeyguardState(showing);
}
@Override
}
}
mProfileApp = processName;
- mProfileFile = profilerInfo.profileFile;
- if (mProfileFd != null) {
- try {
- mProfileFd.close();
- } catch (IOException e) {
+
+ if (mProfilerInfo != null) {
+ if (mProfilerInfo.profileFd != null) {
+ try {
+ mProfilerInfo.profileFd.close();
+ } catch (IOException e) {
+ }
}
- mProfileFd = null;
}
- mProfileFd = profilerInfo.profileFd;
- mSamplingInterval = profilerInfo.samplingInterval;
- mAutoStopProfiler = profilerInfo.autoStopProfiler;
- mStreamingOutput = profilerInfo.streamingOutput;
+ mProfilerInfo = new ProfilerInfo(profilerInfo);
mProfileType = 0;
}
}
throw new IllegalArgumentException("Provided bugreport type is not correct, value: "
+ bugreportType);
}
+ // Always log caller, even if it does not have permission to dump.
+ String type = extraOptions == null ? "bugreport" : extraOptions;
+ Slog.i(TAG, type + " requested by UID " + Binder.getCallingUid());
+
enforceCallingPermission(android.Manifest.permission.DUMP, "requestBugReport");
if (extraOptions != null) {
SystemProperties.set("dumpstate.options", extraOptions);
timeout = getInputDispatchingTimeoutLocked(proc);
}
- if (!inputDispatchingTimedOut(proc, null, null, aboveSystem, reason)) {
+ if (inputDispatchingTimedOut(proc, null, null, aboveSystem, reason)) {
return -1;
}
return false;
}
- if (mDidDexOpt) {
- // Give more time since we were dexopting.
- mDidDexOpt = false;
- return false;
- }
-
if (proc.instr != null) {
Bundle info = new Bundle();
info.putString("shortMsg", "keyDispatchingTimedOut");
+ " couldn't be found");
return null;
}
+ if (activity.app == null || activity.app.thread == null) {
+ Slog.w(TAG, "enqueueAssistContext failed: no process for " + activity);
+ return null;
+ }
}
PendingAssistExtras pae;
}
final boolean translucentChanged = r.changeWindowTranslucency(true);
if (translucentChanged) {
- r.getStack().releaseBackgroundResources(r);
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
mWindowManager.setAppFullscreen(token, true);
}
@Override
- public boolean requestVisibleBehind(IBinder token, boolean visible) {
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (this) {
- final ActivityRecord r = ActivityRecord.isInStackLocked(token);
- if (r != null) {
- return mStackSupervisor.requestVisibleBehindLocked(r, visible);
- }
- }
- return false;
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- @Override
- public boolean isBackgroundVisibleBehind(IBinder token) {
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (this) {
- final ActivityStack stack = ActivityRecord.getStackLocked(token);
- final boolean visible = stack == null ? false : stack.hasVisibleBehindActivity();
- if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG_VISIBLE_BEHIND,
- "isBackgroundVisibleBehind: stack=" + stack + " visible=" + visible);
- return visible;
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- @Override
public Bundle getActivityOptions(IBinder token) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
- final ActivityOptions activityOptions = r.pendingOptions;
- r.pendingOptions = null;
+ final ActivityOptions activityOptions = r.takeOptionsLocked();
return activityOptions == null ? null : activityOptions.toBundle();
}
return null;
/**
* Schedule the given thread a normal scheduling priority.
*
- * @param newTid the tid of the thread to adjust the scheduling of.
+ * @param tid the tid of the thread to adjust the scheduling of.
* @param suppressLogs {@code true} if any error logging should be disabled.
*
* @return {@code true} if this succeeded.
if (!suppressLogs) {
Slog.w(TAG, "Failed to set scheduling policy, thread does not exist:\n" + e);
}
+ } catch (SecurityException e) {
+ if (!suppressLogs) {
+ Slog.w(TAG, "Failed to set scheduling policy, not allowed:\n" + e);
+ }
}
return false;
}
/**
* Schedule the given thread an FIFO scheduling priority.
*
- * @param newTid the tid of the thread to adjust the scheduling of.
+ * @param tid the tid of the thread to adjust the scheduling of.
* @param suppressLogs {@code true} if any error logging should be disabled.
*
* @return {@code true} if this succeeded.
if (!suppressLogs) {
Slog.w(TAG, "Failed to set scheduling policy, thread does not exist:\n" + e);
}
+ } catch (SecurityException e) {
+ if (!suppressLogs) {
+ Slog.w(TAG, "Failed to set scheduling policy, not allowed:\n" + e);
+ }
}
return false;
}
mContext.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
|| Settings.Global.getInt(
resolver, DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
- final boolean supportsPictureInPicture =
- mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow(mContext);
+ final boolean supportsPictureInPicture = supportsMultiWindow &&
+ mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
final boolean supportsSplitScreenMultiWindow =
ActivityManager.supportsSplitScreenMultiWindow(mContext);
final boolean supportsMultiDisplay = mContext.getPackageManager()
}
}
- public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
+ public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
traceLog.traceBegin("PhaseActivityManagerReady");
synchronized(this) {
if (mSystemReady) {
mSystemReady = true;
}
+ try {
+ sTheRealBuildSerial = IDeviceIdentifiersPolicyService.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDENTIFIERS_SERVICE))
+ .getSerial();
+ } catch (RemoteException e) {}
+
ArrayList<ProcessRecord> procsToKill = null;
synchronized(mPidsSelfLocked) {
for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
final ProcessRecord r = handleApplicationWtfInner(callingUid, callingPid, app, tag,
crashInfo);
- final boolean isFatal = "eng".equals(Build.TYPE) || Settings.Global
+ final boolean isFatal = Build.IS_ENG || Settings.Global
.getInt(mContext.getContentResolver(), Settings.Global.WTF_IS_FATAL, 0) != 0;
final boolean isSystem = (r == null) || r.persistent;
}
sb.append("\n");
}
+ if (process.info.isInstantApp()) {
+ sb.append("Instant-App: true\n");
+ }
}
}
this, in, out, err, args, callback, resultReceiver);
}
+ SleepToken acquireSleepToken(String tag, int displayId) {
+ synchronized (this) {
+ final SleepToken token = mStackSupervisor.createSleepTokenLocked(tag, displayId);
+ updateSleepIfNeededLocked();
+ return token;
+ }
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
}
} else if ("starter".equals(cmd)) {
synchronized (this) {
- dumpActivityStarterLocked(pw);
+ dumpActivityStarterLocked(pw, dumpPackage);
}
} else if ("recents".equals(cmd) || "r".equals(cmd)) {
synchronized (this) {
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- dumpActivityStarterLocked(pw);
+ dumpActivityStarterLocked(pw, dumpPackage);
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- dumpActivityStarterLocked(pw);
+ dumpActivityStarterLocked(pw, dumpPackage);
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
private void dumpLastANRLocked(PrintWriter pw) {
- pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity lastanr)");
+ pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
if (mLastANRState == null) {
pw.println(" <no ANR has occurred since boot>");
} else {
}
}
- private void dumpActivityStarterLocked(PrintWriter pw) {
- pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity starter)");
- mActivityStarter.dump(pw, "");
+ private void dumpActivityStarterLocked(PrintWriter pw, String dumpPackage) {
+ pw.println("ACTIVITY MANAGER STARTER (dumpsys activity starter)");
+ mActivityStarter.dump(pw, "", dumpPackage);
}
void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
if (dumpPackage == null) {
pw.println(" mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness));
- pw.println(" mSleepTokens=" + mSleepTokens);
+ pw.println(" mSleepTokens=" + mStackSupervisor.mSleepTokens);
pw.println(" mSleeping=" + mSleeping);
pw.println(" mShuttingDown=" + mShuttingDown + " mTestPssMode=" + mTestPssMode);
if (mRunningVoice != null) {
pw.println(" mTrackAllocationApp=" + mTrackAllocationApp);
}
}
- if (mProfileApp != null || mProfileProc != null || mProfileFile != null
- || mProfileFd != null) {
+ if (mProfileApp != null || mProfileProc != null || (mProfilerInfo != null &&
+ (mProfilerInfo.profileFile != null || mProfilerInfo.profileFd != null))) {
if (dumpPackage == null || dumpPackage.equals(mProfileApp)) {
if (needSep) {
pw.println();
needSep = false;
}
pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
- pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
- pw.println(" mSamplingInterval=" + mSamplingInterval + " mAutoStopProfiler="
- + mAutoStopProfiler + " mStreamingOutput=" + mStreamingOutput);
- pw.println(" mProfileType=" + mProfileType);
+ if (mProfilerInfo != null) {
+ pw.println(" mProfileFile=" + mProfilerInfo.profileFile + " mProfileFd=" +
+ mProfilerInfo.profileFd);
+ pw.println(" mSamplingInterval=" + mProfilerInfo.samplingInterval +
+ " mAutoStopProfiler=" + mProfilerInfo.autoStopProfiler +
+ " mStreamingOutput=" + mProfilerInfo.streamingOutput);
+ pw.println(" mProfileType=" + mProfileType);
+ }
}
}
if (mNativeDebuggingApp != null) {
pw.println(" mBooting=" + mBooting
+ " mCallFinishBooting=" + mCallFinishBooting
+ " mBootAnimationComplete=" + mBootAnimationComplete);
- pw.print(" mLastPowerCheckRealtime=");
- TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
- pw.println("");
pw.print(" mLastPowerCheckUptime=");
TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
pw.println("");
Collections.sort(list, comparator);
- final long curRealtime = SystemClock.elapsedRealtime();
- final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
final long curUptime = SystemClock.uptimeMillis();
final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
if (r.setProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
- if (r.lastWakeTime != 0) {
- long wtime;
- BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
- synchronized (stats) {
- wtime = stats.getProcessWakeTime(r.info.uid,
- r.pid, curRealtime);
- }
- long timeUsed = wtime - r.lastWakeTime;
- pw.print(prefix);
- pw.print(" ");
- pw.print("keep awake over ");
- TimeUtils.formatDuration(realtimeSince, pw);
- pw.print(" used ");
- TimeUtils.formatDuration(timeUsed, pw);
- pw.print(" (");
- pw.print((timeUsed*100)/realtimeSince);
- pw.println("%)");
- }
if (r.lastCpuTime != 0) {
long timeUsed = r.curCpuTime - r.lastCpuTime;
pw.print(prefix);
}
} catch (IOException e) {
if (!isCheckinRequest) {
- pw.println("Got IoException!");
+ pw.println("Got IoException! " + e);
pw.flush();
}
} catch (RemoteException e) {
if (!isCheckinRequest) {
- pw.println("Got RemoteException!");
+ pw.println("Got RemoteException! " + e);
pw.flush();
}
}
ArrayList<MemItem> catMems = new ArrayList<MemItem>();
catMems.add(new MemItem("Native", "Native", nativePss, nativeSwapPss, -1));
- final MemItem dalvikItem =
- new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, -2);
- if (dalvikSubitemPss.length > 0) {
- dalvikItem.subitems = new ArrayList<MemItem>();
- for (int j=0; j<dalvikSubitemPss.length; j++) {
- final String name = Debug.MemoryInfo.getOtherLabel(
- Debug.MemoryInfo.NUM_OTHER_STATS + j);
- dalvikItem.subitems.add(new MemItem(name, name, dalvikSubitemPss[j],
- dalvikSubitemSwapPss[j], j));
- }
- }
- catMems.add(dalvikItem);
+ final int dalvikId = -2;
+ catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, dalvikId));
catMems.add(new MemItem("Unknown", "Unknown", otherPss, otherSwapPss, -3));
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
String label = Debug.MemoryInfo.getOtherLabel(j);
catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], j));
}
+ if (dalvikSubitemPss.length > 0) {
+ // Add dalvik subitems.
+ for (MemItem memItem : catMems) {
+ int memItemStart = 0, memItemEnd = 0;
+ if (memItem.id == dalvikId) {
+ memItemStart = Debug.MemoryInfo.OTHER_DVK_STAT_DALVIK_START;
+ memItemEnd = Debug.MemoryInfo.OTHER_DVK_STAT_DALVIK_END;
+ } else if (memItem.id == Debug.MemoryInfo.OTHER_DALVIK_OTHER) {
+ memItemStart = Debug.MemoryInfo.OTHER_DVK_STAT_DALVIK_OTHER_START;
+ memItemEnd = Debug.MemoryInfo.OTHER_DVK_STAT_DALVIK_OTHER_END;
+ } else if (memItem.id == Debug.MemoryInfo.OTHER_DEX) {
+ memItemStart = Debug.MemoryInfo.OTHER_DVK_STAT_DEX_START;
+ memItemEnd = Debug.MemoryInfo.OTHER_DVK_STAT_DEX_END;
+ } else if (memItem.id == Debug.MemoryInfo.OTHER_ART) {
+ memItemStart = Debug.MemoryInfo.OTHER_DVK_STAT_ART_START;
+ memItemEnd = Debug.MemoryInfo.OTHER_DVK_STAT_ART_END;
+ } else {
+ continue; // No subitems, continue.
+ }
+ memItem.subitems = new ArrayList<MemItem>();
+ for (int j=memItemStart; j<=memItemEnd; j++) {
+ final String name = Debug.MemoryInfo.getOtherLabel(
+ Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ memItem.subitems.add(new MemItem(name, name, dalvikSubitemPss[j],
+ dalvikSubitemSwapPss[j], j));
+ }
+ }
+ }
ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
for (int j=0; j<oomPss.length; j++) {
&& config.navigation == Configuration.NAVIGATION_NONAV);
int modeType = config.uiMode & Configuration.UI_MODE_TYPE_MASK;
final boolean uiModeSupportsDialogs = (modeType != Configuration.UI_MODE_TYPE_CAR
- && !(modeType == Configuration.UI_MODE_TYPE_WATCH && "user".equals(Build.TYPE))
+ && !(modeType == Configuration.UI_MODE_TYPE_WATCH && Build.IS_USER)
&& modeType != Configuration.UI_MODE_TYPE_TELEVISION
&& modeType != Configuration.UI_MODE_TYPE_VR_HEADSET);
return inputMethodExists && uiModeSupportsDialogs;
if (DEBUG_PSS) Slog.d(TAG_PSS,
"Requesting dump heap from "
+ myProc + " to " + heapdumpFile);
- thread.dumpHeap(true, heapdumpFile.toString(), fd);
+ thread.dumpHeap(/* managed= */ true,
+ /* mallocInfo= */ false, /* runGc= */ false,
+ heapdumpFile.toString(), fd);
} catch (RemoteException e) {
}
}
}
}
- final void checkExcessivePowerUsageLocked(boolean doKills) {
+ final void checkExcessivePowerUsageLocked() {
updateCpuStatsNow();
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- boolean doWakeKills = doKills;
- boolean doCpuKills = doKills;
- if (mLastPowerCheckRealtime == 0) {
- doWakeKills = false;
- }
+ boolean doCpuKills = true;
if (mLastPowerCheckUptime == 0) {
doCpuKills = false;
}
- if (stats.isScreenOn()) {
- doWakeKills = false;
- }
- final long curRealtime = SystemClock.elapsedRealtime();
- final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
final long curUptime = SystemClock.uptimeMillis();
final long uptimeSince = curUptime - mLastPowerCheckUptime;
- mLastPowerCheckRealtime = curRealtime;
mLastPowerCheckUptime = curUptime;
- if (realtimeSince < mConstants.WAKE_LOCK_MIN_CHECK_DURATION) {
- doWakeKills = false;
- }
- if (uptimeSince < mConstants.CPU_MIN_CHECK_DURATION) {
- doCpuKills = false;
- }
int i = mLruProcesses.size();
while (i > 0) {
i--;
ProcessRecord app = mLruProcesses.get(i);
if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
- long wtime;
- synchronized (stats) {
- wtime = stats.getProcessWakeTime(app.info.uid,
- app.pid, curRealtime);
+ if (app.lastCpuTime <= 0) {
+ continue;
}
- long wtimeUsed = wtime - app.lastWakeTime;
long cputimeUsed = app.curCpuTime - app.lastCpuTime;
if (DEBUG_POWER) {
StringBuilder sb = new StringBuilder(128);
- sb.append("Wake for ");
- app.toShortString(sb);
- sb.append(": over ");
- TimeUtils.formatDuration(realtimeSince, sb);
- sb.append(" used ");
- TimeUtils.formatDuration(wtimeUsed, sb);
- sb.append(" (");
- sb.append((wtimeUsed*100)/realtimeSince);
- sb.append("%)");
- Slog.i(TAG_POWER, sb.toString());
- sb.setLength(0);
sb.append("CPU for ");
app.toShortString(sb);
sb.append(": over ");
sb.append("%)");
Slog.i(TAG_POWER, sb.toString());
}
- // If a process has held a wake lock for more
- // than 50% of the time during this period,
- // that sounds bad. Kill!
- if (doWakeKills && realtimeSince > 0
- && ((wtimeUsed*100)/realtimeSince) >= 50) {
- synchronized (stats) {
- stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
- realtimeSince, wtimeUsed);
+ // If the process has used too much CPU over the last duration, the
+ // user probably doesn't want this, so kill!
+ if (doCpuKills && uptimeSince > 0) {
+ // What is the limit for this process?
+ int cpuLimit;
+ long checkDur = curUptime - app.whenUnimportant;
+ if (checkDur <= mConstants.POWER_CHECK_INTERVAL) {
+ cpuLimit = mConstants.POWER_CHECK_MAX_CPU_1;
+ } else if (checkDur <= (mConstants.POWER_CHECK_INTERVAL*2)
+ || app.setProcState <= ActivityManager.PROCESS_STATE_HOME) {
+ cpuLimit = mConstants.POWER_CHECK_MAX_CPU_2;
+ } else if (checkDur <= (mConstants.POWER_CHECK_INTERVAL*3)) {
+ cpuLimit = mConstants.POWER_CHECK_MAX_CPU_3;
+ } else {
+ cpuLimit = mConstants.POWER_CHECK_MAX_CPU_4;
}
- app.kill("excessive wake held " + wtimeUsed + " during " + realtimeSince, true);
- app.baseProcessTracker.reportExcessiveWake(app.pkgList);
- } else if (doCpuKills && uptimeSince > 0
- && ((cputimeUsed*100)/uptimeSince) >= 25) {
- synchronized (stats) {
- stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
- uptimeSince, cputimeUsed);
+ if (((cputimeUsed*100)/uptimeSince) >= cpuLimit) {
+ synchronized (stats) {
+ stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
+ uptimeSince, cputimeUsed);
+ }
+ app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince
+ + " dur=" + checkDur + " limit=" + cpuLimit, true);
+ app.baseProcessTracker.reportExcessiveCpu(app.pkgList);
}
- app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince, true);
- app.baseProcessTracker.reportExcessiveCpu(app.pkgList);
- } else {
- app.lastWakeTime = wtime;
- app.lastCpuTime = app.curCpuTime;
}
+ app.lastCpuTime = app.curCpuTime;
}
}
}
int changes = 0;
if (app.curAdj != app.setAdj) {
- ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj);
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Set " + app.pid + " " + app.processName + " adj " + app.curAdj + ": "
- + app.adjType);
+ ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.info.uid) {
+ String msg = "Set " + app.pid + " " + app.processName + " adj "
+ + app.curAdj + ": " + app.adjType;
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
+ }
app.setAdj = app.curAdj;
app.verifiedAdj = ProcessList.INVALID_ADJ;
}
if (app.setSchedGroup != app.curSchedGroup) {
int oldSchedGroup = app.setSchedGroup;
app.setSchedGroup = app.curSchedGroup;
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Setting sched group of " + app.processName
- + " to " + app.curSchedGroup);
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.uid) {
+ String msg = "Setting sched group of " + app.processName
+ + " to " + app.curSchedGroup;
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
+ }
if (app.waitingToKill != null && app.curReceivers.isEmpty()
&& app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
app.kill(app.waitingToKill, true);
app.curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
mVrController.onTopProcChangedLocked(app);
if (mUseFifoUiScheduling) {
- // Reset UI pipeline to SCHED_OTHER
- setThreadScheduler(app.pid, SCHED_OTHER, 0);
- setThreadPriority(app.pid, app.savedPriority);
- if (app.renderThreadTid != 0) {
- setThreadScheduler(app.renderThreadTid,
- SCHED_OTHER, 0);
- setThreadPriority(app.renderThreadTid, -4);
+ try {
+ // Reset UI pipeline to SCHED_OTHER
+ setThreadScheduler(app.pid, SCHED_OTHER, 0);
+ setThreadPriority(app.pid, app.savedPriority);
+ if (app.renderThreadTid != 0) {
+ setThreadScheduler(app.renderThreadTid,
+ SCHED_OTHER, 0);
+ setThreadPriority(app.renderThreadTid, -4);
+ }
+ } catch (IllegalArgumentException e) {
+ Slog.w(TAG,
+ "Failed to set scheduling policy, thread does not exist:\n"
+ + e);
+ } catch (SecurityException e) {
+ Slog.w(TAG, "Failed to set scheduling policy, not allowed:\n" + e);
}
} else {
// Reset priority for top app UI and render threads
"Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
}
if (app.setProcState != app.curProcState) {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Proc state change of " + app.processName
- + " to " + app.curProcState);
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.uid) {
+ String msg = "Proc state change of " + app.processName
+ + " to " + app.curProcState;
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
+ }
boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE;
boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE;
if (setImportant && !curImportant) {
// This app is no longer something we consider important enough to allow to
// use arbitrary amounts of battery power. Note
- // its current wake lock time to later know to kill it if
+ // its current CPU time to later know to kill it if
// it is not behaving well.
- BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- synchronized (stats) {
- app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
- app.pid, nowElapsed);
- }
- app.lastCpuTime = app.curCpuTime;
-
+ app.whenUnimportant = now;
+ app.lastCpuTime = 0;
}
// Inform UsageStats of important process state change
// Must be called before updating setProcState
}
if (uidRec != null) {
uidRec.pendingChange = pendingChange;
- if (change == UidRecord.CHANGE_GONE && !uidRec.idle) {
+ if ((change & UidRecord.CHANGE_GONE) != 0 && !uidRec.idle) {
// If this uid is going away, and we haven't yet reported it is gone,
// then do so now.
- change = UidRecord.CHANGE_GONE_IDLE;
+ change |= UidRecord.CHANGE_IDLE;
}
} else if (uid < 0) {
throw new IllegalArgumentException("No UidRecord or uid");
mPendingUidChanges.add(pendingChange);
} else {
pendingChange = uidRec.pendingChange;
- if (change == UidRecord.CHANGE_GONE && pendingChange.change == UidRecord.CHANGE_IDLE) {
- change = UidRecord.CHANGE_GONE_IDLE;
+ // If there is no change in idle or active state, then keep whatever was pending.
+ if ((change & (UidRecord.CHANGE_IDLE | UidRecord.CHANGE_ACTIVE)) == 0) {
+ change |= (pendingChange.change & (UidRecord.CHANGE_IDLE
+ | UidRecord.CHANGE_ACTIVE));
+ }
+ // If there is no change in cached or uncached state, then keep whatever was pending.
+ if ((change & (UidRecord.CHANGE_CACHED | UidRecord.CHANGE_UNCACHED)) == 0) {
+ change |= (pendingChange.change & (UidRecord.CHANGE_CACHED
+ | UidRecord.CHANGE_UNCACHED));
+ }
+ // If this is a report of the UID being gone, then we shouldn't keep any previous
+ // report of it being active or cached. (That is, a gone uid is never active,
+ // and never cached.)
+ if ((change & UidRecord.CHANGE_GONE) != 0) {
+ change &= ~(UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_CACHED);
+ if (!uidRec.idle) {
+ // If this uid is going away, and we haven't yet reported it is gone,
+ // then do so now.
+ change |= UidRecord.CHANGE_IDLE;
+ }
}
}
pendingChange.change = change;
pendingChange.ephemeral = uidRec != null ? uidRec.ephemeral : isEphemeralLocked(uid);
pendingChange.procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0;
if (uidRec != null) {
+ uidRec.lastReportedChange = change;
uidRec.updateLastDispatchedProcStateSeq(change);
}
// Directly update the power manager, since we sit on top of it and it is critical
// it be kept in sync (so wake locks will be held as soon as appropriate).
if (mLocalPowerManager != null) {
- switch (change) {
- case UidRecord.CHANGE_GONE:
- case UidRecord.CHANGE_GONE_IDLE:
- mLocalPowerManager.uidGone(pendingChange.uid);
- break;
- case UidRecord.CHANGE_IDLE:
- mLocalPowerManager.uidIdle(pendingChange.uid);
- break;
- case UidRecord.CHANGE_ACTIVE:
- mLocalPowerManager.uidActive(pendingChange.uid);
- break;
- default:
- mLocalPowerManager.updateUidProcState(pendingChange.uid,
- pendingChange.processState);
- break;
+ // TO DO: dispatch cached/uncached changes here, so we don't need to report
+ // all proc state changes.
+ if ((change & UidRecord.CHANGE_ACTIVE) != 0) {
+ mLocalPowerManager.uidActive(pendingChange.uid);
+ }
+ if ((change & UidRecord.CHANGE_IDLE) != 0) {
+ mLocalPowerManager.uidIdle(pendingChange.uid);
+ }
+ if ((change & UidRecord.CHANGE_GONE) != 0) {
+ mLocalPowerManager.uidGone(pendingChange.uid);
+ } else {
+ mLocalPowerManager.updateUidProcState(pendingChange.uid,
+ pendingChange.processState);
}
}
}
requestPssAllProcsLocked(now, false, mProcessStats.isMemFactorLowered());
}
+ ArrayList<UidRecord> becameIdle = null;
+
// Update from any uid changes.
if (mLocalPowerManager != null) {
mLocalPowerManager.startUidChanges();
for (int i=mActiveUids.size()-1; i>=0; i--) {
final UidRecord uidRec = mActiveUids.valueAt(i);
int uidChange = UidRecord.CHANGE_PROCSTATE;
- if (uidRec.setProcState != uidRec.curProcState
- || uidRec.setWhitelist != uidRec.curWhitelist) {
+ if (uidRec.curProcState != ActivityManager.PROCESS_STATE_NONEXISTENT
+ && (uidRec.setProcState != uidRec.curProcState
+ || uidRec.setWhitelist != uidRec.curWhitelist)) {
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"Changes in " + uidRec + ": proc state from " + uidRec.setProcState
+ " to " + uidRec.curProcState + ", whitelist from " + uidRec.setWhitelist
mConstants.BACKGROUND_SETTLE_TIME);
}
}
+ if (uidRec.idle && !uidRec.setIdle) {
+ uidChange = UidRecord.CHANGE_IDLE;
+ if (becameIdle == null) {
+ becameIdle = new ArrayList<>();
+ }
+ becameIdle.add(uidRec);
+ }
} else {
if (uidRec.idle) {
uidChange = UidRecord.CHANGE_ACTIVE;
}
uidRec.lastBackgroundTime = 0;
}
+ final boolean wasCached = uidRec.setProcState
+ > ActivityManager.PROCESS_STATE_RECEIVER;
+ final boolean isCached = uidRec.curProcState
+ > ActivityManager.PROCESS_STATE_RECEIVER;
+ if (wasCached != isCached ||
+ uidRec.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
+ uidChange |= isCached ? UidRecord.CHANGE_CACHED : UidRecord.CHANGE_UNCACHED;
+ }
uidRec.setProcState = uidRec.curProcState;
uidRec.setWhitelist = uidRec.curWhitelist;
+ uidRec.setIdle = uidRec.idle;
enqueueUidChangeLocked(uidRec, -1, uidChange);
noteUidProcessState(uidRec.uid, uidRec.curProcState);
if (uidRec.foregroundServices) {
mLocalPowerManager.finishUidChanges();
}
+ if (becameIdle != null) {
+ // If we have any new uids that became idle this time, we need to make sure
+ // they aren't left with running services.
+ for (int i = becameIdle.size() - 1; i >= 0; i--) {
+ mServices.stopInBackgroundLocked(becameIdle.get(i).uid);
+ }
+ }
+
if (mProcessStats.shouldWriteNowLocked(now)) {
mHandler.post(new Runnable() {
@Override public void run() {
userId == UserHandle.getUserId(uidRec.uid)) {
EventLogTags.writeAmUidIdle(uidRec.uid);
uidRec.idle = true;
+ uidRec.setIdle = true;
Slog.w(TAG, "Idling uid " + UserHandle.formatUid(uidRec.uid)
+ " from package " + packageName + " user " + userId);
doStopUidLocked(uidRec.uid, uidRec);
if (bgTime <= maxBgTime) {
EventLogTags.writeAmUidIdle(uidRec.uid);
uidRec.idle = true;
+ uidRec.setIdle = true;
doStopUidLocked(uidRec.uid, uidRec);
} else {
if (nextTime == 0 || nextTime > bgTime) {
}
private void clearProfilerLocked() {
- if (mProfileFd != null) {
+ if (mProfilerInfo !=null && mProfilerInfo.profileFd != null) {
try {
- mProfileFd.close();
+ mProfilerInfo.profileFd.close();
} catch (IOException e) {
}
}
mProfileApp = null;
mProfileProc = null;
- mProfileFile = null;
- mProfileType = 0;
- mAutoStopProfiler = false;
- mStreamingOutput = false;
- mSamplingInterval = 0;
+ mProfilerInfo = null;
}
public boolean profileControl(String process, int userId, boolean start,
proc.thread.profilerControl(start, profilerInfo, profileType);
fd = null;
try {
- mProfileFd.close();
+ mProfilerInfo.profileFd.close();
} catch (IOException e) {
}
- mProfileFd = null;
+ mProfilerInfo.profileFd = null;
} else {
stopProfilerLocked(proc, profileType);
if (profilerInfo != null && profilerInfo.profileFd != null) {
return proc;
}
- public boolean dumpHeap(String process, int userId, boolean managed,
- String path, ParcelFileDescriptor fd) throws RemoteException {
+ public boolean dumpHeap(String process, int userId, boolean managed, boolean mallocInfo,
+ boolean runGc, String path, ParcelFileDescriptor fd) throws RemoteException {
try {
synchronized (this) {
}
}
- proc.thread.dumpHeap(managed, path, fd);
+ proc.thread.dumpHeap(managed, mallocInfo, runGc, path, fd);
fd = null;
return true;
}
}
if (DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path);
mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG);
+
+ // Forced gc to clean up the remnant hprof fd.
+ Runtime.getRuntime().gc();
}
}
}
@Override
- public SleepToken acquireSleepToken(String tag) {
+ public SleepToken acquireSleepToken(String tag, int displayId) {
Preconditions.checkNotNull(tag);
-
- synchronized (ActivityManagerService.this) {
- SleepTokenImpl token = new SleepTokenImpl(tag);
- mSleepTokens.add(token);
- updateSleepIfNeededLocked();
- return token;
- }
+ return ActivityManagerService.this.acquireSleepToken(tag, displayId);
}
@Override
synchronized (ActivityManagerService.this) {
ActivityManagerService.this.onUserStoppedLocked(userId);
}
+ mBatteryStatsService.onUserRemoved(userId);
}
@Override
Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
return;
}
- ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration);
+ synchronized (ActivityManagerService.this) {
+ ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration);
+ }
}
@Override
// We might change the visibilities here, so prepare an empty app transition which
// might be overridden later if we actually change visibilities.
- mWindowManager.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
+ final boolean wasTransitionSet =
+ mWindowManager.getPendingAppTransition() != TRANSIT_NONE;
+ if (!wasTransitionSet) {
+ mWindowManager.prepareAppTransition(TRANSIT_NONE,
+ false /* alwaysKeepCurrent */);
+ }
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- mWindowManager.executeAppTransition();
+
+ // If there was a transition set already we don't want to interfere with it as we
+ // might be starting it too early.
+ if (!wasTransitionSet) {
+ mWindowManager.executeAppTransition();
+ }
}
if (callback != null) {
callback.run();
@Override
public void notifyKeyguardTrustedChanged() {
synchronized (ActivityManagerService.this) {
- if (mKeyguardController.isKeyguardShowing()) {
+ if (mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) {
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
}
pw.println(" Reason: " + reason);
}
pw.println();
- mActivityStarter.dump(pw, " ");
+ mActivityStarter.dump(pw, " ", null);
pw.println();
pw.println("-------------------------------------------------------------------------------");
dumpActivitiesLocked(null /* fd */, pw, null /* args */, 0 /* opti */,
mLastANRState = null;
}
}
+
+ @Override
+ public void setFocusedActivity(IBinder token) {
+ synchronized (ActivityManagerService.this) {
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r == null) {
+ throw new IllegalArgumentException(
+ "setFocusedActivity: No activity record matching token=" + token);
+ }
+ if (mStackSupervisor.moveFocusableActivityStackToFrontLocked(
+ r, "setFocusedActivity")) {
+ mStackSupervisor.resumeFocusedStackTopActivityLocked();
+ }
+ }
+ }
+
+ @Override
+ public boolean hasRunningActivity(int uid, @Nullable String packageName) {
+ if (packageName == null) return false;
+
+ synchronized (ActivityManagerService.this) {
+ for (int i = 0; i < mLruProcesses.size(); i++) {
+ final ProcessRecord processRecord = mLruProcesses.get(i);
+ if (processRecord.uid == uid) {
+ for (int j = 0; j < processRecord.activities.size(); j++) {
+ final ActivityRecord activityRecord = processRecord.activities.get(j);
+ if (packageName.equals(activityRecord.packageName)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
}
/**
record.networkStateLock.wait(mWaitForNetworkTimeoutMs);
record.waitingForNetwork = false;
final long totalTime = SystemClock.uptimeMillis() - startTime;
- if (totalTime >= mWaitForNetworkTimeoutMs) {
+ if (totalTime >= mWaitForNetworkTimeoutMs || DEBUG_NETWORK) {
Slog.wtf(TAG_NETWORK, "Total time waited for network rules to get updated: "
+ totalTime + ". Uid: " + callingUid + " procStateSeq: "
+ procStateSeq + " UidRec: " + record
}
}
- private final class SleepTokenImpl extends SleepToken {
- private final String mTag;
- private final long mAcquireTime;
-
- public SleepTokenImpl(String tag) {
- mTag = tag;
- mAcquireTime = SystemClock.uptimeMillis();
- }
-
- @Override
- public void release() {
- synchronized (ActivityManagerService.this) {
- if (mSleepTokens.remove(this)) {
- updateSleepIfNeededLocked();
- }
- }
- }
-
- @Override
- public String toString() {
- return "{\"" + mTag + "\", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
- }
- }
-
/**
* An implementation of IAppTask, that allows an app to manage its own tasks via
* {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that
}
return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
resolvedType, null, null, null, null, 0, 0, null, null,
- null, bOptions, false, callingUser, null, tr, "AppTaskImpl");
+ null, bOptions, false, callingUser, tr, "AppTaskImpl");
}
@Override
if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
try {
final ApplicationInfo ai = AppGlobals.getPackageManager()
- .getApplicationInfo(packageName, 0 /*flags*/, app.userId);
+ .getApplicationInfo(packageName, STOCK_PM_FLAGS, app.userId);
if (ai != null) {
app.thread.scheduleApplicationInfoChanged(ai);
}
return mNmi != null;
}
}
+
+ @Override
+ public void setShowWhenLocked(IBinder token, boolean showWhenLocked)
+ throws RemoteException {
+ synchronized (this) {
+ final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+ if (r == null) {
+ return;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ r.setShowWhenLocked(showWhenLocked);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ @Override
+ public void setTurnScreenOn(IBinder token, boolean turnScreenOn) throws RemoteException {
+ synchronized (this) {
+ final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+ if (r == null) {
+ return;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ r.setTurnScreenOn(turnScreenOn);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
}