TaskRecord.java revision fdcc4d4235c829a41b4d23043431bb8fa915a440
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.am; 18 19import static android.app.ActivityManager.DOCKED_STACK_ID; 20import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID; 21import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID; 22import static android.app.ActivityManager.HOME_STACK_ID; 23import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; 24import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; 25import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS; 26import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT; 27import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED; 28import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER; 29import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; 30import static com.android.server.am.ActivityManagerDebugConfig.*; 31import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; 32import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; 33import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; 34 35import android.app.Activity; 36import android.app.ActivityManager; 37import android.app.ActivityManager.TaskThumbnail; 38import android.app.ActivityManager.TaskDescription; 39import android.app.ActivityOptions; 40import android.app.AppGlobals; 41import android.content.ComponentName; 42import android.content.Intent; 43import android.content.pm.ActivityInfo; 44import android.content.pm.ApplicationInfo; 45import android.content.pm.IPackageManager; 46import android.content.pm.PackageManager; 47import android.content.res.Configuration; 48import android.graphics.Bitmap; 49import android.graphics.Rect; 50import android.os.Debug; 51import android.os.ParcelFileDescriptor; 52import android.os.RemoteException; 53import android.os.UserHandle; 54import android.service.voice.IVoiceInteractionSession; 55import android.util.DisplayMetrics; 56import android.util.Slog; 57import com.android.internal.app.IVoiceInteractor; 58import com.android.internal.util.XmlUtils; 59import org.xmlpull.v1.XmlPullParser; 60import org.xmlpull.v1.XmlPullParserException; 61import org.xmlpull.v1.XmlSerializer; 62 63import java.io.File; 64import java.io.IOException; 65import java.io.PrintWriter; 66import java.util.ArrayList; 67import java.util.Objects; 68 69final class TaskRecord { 70 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM; 71 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; 72 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; 73 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; 74 private static final String TAG_TASKS = TAG + POSTFIX_TASKS; 75 76 static final String ATTR_TASKID = "task_id"; 77 private static final String TAG_INTENT = "intent"; 78 private static final String TAG_AFFINITYINTENT = "affinity_intent"; 79 static final String ATTR_REALACTIVITY = "real_activity"; 80 private static final String ATTR_ORIGACTIVITY = "orig_activity"; 81 private static final String TAG_ACTIVITY = "activity"; 82 private static final String ATTR_AFFINITY = "affinity"; 83 private static final String ATTR_ROOT_AFFINITY = "root_affinity"; 84 private static final String ATTR_ROOTHASRESET = "root_has_reset"; 85 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents"; 86 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode"; 87 private static final String ATTR_USERID = "user_id"; 88 private static final String ATTR_EFFECTIVE_UID = "effective_uid"; 89 private static final String ATTR_TASKTYPE = "task_type"; 90 private static final String ATTR_FIRSTACTIVETIME = "first_active_time"; 91 private static final String ATTR_LASTACTIVETIME = "last_active_time"; 92 private static final String ATTR_LASTDESCRIPTION = "last_description"; 93 private static final String ATTR_LASTTIMEMOVED = "last_time_moved"; 94 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity"; 95 static final String ATTR_TASK_AFFILIATION = "task_affiliation"; 96 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation"; 97 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation"; 98 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color"; 99 private static final String ATTR_CALLING_UID = "calling_uid"; 100 private static final String ATTR_CALLING_PACKAGE = "calling_package"; 101 private static final String ATTR_RESIZEABLE = "resizeable"; 102 private static final String ATTR_PRIVILEGED = "privileged"; 103 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds"; 104 105 private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail"; 106 107 static final boolean IGNORE_RETURN_TO_RECENTS = true; 108 109 static final int INVALID_TASK_ID = -1; 110 111 final int taskId; // Unique identifier for this task. 112 String affinity; // The affinity name for this task, or null; may change identity. 113 String rootAffinity; // Initial base affinity, or null; does not change from initial root. 114 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task 115 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app 116 Intent intent; // The original intent that started the task. 117 Intent affinityIntent; // Intent of affinity-moved activity that started this task. 118 int effectiveUid; // The current effective uid of the identity of this task. 119 ComponentName origActivity; // The non-alias activity component of the intent. 120 ComponentName realActivity; // The actual activity component that started the task. 121 long firstActiveTime; // First time this task was active. 122 long lastActiveTime; // Last time this task was active, including sleep. 123 boolean inRecents; // Actually in the recents list? 124 boolean isAvailable; // Is the activity available to be launched? 125 boolean rootWasReset; // True if the intent at the root of the task had 126 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag. 127 boolean autoRemoveRecents; // If true, we should automatically remove the task from 128 // recents when activity finishes 129 boolean askedCompatMode;// Have asked the user about compat mode for this task. 130 boolean hasBeenVisible; // Set if any activities in the task have been visible to the user. 131 132 String stringName; // caching of toString() result. 133 int userId; // user for which this task was created 134 135 int numFullscreen; // Number of fullscreen activities. 136 137 boolean mResizeable; // Activities in the task resizeable. Based on the resizable setting of 138 // the root activity. 139 int mLockTaskMode; // Which tasklock mode to launch this task in. One of 140 // ActivityManager.LOCK_TASK_LAUNCH_MODE_* 141 private boolean mPrivileged; // The root activity application of this task holds 142 // privileged permissions. 143 144 /** Can't be put in lockTask mode. */ 145 final static int LOCK_TASK_AUTH_DONT_LOCK = 0; 146 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */ 147 final static int LOCK_TASK_AUTH_PINNABLE = 1; 148 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */ 149 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2; 150 /** Can enter lockTask without user approval. Can start over existing lockTask task. */ 151 final static int LOCK_TASK_AUTH_WHITELISTED = 3; 152 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing 153 * lockTask task. */ 154 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4; 155 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE; 156 157 int mLockTaskUid = -1; // The uid of the application that called startLockTask(). 158 159 // This represents the last resolved activity values for this task 160 // NOTE: This value needs to be persisted with each task 161 TaskDescription lastTaskDescription = new TaskDescription(); 162 163 /** List of all activities in the task arranged in history order */ 164 final ArrayList<ActivityRecord> mActivities; 165 166 /** Current stack */ 167 ActivityStack stack; 168 169 /** Takes on same set of values as ActivityRecord.mActivityType */ 170 int taskType; 171 172 /** Takes on same value as first root activity */ 173 boolean isPersistable = false; 174 int maxRecents; 175 176 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for 177 * determining the order when restoring. Sign indicates whether last task movement was to front 178 * (positive) or back (negative). Absolute value indicates time. */ 179 long mLastTimeMoved = System.currentTimeMillis(); 180 181 /** Indication of what to run next when task exits. Use ActivityRecord types. 182 * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the 183 * task stack. */ 184 private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE; 185 186 /** If original intent did not allow relinquishing task identity, save that information */ 187 boolean mNeverRelinquishIdentity = true; 188 189 // Used in the unique case where we are clearing the task in order to reuse it. In that case we 190 // do not want to delete the stack when the task goes empty. 191 boolean mReuseTask = false; 192 193 private Bitmap mLastThumbnail; // Last thumbnail captured for this item. 194 private final File mLastThumbnailFile; // File containing last thumbnail. 195 private final String mFilename; 196 CharSequence lastDescription; // Last description captured for this item. 197 198 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent. 199 int mAffiliatedTaskColor; // color of the parent task affiliation. 200 TaskRecord mPrevAffiliate; // previous task in affiliated chain. 201 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence. 202 TaskRecord mNextAffiliate; // next task in affiliated chain. 203 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence. 204 205 // For relaunching the task from recents as though it was launched by the original launcher. 206 int mCallingUid; 207 String mCallingPackage; 208 209 final ActivityManagerService mService; 210 211 // Whether or not this task covers the entire screen; by default tasks are fullscreen. 212 boolean mFullscreen = true; 213 214 // Bounds of the Task. null for fullscreen tasks. 215 Rect mBounds = null; 216 // Last non-fullscreen bounds the task was launched in or resized to. 217 // The information is persisted and used to determine the appropriate stack to launch the 218 // task into on restore. 219 Rect mLastNonFullscreenBounds = null; 220 // Minimal size for width/height of this task when it's resizeable. -1 means it should use the 221 // default minimal size. 222 final int mMinimalSize; 223 224 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible) 225 // This number will be assigned when we evaluate OOM scores for all visible tasks. 226 int mLayerRank = -1; 227 228 Configuration mOverrideConfig = Configuration.EMPTY; 229 230 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent, 231 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) { 232 mService = service; 233 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + 234 TaskPersister.IMAGE_EXTENSION; 235 mLastThumbnailFile = new File(TaskPersister.sImagesDir, mFilename); 236 taskId = _taskId; 237 mAffiliatedTaskId = _taskId; 238 voiceSession = _voiceSession; 239 voiceInteractor = _voiceInteractor; 240 isAvailable = true; 241 mActivities = new ArrayList<>(); 242 mCallingUid = info.applicationInfo.uid; 243 mCallingPackage = info.packageName; 244 setIntent(_intent, info); 245 mMinimalSize = info != null && info.layout != null ? info.layout.minimalSize : -1; 246 } 247 248 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent, 249 TaskDescription _taskDescription) { 250 mService = service; 251 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + 252 TaskPersister.IMAGE_EXTENSION; 253 mLastThumbnailFile = new File(TaskPersister.sImagesDir, mFilename); 254 taskId = _taskId; 255 mAffiliatedTaskId = _taskId; 256 voiceSession = null; 257 voiceInteractor = null; 258 isAvailable = true; 259 mActivities = new ArrayList<>(); 260 mCallingUid = info.applicationInfo.uid; 261 mCallingPackage = info.packageName; 262 setIntent(_intent, info); 263 264 taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE; 265 isPersistable = true; 266 // Clamp to [1, max]. 267 maxRecents = Math.min(Math.max(info.maxRecents, 1), 268 ActivityManager.getMaxAppRecentsLimitStatic()); 269 270 taskType = APPLICATION_ACTIVITY_TYPE; 271 mTaskToReturnTo = HOME_ACTIVITY_TYPE; 272 userId = UserHandle.getUserId(info.applicationInfo.uid); 273 lastTaskDescription = _taskDescription; 274 mMinimalSize = info != null && info.layout != null ? info.layout.minimalSize : -1; 275 } 276 277 private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, 278 Intent _affinityIntent, String _affinity, String _rootAffinity, 279 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, 280 boolean _autoRemoveRecents, boolean _askedCompatMode, int _taskType, int _userId, 281 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities, 282 long _firstActiveTime, long _lastActiveTime, long lastTimeMoved, 283 boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription, 284 int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor, 285 int callingUid, String callingPackage, boolean resizeable, boolean privileged) { 286 mService = service; 287 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + 288 TaskPersister.IMAGE_EXTENSION; 289 mLastThumbnailFile = new File(TaskPersister.sImagesDir, mFilename); 290 taskId = _taskId; 291 intent = _intent; 292 affinityIntent = _affinityIntent; 293 affinity = _affinity; 294 rootAffinity = _rootAffinity; 295 voiceSession = null; 296 voiceInteractor = null; 297 realActivity = _realActivity; 298 origActivity = _origActivity; 299 rootWasReset = _rootWasReset; 300 isAvailable = true; 301 autoRemoveRecents = _autoRemoveRecents; 302 askedCompatMode = _askedCompatMode; 303 taskType = _taskType; 304 mTaskToReturnTo = HOME_ACTIVITY_TYPE; 305 userId = _userId; 306 effectiveUid = _effectiveUid; 307 firstActiveTime = _firstActiveTime; 308 lastActiveTime = _lastActiveTime; 309 lastDescription = _lastDescription; 310 mActivities = activities; 311 mLastTimeMoved = lastTimeMoved; 312 mNeverRelinquishIdentity = neverRelinquishIdentity; 313 lastTaskDescription = _lastTaskDescription; 314 mAffiliatedTaskId = taskAffiliation; 315 mAffiliatedTaskColor = taskAffiliationColor; 316 mPrevAffiliateTaskId = prevTaskId; 317 mNextAffiliateTaskId = nextTaskId; 318 mCallingUid = callingUid; 319 mCallingPackage = callingPackage; 320 mResizeable = resizeable; 321 mPrivileged = privileged; 322 ActivityInfo info = mActivities.get(0).info; 323 mMinimalSize = info != null && info.layout != null ? info.layout.minimalSize : -1; 324 } 325 326 void touchActiveTime() { 327 lastActiveTime = System.currentTimeMillis(); 328 if (firstActiveTime == 0) { 329 firstActiveTime = lastActiveTime; 330 } 331 } 332 333 long getInactiveDuration() { 334 return System.currentTimeMillis() - lastActiveTime; 335 } 336 337 /** Sets the original intent, and the calling uid and package. */ 338 void setIntent(ActivityRecord r) { 339 mCallingUid = r.launchedFromUid; 340 mCallingPackage = r.launchedFromPackage; 341 setIntent(r.intent, r.info); 342 } 343 344 /** Sets the original intent, _without_ updating the calling uid or package. */ 345 private void setIntent(Intent _intent, ActivityInfo info) { 346 if (intent == null) { 347 mNeverRelinquishIdentity = 348 (info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0; 349 } else if (mNeverRelinquishIdentity) { 350 return; 351 } 352 353 affinity = info.taskAffinity; 354 if (intent == null) { 355 // If this task already has an intent associated with it, don't set the root 356 // affinity -- we don't want it changing after initially set, but the initially 357 // set value may be null. 358 rootAffinity = affinity; 359 } 360 effectiveUid = info.applicationInfo.uid; 361 stringName = null; 362 363 if (info.targetActivity == null) { 364 if (_intent != null) { 365 // If this Intent has a selector, we want to clear it for the 366 // recent task since it is not relevant if the user later wants 367 // to re-launch the app. 368 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) { 369 _intent = new Intent(_intent); 370 _intent.setSelector(null); 371 _intent.setSourceBounds(null); 372 } 373 } 374 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent); 375 intent = _intent; 376 realActivity = _intent != null ? _intent.getComponent() : null; 377 origActivity = null; 378 } else { 379 ComponentName targetComponent = new ComponentName( 380 info.packageName, info.targetActivity); 381 if (_intent != null) { 382 Intent targetIntent = new Intent(_intent); 383 targetIntent.setComponent(targetComponent); 384 targetIntent.setSelector(null); 385 targetIntent.setSourceBounds(null); 386 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 387 "Setting Intent of " + this + " to target " + targetIntent); 388 intent = targetIntent; 389 realActivity = targetComponent; 390 origActivity = _intent.getComponent(); 391 } else { 392 intent = null; 393 realActivity = targetComponent; 394 origActivity = new ComponentName(info.packageName, info.name); 395 } 396 } 397 398 final int intentFlags = intent == null ? 0 : intent.getFlags(); 399 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 400 // Once we are set to an Intent with this flag, we count this 401 // task as having a true root activity. 402 rootWasReset = true; 403 } 404 405 userId = UserHandle.getUserId(info.applicationInfo.uid); 406 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) { 407 // If the activity itself has requested auto-remove, then just always do it. 408 autoRemoveRecents = true; 409 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS)) 410 == FLAG_ACTIVITY_NEW_DOCUMENT) { 411 // If the caller has not asked for the document to be retained, then we may 412 // want to turn on auto-remove, depending on whether the target has set its 413 // own document launch mode. 414 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) { 415 autoRemoveRecents = false; 416 } else { 417 autoRemoveRecents = true; 418 } 419 } else { 420 autoRemoveRecents = false; 421 } 422 mResizeable = info.resizeable; 423 mLockTaskMode = info.lockTaskLaunchMode; 424 mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0; 425 setLockTaskAuth(); 426 } 427 428 void setTaskToReturnTo(int taskToReturnTo) { 429 mTaskToReturnTo = (IGNORE_RETURN_TO_RECENTS && taskToReturnTo == RECENTS_ACTIVITY_TYPE) 430 ? HOME_ACTIVITY_TYPE : taskToReturnTo; 431 } 432 433 int getTaskToReturnTo() { 434 return mTaskToReturnTo; 435 } 436 437 void setPrevAffiliate(TaskRecord prevAffiliate) { 438 mPrevAffiliate = prevAffiliate; 439 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId; 440 } 441 442 void setNextAffiliate(TaskRecord nextAffiliate) { 443 mNextAffiliate = nextAffiliate; 444 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId; 445 } 446 447 // Close up recents linked list. 448 void closeRecentsChain() { 449 if (mPrevAffiliate != null) { 450 mPrevAffiliate.setNextAffiliate(mNextAffiliate); 451 } 452 if (mNextAffiliate != null) { 453 mNextAffiliate.setPrevAffiliate(mPrevAffiliate); 454 } 455 setPrevAffiliate(null); 456 setNextAffiliate(null); 457 } 458 459 void removedFromRecents() { 460 disposeThumbnail(); 461 closeRecentsChain(); 462 if (inRecents) { 463 inRecents = false; 464 mService.notifyTaskPersisterLocked(this, false); 465 } 466 } 467 468 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) { 469 closeRecentsChain(); 470 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId; 471 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor; 472 // Find the end 473 while (taskToAffiliateWith.mNextAffiliate != null) { 474 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate; 475 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) { 476 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId=" 477 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId); 478 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) { 479 nextRecents.setPrevAffiliate(null); 480 } 481 taskToAffiliateWith.setNextAffiliate(null); 482 break; 483 } 484 taskToAffiliateWith = nextRecents; 485 } 486 taskToAffiliateWith.setNextAffiliate(this); 487 setPrevAffiliate(taskToAffiliateWith); 488 setNextAffiliate(null); 489 } 490 491 /** 492 * Sets the last thumbnail. 493 * @return whether the thumbnail was set 494 */ 495 boolean setLastThumbnail(Bitmap thumbnail) { 496 if (mLastThumbnail != thumbnail) { 497 mLastThumbnail = thumbnail; 498 if (thumbnail == null) { 499 if (mLastThumbnailFile != null) { 500 mLastThumbnailFile.delete(); 501 } 502 } else { 503 mService.mTaskPersister.saveImage(thumbnail, mFilename); 504 } 505 return true; 506 } 507 return false; 508 } 509 510 void getLastThumbnail(TaskThumbnail thumbs) { 511 thumbs.mainThumbnail = mLastThumbnail; 512 thumbs.thumbnailFileDescriptor = null; 513 if (mLastThumbnail == null) { 514 thumbs.mainThumbnail = mService.mTaskPersister.getImageFromWriteQueue(mFilename); 515 } 516 // Only load the thumbnail file if we don't have a thumbnail 517 if (thumbs.mainThumbnail == null && mLastThumbnailFile.exists()) { 518 try { 519 thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile, 520 ParcelFileDescriptor.MODE_READ_ONLY); 521 } catch (IOException e) { 522 } 523 } 524 } 525 526 void freeLastThumbnail() { 527 mLastThumbnail = null; 528 } 529 530 void disposeThumbnail() { 531 mLastThumbnail = null; 532 lastDescription = null; 533 } 534 535 /** Returns the intent for the root activity for this task */ 536 Intent getBaseIntent() { 537 return intent != null ? intent : affinityIntent; 538 } 539 540 /** Returns the first non-finishing activity from the root. */ 541 ActivityRecord getRootActivity() { 542 for (int i = 0; i < mActivities.size(); i++) { 543 final ActivityRecord r = mActivities.get(i); 544 if (r.finishing) { 545 continue; 546 } 547 return r; 548 } 549 return null; 550 } 551 552 ActivityRecord getTopActivity() { 553 for (int i = mActivities.size() - 1; i >= 0; --i) { 554 final ActivityRecord r = mActivities.get(i); 555 if (r.finishing) { 556 continue; 557 } 558 return r; 559 } 560 return null; 561 } 562 563 ActivityRecord topRunningActivityLocked() { 564 if (stack != null) { 565 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) { 566 ActivityRecord r = mActivities.get(activityNdx); 567 if (!r.finishing && stack.okToShowLocked(r)) { 568 return r; 569 } 570 } 571 } 572 return null; 573 } 574 575 /** Call after activity movement or finish to make sure that frontOfTask is set correctly */ 576 final void setFrontOfTask() { 577 boolean foundFront = false; 578 final int numActivities = mActivities.size(); 579 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { 580 final ActivityRecord r = mActivities.get(activityNdx); 581 if (foundFront || r.finishing) { 582 r.frontOfTask = false; 583 } else { 584 r.frontOfTask = true; 585 // Set frontOfTask false for every following activity. 586 foundFront = true; 587 } 588 } 589 if (!foundFront && numActivities > 0) { 590 // All activities of this task are finishing. As we ought to have a frontOfTask 591 // activity, make the bottom activity front. 592 mActivities.get(0).frontOfTask = true; 593 } 594 } 595 596 /** 597 * Reorder the history stack so that the passed activity is brought to the front. 598 */ 599 final void moveActivityToFrontLocked(ActivityRecord newTop) { 600 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 601 "Removing and adding activity " + newTop 602 + " to stack at top callers=" + Debug.getCallers(4)); 603 604 mActivities.remove(newTop); 605 mActivities.add(newTop); 606 updateEffectiveIntent(); 607 608 setFrontOfTask(); 609 } 610 611 void addActivityAtBottom(ActivityRecord r) { 612 addActivityAtIndex(0, r); 613 } 614 615 void addActivityToTop(ActivityRecord r) { 616 addActivityAtIndex(mActivities.size(), r); 617 } 618 619 void addActivityAtIndex(int index, ActivityRecord r) { 620 // Remove r first, and if it wasn't already in the list and it's fullscreen, count it. 621 if (!mActivities.remove(r) && r.fullscreen) { 622 // Was not previously in list. 623 numFullscreen++; 624 } 625 // Only set this based on the first activity 626 if (mActivities.isEmpty()) { 627 taskType = r.mActivityType; 628 isPersistable = r.isPersistable(); 629 mCallingUid = r.launchedFromUid; 630 mCallingPackage = r.launchedFromPackage; 631 // Clamp to [1, max]. 632 maxRecents = Math.min(Math.max(r.info.maxRecents, 1), 633 ActivityManager.getMaxAppRecentsLimitStatic()); 634 } else { 635 // Otherwise make all added activities match this one. 636 r.mActivityType = taskType; 637 } 638 mActivities.add(index, r); 639 updateEffectiveIntent(); 640 if (r.isPersistable()) { 641 mService.notifyTaskPersisterLocked(this, false); 642 } 643 } 644 645 /** @return true if this was the last activity in the task */ 646 boolean removeActivity(ActivityRecord r) { 647 if (mActivities.remove(r) && r.fullscreen) { 648 // Was previously in list. 649 numFullscreen--; 650 } 651 if (r.isPersistable()) { 652 mService.notifyTaskPersisterLocked(this, false); 653 } 654 if (mActivities.isEmpty()) { 655 return !mReuseTask; 656 } 657 updateEffectiveIntent(); 658 return false; 659 } 660 661 boolean autoRemoveFromRecents() { 662 // We will automatically remove the task either if it has explicitly asked for 663 // this, or it is empty and has never contained an activity that got shown to 664 // the user. 665 return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible); 666 } 667 668 /** 669 * Completely remove all activities associated with an existing 670 * task starting at a specified index. 671 */ 672 final void performClearTaskAtIndexLocked(int activityNdx) { 673 int numActivities = mActivities.size(); 674 for ( ; activityNdx < numActivities; ++activityNdx) { 675 final ActivityRecord r = mActivities.get(activityNdx); 676 if (r.finishing) { 677 continue; 678 } 679 if (stack == null) { 680 // Task was restored from persistent storage. 681 r.takeFromHistory(); 682 mActivities.remove(activityNdx); 683 --activityNdx; 684 --numActivities; 685 } else if (stack.finishActivityLocked( 686 r, Activity.RESULT_CANCELED, null, "clear-task-index", false)) { 687 --activityNdx; 688 --numActivities; 689 } 690 } 691 } 692 693 /** 694 * Completely remove all activities associated with an existing task. 695 */ 696 final void performClearTaskLocked() { 697 mReuseTask = true; 698 performClearTaskAtIndexLocked(0); 699 mReuseTask = false; 700 } 701 702 /** 703 * Perform clear operation as requested by 704 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the 705 * stack to the given task, then look for 706 * an instance of that activity in the stack and, if found, finish all 707 * activities on top of it and return the instance. 708 * 709 * @param newR Description of the new activity being started. 710 * @return Returns the old activity that should be continued to be used, 711 * or null if none was found. 712 */ 713 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) { 714 int numActivities = mActivities.size(); 715 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) { 716 ActivityRecord r = mActivities.get(activityNdx); 717 if (r.finishing) { 718 continue; 719 } 720 if (r.realActivity.equals(newR.realActivity)) { 721 // Here it is! Now finish everything in front... 722 final ActivityRecord ret = r; 723 724 for (++activityNdx; activityNdx < numActivities; ++activityNdx) { 725 r = mActivities.get(activityNdx); 726 if (r.finishing) { 727 continue; 728 } 729 ActivityOptions opts = r.takeOptionsLocked(); 730 if (opts != null) { 731 ret.updateOptionsLocked(opts); 732 } 733 if (stack != null && stack.finishActivityLocked( 734 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) { 735 --activityNdx; 736 --numActivities; 737 } 738 } 739 740 // Finally, if this is a normal launch mode (that is, not 741 // expecting onNewIntent()), then we will finish the current 742 // instance of the activity so a new fresh one can be started. 743 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE 744 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) { 745 if (!ret.finishing) { 746 if (stack != null) { 747 stack.finishActivityLocked( 748 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false); 749 } 750 return null; 751 } 752 } 753 754 return ret; 755 } 756 } 757 758 return null; 759 } 760 761 public TaskThumbnail getTaskThumbnailLocked() { 762 if (stack != null) { 763 final ActivityRecord resumedActivity = stack.mResumedActivity; 764 if (resumedActivity != null && resumedActivity.task == this) { 765 final Bitmap thumbnail = stack.screenshotActivities(resumedActivity); 766 setLastThumbnail(thumbnail); 767 } 768 } 769 final TaskThumbnail taskThumbnail = new TaskThumbnail(); 770 getLastThumbnail(taskThumbnail); 771 return taskThumbnail; 772 } 773 774 public void removeTaskActivitiesLocked() { 775 // Just remove the entire task. 776 performClearTaskAtIndexLocked(0); 777 } 778 779 String lockTaskAuthToString() { 780 switch (mLockTaskAuth) { 781 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK"; 782 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE"; 783 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE"; 784 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED"; 785 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV"; 786 default: return "unknown=" + mLockTaskAuth; 787 } 788 } 789 790 void setLockTaskAuth() { 791 if (!mPrivileged && 792 (mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS || 793 mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) { 794 // Non-priv apps are not allowed to use always or never, fall back to default 795 mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT; 796 } 797 switch (mLockTaskMode) { 798 case LOCK_TASK_LAUNCH_MODE_DEFAULT: 799 mLockTaskAuth = isLockTaskWhitelistedLocked() ? 800 LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE; 801 break; 802 803 case LOCK_TASK_LAUNCH_MODE_NEVER: 804 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK; 805 break; 806 807 case LOCK_TASK_LAUNCH_MODE_ALWAYS: 808 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV; 809 break; 810 811 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED: 812 mLockTaskAuth = isLockTaskWhitelistedLocked() ? 813 LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE; 814 break; 815 } 816 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this + 817 " mLockTaskAuth=" + lockTaskAuthToString()); 818 } 819 820 boolean isLockTaskWhitelistedLocked() { 821 String pkg = (realActivity != null) ? realActivity.getPackageName() : null; 822 if (pkg == null) { 823 return false; 824 } 825 String[] packages = mService.mLockTaskPackages.get(userId); 826 if (packages == null) { 827 return false; 828 } 829 for (int i = packages.length - 1; i >= 0; --i) { 830 if (pkg.equals(packages[i])) { 831 return true; 832 } 833 } 834 return false; 835 } 836 boolean isHomeTask() { 837 return taskType == HOME_ACTIVITY_TYPE; 838 } 839 840 boolean isApplicationTask() { 841 return taskType == APPLICATION_ACTIVITY_TYPE; 842 } 843 844 boolean isOverHomeStack() { 845 return mTaskToReturnTo == HOME_ACTIVITY_TYPE || mTaskToReturnTo == RECENTS_ACTIVITY_TYPE; 846 } 847 848 /** 849 * Find the activity in the history stack within the given task. Returns 850 * the index within the history at which it's found, or < 0 if not found. 851 */ 852 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) { 853 final ComponentName realActivity = r.realActivity; 854 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) { 855 ActivityRecord candidate = mActivities.get(activityNdx); 856 if (candidate.finishing) { 857 continue; 858 } 859 if (candidate.realActivity.equals(realActivity)) { 860 return candidate; 861 } 862 } 863 return null; 864 } 865 866 /** Updates the last task description values. */ 867 void updateTaskDescription() { 868 // Traverse upwards looking for any break between main task activities and 869 // utility activities. 870 int activityNdx; 871 final int numActivities = mActivities.size(); 872 final boolean relinquish = numActivities == 0 ? false : 873 (mActivities.get(0).info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) != 0; 874 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities; 875 ++activityNdx) { 876 final ActivityRecord r = mActivities.get(activityNdx); 877 if (relinquish && (r.info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0) { 878 // This will be the top activity for determining taskDescription. Pre-inc to 879 // overcome initial decrement below. 880 ++activityNdx; 881 break; 882 } 883 if (r.intent != null && 884 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { 885 break; 886 } 887 } 888 if (activityNdx > 0) { 889 // Traverse downwards starting below break looking for set label, icon. 890 // Note that if there are activities in the task but none of them set the 891 // recent activity values, then we do not fall back to the last set 892 // values in the TaskRecord. 893 String label = null; 894 String iconFilename = null; 895 int colorPrimary = 0; 896 for (--activityNdx; activityNdx >= 0; --activityNdx) { 897 final ActivityRecord r = mActivities.get(activityNdx); 898 if (r.taskDescription != null) { 899 if (label == null) { 900 label = r.taskDescription.getLabel(); 901 } 902 if (iconFilename == null) { 903 iconFilename = r.taskDescription.getIconFilename(); 904 } 905 if (colorPrimary == 0) { 906 colorPrimary = r.taskDescription.getPrimaryColor(); 907 } 908 } 909 } 910 lastTaskDescription = new TaskDescription(label, colorPrimary, iconFilename); 911 // Update the task affiliation color if we are the parent of the group 912 if (taskId == mAffiliatedTaskId) { 913 mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor(); 914 } 915 } 916 } 917 918 int findEffectiveRootIndex() { 919 int effectiveNdx = 0; 920 final int topActivityNdx = mActivities.size() - 1; 921 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) { 922 final ActivityRecord r = mActivities.get(activityNdx); 923 if (r.finishing) { 924 continue; 925 } 926 effectiveNdx = activityNdx; 927 if ((r.info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0) { 928 break; 929 } 930 } 931 return effectiveNdx; 932 } 933 934 void updateEffectiveIntent() { 935 final int effectiveRootIndex = findEffectiveRootIndex(); 936 final ActivityRecord r = mActivities.get(effectiveRootIndex); 937 setIntent(r); 938 } 939 940 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException { 941 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this); 942 943 out.attribute(null, ATTR_TASKID, String.valueOf(taskId)); 944 if (realActivity != null) { 945 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString()); 946 } 947 if (origActivity != null) { 948 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString()); 949 } 950 // Write affinity, and root affinity if it is different from affinity. 951 // We use the special string "@" for a null root affinity, so we can identify 952 // later whether we were given a root affinity or should just make it the 953 // same as the affinity. 954 if (affinity != null) { 955 out.attribute(null, ATTR_AFFINITY, affinity); 956 if (!affinity.equals(rootAffinity)) { 957 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@"); 958 } 959 } else if (rootAffinity != null) { 960 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@"); 961 } 962 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset)); 963 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents)); 964 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode)); 965 out.attribute(null, ATTR_USERID, String.valueOf(userId)); 966 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid)); 967 out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType)); 968 out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime)); 969 out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime)); 970 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved)); 971 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity)); 972 if (lastDescription != null) { 973 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString()); 974 } 975 if (lastTaskDescription != null) { 976 lastTaskDescription.saveToXml(out); 977 } 978 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor)); 979 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId)); 980 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId)); 981 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId)); 982 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid)); 983 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage); 984 out.attribute(null, ATTR_RESIZEABLE, String.valueOf(mResizeable)); 985 out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged)); 986 if (mLastNonFullscreenBounds != null) { 987 out.attribute( 988 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString()); 989 } 990 991 if (affinityIntent != null) { 992 out.startTag(null, TAG_AFFINITYINTENT); 993 affinityIntent.saveToXml(out); 994 out.endTag(null, TAG_AFFINITYINTENT); 995 } 996 997 out.startTag(null, TAG_INTENT); 998 intent.saveToXml(out); 999 out.endTag(null, TAG_INTENT); 1000 1001 final ArrayList<ActivityRecord> activities = mActivities; 1002 final int numActivities = activities.size(); 1003 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { 1004 final ActivityRecord r = activities.get(activityNdx); 1005 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() || 1006 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT 1007 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) && 1008 activityNdx > 0) { 1009 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET). 1010 break; 1011 } 1012 out.startTag(null, TAG_ACTIVITY); 1013 r.saveToXml(out); 1014 out.endTag(null, TAG_ACTIVITY); 1015 } 1016 } 1017 1018 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor) 1019 throws IOException, XmlPullParserException { 1020 Intent intent = null; 1021 Intent affinityIntent = null; 1022 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(); 1023 ComponentName realActivity = null; 1024 ComponentName origActivity = null; 1025 String affinity = null; 1026 String rootAffinity = null; 1027 boolean hasRootAffinity = false; 1028 boolean rootHasReset = false; 1029 boolean autoRemoveRecents = false; 1030 boolean askedCompatMode = false; 1031 int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE; 1032 int userId = 0; 1033 int effectiveUid = -1; 1034 String lastDescription = null; 1035 long firstActiveTime = -1; 1036 long lastActiveTime = -1; 1037 long lastTimeOnTop = 0; 1038 boolean neverRelinquishIdentity = true; 1039 int taskId = INVALID_TASK_ID; 1040 final int outerDepth = in.getDepth(); 1041 TaskDescription taskDescription = new TaskDescription(); 1042 int taskAffiliation = INVALID_TASK_ID; 1043 int taskAffiliationColor = 0; 1044 int prevTaskId = INVALID_TASK_ID; 1045 int nextTaskId = INVALID_TASK_ID; 1046 int callingUid = -1; 1047 String callingPackage = ""; 1048 boolean resizeable = false; 1049 boolean privileged = false; 1050 Rect bounds = null; 1051 1052 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) { 1053 final String attrName = in.getAttributeName(attrNdx); 1054 final String attrValue = in.getAttributeValue(attrNdx); 1055 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" + 1056 attrName + " value=" + attrValue); 1057 if (ATTR_TASKID.equals(attrName)) { 1058 if (taskId == INVALID_TASK_ID) taskId = Integer.valueOf(attrValue); 1059 } else if (ATTR_REALACTIVITY.equals(attrName)) { 1060 realActivity = ComponentName.unflattenFromString(attrValue); 1061 } else if (ATTR_ORIGACTIVITY.equals(attrName)) { 1062 origActivity = ComponentName.unflattenFromString(attrValue); 1063 } else if (ATTR_AFFINITY.equals(attrName)) { 1064 affinity = attrValue; 1065 } else if (ATTR_ROOT_AFFINITY.equals(attrName)) { 1066 rootAffinity = attrValue; 1067 hasRootAffinity = true; 1068 } else if (ATTR_ROOTHASRESET.equals(attrName)) { 1069 rootHasReset = Boolean.valueOf(attrValue); 1070 } else if (ATTR_AUTOREMOVERECENTS.equals(attrName)) { 1071 autoRemoveRecents = Boolean.valueOf(attrValue); 1072 } else if (ATTR_ASKEDCOMPATMODE.equals(attrName)) { 1073 askedCompatMode = Boolean.valueOf(attrValue); 1074 } else if (ATTR_USERID.equals(attrName)) { 1075 userId = Integer.valueOf(attrValue); 1076 } else if (ATTR_EFFECTIVE_UID.equals(attrName)) { 1077 effectiveUid = Integer.valueOf(attrValue); 1078 } else if (ATTR_TASKTYPE.equals(attrName)) { 1079 taskType = Integer.valueOf(attrValue); 1080 } else if (ATTR_FIRSTACTIVETIME.equals(attrName)) { 1081 firstActiveTime = Long.valueOf(attrValue); 1082 } else if (ATTR_LASTACTIVETIME.equals(attrName)) { 1083 lastActiveTime = Long.valueOf(attrValue); 1084 } else if (ATTR_LASTDESCRIPTION.equals(attrName)) { 1085 lastDescription = attrValue; 1086 } else if (ATTR_LASTTIMEMOVED.equals(attrName)) { 1087 lastTimeOnTop = Long.valueOf(attrValue); 1088 } else if (ATTR_NEVERRELINQUISH.equals(attrName)) { 1089 neverRelinquishIdentity = Boolean.valueOf(attrValue); 1090 } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) { 1091 taskDescription.restoreFromXml(attrName, attrValue); 1092 } else if (ATTR_TASK_AFFILIATION.equals(attrName)) { 1093 taskAffiliation = Integer.valueOf(attrValue); 1094 } else if (ATTR_PREV_AFFILIATION.equals(attrName)) { 1095 prevTaskId = Integer.valueOf(attrValue); 1096 } else if (ATTR_NEXT_AFFILIATION.equals(attrName)) { 1097 nextTaskId = Integer.valueOf(attrValue); 1098 } else if (ATTR_TASK_AFFILIATION_COLOR.equals(attrName)) { 1099 taskAffiliationColor = Integer.valueOf(attrValue); 1100 } else if (ATTR_CALLING_UID.equals(attrName)) { 1101 callingUid = Integer.valueOf(attrValue); 1102 } else if (ATTR_CALLING_PACKAGE.equals(attrName)) { 1103 callingPackage = attrValue; 1104 } else if (ATTR_RESIZEABLE.equals(attrName)) { 1105 resizeable = Boolean.valueOf(attrValue); 1106 } else if (ATTR_PRIVILEGED.equals(attrName)) { 1107 privileged = Boolean.valueOf(attrValue); 1108 } else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) { 1109 bounds = Rect.unflattenFromString(attrValue); 1110 } else { 1111 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName); 1112 } 1113 } 1114 1115 int event; 1116 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) && 1117 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) { 1118 if (event == XmlPullParser.START_TAG) { 1119 final String name = in.getName(); 1120 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" + 1121 name); 1122 if (TAG_AFFINITYINTENT.equals(name)) { 1123 affinityIntent = Intent.restoreFromXml(in); 1124 } else if (TAG_INTENT.equals(name)) { 1125 intent = Intent.restoreFromXml(in); 1126 } else if (TAG_ACTIVITY.equals(name)) { 1127 ActivityRecord activity = ActivityRecord.restoreFromXml(in, stackSupervisor); 1128 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" + 1129 activity); 1130 if (activity != null) { 1131 activities.add(activity); 1132 } 1133 } else { 1134 Slog.e(TAG, "restoreTask: Unexpected name=" + name); 1135 XmlUtils.skipCurrentTag(in); 1136 } 1137 } 1138 } 1139 if (!hasRootAffinity) { 1140 rootAffinity = affinity; 1141 } else if ("@".equals(rootAffinity)) { 1142 rootAffinity = null; 1143 } 1144 if (effectiveUid <= 0) { 1145 Intent checkIntent = intent != null ? intent : affinityIntent; 1146 effectiveUid = 0; 1147 if (checkIntent != null) { 1148 IPackageManager pm = AppGlobals.getPackageManager(); 1149 try { 1150 ApplicationInfo ai = pm.getApplicationInfo( 1151 checkIntent.getComponent().getPackageName(), 1152 PackageManager.GET_UNINSTALLED_PACKAGES 1153 | PackageManager.GET_DISABLED_COMPONENTS, userId); 1154 if (ai != null) { 1155 effectiveUid = ai.uid; 1156 } 1157 } catch (RemoteException e) { 1158 } 1159 } 1160 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent 1161 + ": effectiveUid=" + effectiveUid); 1162 } 1163 1164 final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent, 1165 affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset, 1166 autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription, 1167 activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity, 1168 taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, 1169 callingUid, callingPackage, resizeable, privileged); 1170 task.updateOverrideConfiguration(bounds); 1171 1172 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) { 1173 activities.get(activityNdx).task = task; 1174 } 1175 1176 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task); 1177 return task; 1178 } 1179 1180 /** 1181 * Update task's override configuration based on the bounds. 1182 * @return Update configuration or null if there is no change. 1183 */ 1184 Configuration updateOverrideConfiguration(Rect bounds) { 1185 if (Objects.equals(mBounds, bounds)) { 1186 return null; 1187 } 1188 Configuration oldConfig = mOverrideConfig; 1189 1190 mFullscreen = bounds == null; 1191 if (mFullscreen) { 1192 if (mBounds != null && stack.mStackId != DOCKED_STACK_ID) { 1193 mLastNonFullscreenBounds = mBounds; 1194 } 1195 mBounds = null; 1196 mOverrideConfig = Configuration.EMPTY; 1197 } else { 1198 mBounds = new Rect(bounds); 1199 if (stack == null || stack.mStackId != DOCKED_STACK_ID) { 1200 mLastNonFullscreenBounds = mBounds; 1201 } 1202 1203 final Configuration serviceConfig = mService.mConfiguration; 1204 mOverrideConfig = new Configuration(serviceConfig); 1205 // TODO(multidisplay): Update Dp to that of display stack is on. 1206 final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; 1207 mOverrideConfig.screenWidthDp = 1208 Math.min((int)(mBounds.width() / density), serviceConfig.screenWidthDp); 1209 mOverrideConfig.screenHeightDp = 1210 Math.min((int)(mBounds.height() / density), serviceConfig.screenHeightDp); 1211 mOverrideConfig.smallestScreenWidthDp = 1212 Math.min(mOverrideConfig.screenWidthDp, mOverrideConfig.screenHeightDp); 1213 mOverrideConfig.orientation = 1214 (mOverrideConfig.screenWidthDp <= mOverrideConfig.screenHeightDp) 1215 ? Configuration.ORIENTATION_PORTRAIT 1216 : Configuration.ORIENTATION_LANDSCAPE; 1217 } 1218 return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null; 1219 } 1220 1221 /** 1222 * Returns the correct stack to use based on task type and currently set bounds, 1223 * regardless of the focused stack and current stack association of the task. 1224 * The task will be moved (and stack focus changed) later if necessary. 1225 */ 1226 int getLaunchStackId() { 1227 if (!isApplicationTask()) { 1228 return HOME_STACK_ID; 1229 } 1230 if (mBounds != null) { 1231 return FREEFORM_WORKSPACE_STACK_ID; 1232 } 1233 return FULLSCREEN_WORKSPACE_STACK_ID; 1234 } 1235 1236 /** Returns the bounds that should be used to launch this task. */ 1237 Rect getLaunchBounds() { 1238 if (stack == null 1239 || stack.mStackId == HOME_STACK_ID 1240 || stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) { 1241 return (mResizeable && stack != null) ? stack.mBounds : null; 1242 } else if (stack.mStackId == DOCKED_STACK_ID) { 1243 return stack.mBounds; 1244 } 1245 return mLastNonFullscreenBounds; 1246 } 1247 1248 void dump(PrintWriter pw, String prefix) { 1249 pw.print(prefix); pw.print("userId="); pw.print(userId); 1250 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid); 1251 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid); 1252 pw.print(" mCallingPackage="); pw.println(mCallingPackage); 1253 if (affinity != null || rootAffinity != null) { 1254 pw.print(prefix); pw.print("affinity="); pw.print(affinity); 1255 if (affinity == null || !affinity.equals(rootAffinity)) { 1256 pw.print(" root="); pw.println(rootAffinity); 1257 } else { 1258 pw.println(); 1259 } 1260 } 1261 if (voiceSession != null || voiceInteractor != null) { 1262 pw.print(prefix); pw.print("VOICE: session=0x"); 1263 pw.print(Integer.toHexString(System.identityHashCode(voiceSession))); 1264 pw.print(" interactor=0x"); 1265 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor))); 1266 } 1267 if (intent != null) { 1268 StringBuilder sb = new StringBuilder(128); 1269 sb.append(prefix); sb.append("intent={"); 1270 intent.toShortString(sb, false, true, false, true); 1271 sb.append('}'); 1272 pw.println(sb.toString()); 1273 } 1274 if (affinityIntent != null) { 1275 StringBuilder sb = new StringBuilder(128); 1276 sb.append(prefix); sb.append("affinityIntent={"); 1277 affinityIntent.toShortString(sb, false, true, false, true); 1278 sb.append('}'); 1279 pw.println(sb.toString()); 1280 } 1281 if (origActivity != null) { 1282 pw.print(prefix); pw.print("origActivity="); 1283 pw.println(origActivity.flattenToShortString()); 1284 } 1285 if (realActivity != null) { 1286 pw.print(prefix); pw.print("realActivity="); 1287 pw.println(realActivity.flattenToShortString()); 1288 } 1289 if (autoRemoveRecents || isPersistable || taskType != 0 || mTaskToReturnTo != 0 1290 || numFullscreen != 0) { 1291 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents); 1292 pw.print(" isPersistable="); pw.print(isPersistable); 1293 pw.print(" numFullscreen="); pw.print(numFullscreen); 1294 pw.print(" taskType="); pw.print(taskType); 1295 pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo); 1296 } 1297 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask 1298 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) { 1299 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset); 1300 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity); 1301 pw.print(" mReuseTask="); pw.print(mReuseTask); 1302 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString()); 1303 } 1304 if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID 1305 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID 1306 || mNextAffiliate != null) { 1307 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId); 1308 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId); 1309 pw.print(" ("); 1310 if (mPrevAffiliate == null) { 1311 pw.print("null"); 1312 } else { 1313 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate))); 1314 } 1315 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId); 1316 pw.print(" ("); 1317 if (mNextAffiliate == null) { 1318 pw.print("null"); 1319 } else { 1320 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate))); 1321 } 1322 pw.println(")"); 1323 } 1324 pw.print(prefix); pw.print("Activities="); pw.println(mActivities); 1325 if (!askedCompatMode || !inRecents || !isAvailable) { 1326 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode); 1327 pw.print(" inRecents="); pw.print(inRecents); 1328 pw.print(" isAvailable="); pw.println(isAvailable); 1329 } 1330 pw.print(prefix); pw.print("lastThumbnail="); pw.print(mLastThumbnail); 1331 pw.print(" lastThumbnailFile="); pw.println(mLastThumbnailFile); 1332 if (lastDescription != null) { 1333 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription); 1334 } 1335 if (stack != null) { 1336 pw.print(prefix); pw.print("stackId="); pw.println(stack.mStackId); 1337 } 1338 pw.print(prefix); pw.print("hasBeenVisible="); pw.print(hasBeenVisible); 1339 pw.print(" mResizeable="); pw.print(mResizeable); 1340 pw.print(" firstActiveTime="); pw.print(lastActiveTime); 1341 pw.print(" lastActiveTime="); pw.print(lastActiveTime); 1342 pw.print(" (inactive for "); 1343 pw.print((getInactiveDuration()/1000)); pw.println("s)"); 1344 } 1345 1346 @Override 1347 public String toString() { 1348 StringBuilder sb = new StringBuilder(128); 1349 if (stringName != null) { 1350 sb.append(stringName); 1351 sb.append(" U="); 1352 sb.append(userId); 1353 sb.append(" sz="); 1354 sb.append(mActivities.size()); 1355 sb.append('}'); 1356 return sb.toString(); 1357 } 1358 sb.append("TaskRecord{"); 1359 sb.append(Integer.toHexString(System.identityHashCode(this))); 1360 sb.append(" #"); 1361 sb.append(taskId); 1362 if (affinity != null) { 1363 sb.append(" A="); 1364 sb.append(affinity); 1365 } else if (intent != null) { 1366 sb.append(" I="); 1367 sb.append(intent.getComponent().flattenToShortString()); 1368 } else if (affinityIntent != null) { 1369 sb.append(" aI="); 1370 sb.append(affinityIntent.getComponent().flattenToShortString()); 1371 } else { 1372 sb.append(" ??"); 1373 } 1374 stringName = sb.toString(); 1375 return toString(); 1376 } 1377} 1378