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 17 package com.android.server.am; 18 19 import com.android.server.AttributeCache; 20 import com.android.server.am.ActivityStack.ActivityState; 21 22 import android.app.Activity; 23 import android.content.ComponentName; 24 import android.content.Intent; 25 import android.content.pm.ActivityInfo; 26 import android.content.pm.ApplicationInfo; 27 import android.content.res.Configuration; 28 import android.graphics.Bitmap; 29 import android.os.Bundle; 30 import android.os.Message; 31 import android.os.Process; 32 import android.os.RemoteException; 33 import android.os.SystemClock; 34 import android.util.EventLog; 35 import android.util.Log; 36 import android.util.Slog; 37 import android.util.TimeUtils; 38 import android.view.IApplicationToken; 39 40 import java.io.PrintWriter; 41 import java.lang.ref.WeakReference; 42 import java.util.ArrayList; 43 import java.util.HashSet; 44 45 /** 46 * An entry in the history stack, representing an activity. 47 */ 48 class ActivityRecord extends IApplicationToken.Stub { 49 final ActivityManagerService service; // owner 50 final ActivityStack stack; // owner 51 final ActivityInfo info; // all about me 52 final int launchedFromUid; // always the uid who started the activity. 53 final Intent intent; // the original intent that generated us 54 final ComponentName realActivity; // the intent component, or target of an alias. 55 final String shortComponentName; // the short component name of the intent 56 final String resolvedType; // as per original caller; 57 final String packageName; // the package implementing intent's component 58 final String processName; // process where this component wants to run 59 final String taskAffinity; // as per ActivityInfo.taskAffinity 60 final boolean stateNotNeeded; // As per ActivityInfo.flags 61 final boolean fullscreen; // covers the full screen? 62 final boolean componentSpecified; // did caller specifiy an explicit component? 63 final boolean isHomeActivity; // do we consider this to be a home activity? 64 final String baseDir; // where activity source (resources etc) located 65 final String resDir; // where public activity source (public resources etc) located 66 final String dataDir; // where activity data should go 67 CharSequence nonLocalizedLabel; // the label information from the package mgr. 68 int labelRes; // the label information from the package mgr. 69 int icon; // resource identifier of activity's icon. 70 int theme; // resource identifier of activity's theme. 71 TaskRecord task; // the task this is in. 72 long launchTime; // when we starting launching this activity 73 long startTime; // last time this activity was started 74 long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity 75 Configuration configuration; // configuration activity was last running in 76 ActivityRecord resultTo; // who started this entry, so will get our reply 77 final String resultWho; // additional identifier for use by resultTo. 78 final int requestCode; // code given by requester (resultTo) 79 ArrayList results; // pending ActivityResult objs we have received 80 HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act 81 ArrayList newIntents; // any pending new intents for single-top mode 82 HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold 83 UriPermissionOwner uriPermissions; // current special URI access perms. 84 ProcessRecord app; // if non-null, hosting application 85 Bitmap thumbnail; // icon representation of paused screen 86 CharSequence description; // textual description of paused screen 87 ActivityState state; // current state we are in 88 Bundle icicle; // last saved activity state 89 boolean frontOfTask; // is this the root activity of its task? 90 boolean launchFailed; // set if a launched failed, to abort on 2nd try 91 boolean haveState; // have we gotten the last activity state? 92 boolean stopped; // is activity pause finished? 93 boolean delayedResume; // not yet resumed because of stopped app switches? 94 boolean finishing; // activity in pending finish list? 95 boolean configDestroy; // need to destroy due to config change? 96 int configChangeFlags; // which config values have changed 97 boolean keysPaused; // has key dispatching been paused for it? 98 boolean inHistory; // are we in the history stack? 99 int launchMode; // the launch mode activity attribute. 100 boolean visible; // does this activity's window need to be shown? 101 boolean waitingVisible; // true if waiting for a new act to become vis 102 boolean nowVisible; // is this activity's window visible? 103 boolean thumbnailNeeded;// has someone requested a thumbnail? 104 boolean idle; // has the activity gone idle? 105 boolean hasBeenLaunched;// has this activity ever been launched? 106 boolean frozenBeforeDestroy;// has been frozen but not yet destroyed. 107 108 String stringName; // for caching of toString(). 109 110 void dump(PrintWriter pw, String prefix) { 111 pw.print(prefix); pw.print("packageName="); pw.print(packageName); 112 pw.print(" processName="); pw.println(processName); 113 pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid); 114 pw.print(" app="); pw.println(app); 115 pw.print(prefix); pw.println(intent); 116 pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask); 117 pw.print(" task="); pw.println(task); 118 pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity); 119 pw.print(prefix); pw.print("realActivity="); 120 pw.println(realActivity.flattenToShortString()); 121 pw.print(prefix); pw.print("base="); pw.print(baseDir); 122 if (!resDir.equals(baseDir)) pw.print(" res="); pw.print(resDir); 123 pw.print(" data="); pw.println(dataDir); 124 pw.print(prefix); pw.print("labelRes=0x"); 125 pw.print(Integer.toHexString(labelRes)); 126 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon)); 127 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme)); 128 pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded); 129 pw.print(" componentSpecified="); pw.print(componentSpecified); 130 pw.print(" isHomeActivity="); pw.println(isHomeActivity); 131 pw.print(prefix); pw.print("configuration="); pw.println(configuration); 132 if (resultTo != null || resultWho != null) { 133 pw.print(prefix); pw.print("resultTo="); pw.print(resultTo); 134 pw.print(" resultWho="); pw.print(resultWho); 135 pw.print(" resultCode="); pw.println(requestCode); 136 } 137 if (results != null) { 138 pw.print(prefix); pw.print("results="); pw.println(results); 139 } 140 if (pendingResults != null) { 141 pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults); 142 } 143 if (uriPermissions != null) { 144 if (uriPermissions.readUriPermissions != null) { 145 pw.print(prefix); pw.print("readUriPermissions="); 146 pw.println(uriPermissions.readUriPermissions); 147 } 148 if (uriPermissions.writeUriPermissions != null) { 149 pw.print(prefix); pw.print("writeUriPermissions="); 150 pw.println(uriPermissions.writeUriPermissions); 151 } 152 } 153 pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed); 154 pw.print(" haveState="); pw.print(haveState); 155 pw.print(" icicle="); pw.println(icicle); 156 pw.print(prefix); pw.print("state="); pw.print(state); 157 pw.print(" stopped="); pw.print(stopped); 158 pw.print(" delayedResume="); pw.print(delayedResume); 159 pw.print(" finishing="); pw.println(finishing); 160 pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused); 161 pw.print(" inHistory="); pw.print(inHistory); 162 pw.print(" launchMode="); pw.println(launchMode); 163 pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen); 164 pw.print(" visible="); pw.print(visible); 165 pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy); 166 pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded); 167 pw.print(" idle="); pw.println(idle); 168 if (launchTime != 0 || startTime != 0) { 169 pw.print(prefix); pw.print("launchTime="); 170 TimeUtils.formatDuration(launchTime, pw); pw.print(" startTime="); 171 TimeUtils.formatDuration(startTime, pw); pw.println(""); 172 } 173 if (waitingVisible || nowVisible) { 174 pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible); 175 pw.print(" nowVisible="); pw.println(nowVisible); 176 } 177 if (configDestroy || configChangeFlags != 0) { 178 pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy); 179 pw.print(" configChangeFlags="); 180 pw.println(Integer.toHexString(configChangeFlags)); 181 } 182 if (connections != null) { 183 pw.print(prefix); pw.print("connections="); pw.println(connections); 184 } 185 } 186 187 ActivityRecord(ActivityManagerService _service, ActivityStack _stack, ProcessRecord _caller, 188 int _launchedFromUid, Intent _intent, String _resolvedType, 189 ActivityInfo aInfo, Configuration _configuration, 190 ActivityRecord _resultTo, String _resultWho, int _reqCode, 191 boolean _componentSpecified) { 192 service = _service; 193 stack = _stack; 194 info = aInfo; 195 launchedFromUid = _launchedFromUid; 196 intent = _intent; 197 shortComponentName = _intent.getComponent().flattenToShortString(); 198 resolvedType = _resolvedType; 199 componentSpecified = _componentSpecified; 200 configuration = _configuration; 201 resultTo = _resultTo; 202 resultWho = _resultWho; 203 requestCode = _reqCode; 204 state = ActivityState.INITIALIZING; 205 frontOfTask = false; 206 launchFailed = false; 207 haveState = false; 208 stopped = false; 209 delayedResume = false; 210 finishing = false; 211 configDestroy = false; 212 keysPaused = false; 213 inHistory = false; 214 visible = true; 215 waitingVisible = false; 216 nowVisible = false; 217 thumbnailNeeded = false; 218 idle = false; 219 hasBeenLaunched = false; 220 221 if (aInfo != null) { 222 if (aInfo.targetActivity == null 223 || aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE 224 || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) { 225 realActivity = _intent.getComponent(); 226 } else { 227 realActivity = new ComponentName(aInfo.packageName, 228 aInfo.targetActivity); 229 } 230 taskAffinity = aInfo.taskAffinity; 231 stateNotNeeded = (aInfo.flags& 232 ActivityInfo.FLAG_STATE_NOT_NEEDED) != 0; 233 baseDir = aInfo.applicationInfo.sourceDir; 234 resDir = aInfo.applicationInfo.publicSourceDir; 235 dataDir = aInfo.applicationInfo.dataDir; 236 nonLocalizedLabel = aInfo.nonLocalizedLabel; 237 labelRes = aInfo.labelRes; 238 if (nonLocalizedLabel == null && labelRes == 0) { 239 ApplicationInfo app = aInfo.applicationInfo; 240 nonLocalizedLabel = app.nonLocalizedLabel; 241 labelRes = app.labelRes; 242 } 243 icon = aInfo.getIconResource(); 244 theme = aInfo.getThemeResource(); 245 if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0 246 && _caller != null 247 && (aInfo.applicationInfo.uid == Process.SYSTEM_UID 248 || aInfo.applicationInfo.uid == _caller.info.uid)) { 249 processName = _caller.processName; 250 } else { 251 processName = aInfo.processName; 252 } 253 254 if (intent != null && (aInfo.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) != 0) { 255 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 256 } 257 258 packageName = aInfo.applicationInfo.packageName; 259 launchMode = aInfo.launchMode; 260 261 AttributeCache.Entry ent = AttributeCache.instance().get(packageName, 262 theme != 0 ? theme : android.R.style.Theme, 263 com.android.internal.R.styleable.Window); 264 fullscreen = ent != null && !ent.array.getBoolean( 265 com.android.internal.R.styleable.Window_windowIsFloating, false) 266 && !ent.array.getBoolean( 267 com.android.internal.R.styleable.Window_windowIsTranslucent, false); 268 269 if (!_componentSpecified || _launchedFromUid == Process.myUid() 270 || _launchedFromUid == 0) { 271 // If we know the system has determined the component, then 272 // we can consider this to be a home activity... 273 if (Intent.ACTION_MAIN.equals(_intent.getAction()) && 274 _intent.hasCategory(Intent.CATEGORY_HOME) && 275 _intent.getCategories().size() == 1 && 276 _intent.getData() == null && 277 _intent.getType() == null && 278 (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && 279 !"android".equals(realActivity.getClassName())) { 280 // This sure looks like a home activity! 281 // Note the last check is so we don't count the resolver 282 // activity as being home... really, we don't care about 283 // doing anything special with something that comes from 284 // the core framework package. 285 isHomeActivity = true; 286 } else { 287 isHomeActivity = false; 288 } 289 } else { 290 isHomeActivity = false; 291 } 292 } else { 293 realActivity = null; 294 taskAffinity = null; 295 stateNotNeeded = false; 296 baseDir = null; 297 resDir = null; 298 dataDir = null; 299 processName = null; 300 packageName = null; 301 fullscreen = true; 302 isHomeActivity = false; 303 } 304 } 305 306 UriPermissionOwner getUriPermissionsLocked() { 307 if (uriPermissions == null) { 308 uriPermissions = new UriPermissionOwner(service, this); 309 } 310 return uriPermissions; 311 } 312 313 void addResultLocked(ActivityRecord from, String resultWho, 314 int requestCode, int resultCode, 315 Intent resultData) { 316 ActivityResult r = new ActivityResult(from, resultWho, 317 requestCode, resultCode, resultData); 318 if (results == null) { 319 results = new ArrayList(); 320 } 321 results.add(r); 322 } 323 324 void removeResultsLocked(ActivityRecord from, String resultWho, 325 int requestCode) { 326 if (results != null) { 327 for (int i=results.size()-1; i>=0; i--) { 328 ActivityResult r = (ActivityResult)results.get(i); 329 if (r.mFrom != from) continue; 330 if (r.mResultWho == null) { 331 if (resultWho != null) continue; 332 } else { 333 if (!r.mResultWho.equals(resultWho)) continue; 334 } 335 if (r.mRequestCode != requestCode) continue; 336 337 results.remove(i); 338 } 339 } 340 } 341 342 void addNewIntentLocked(Intent intent) { 343 if (newIntents == null) { 344 newIntents = new ArrayList(); 345 } 346 newIntents.add(intent); 347 } 348 349 /** 350 * Deliver a new Intent to an existing activity, so that its onNewIntent() 351 * method will be called at the proper time. 352 */ 353 final void deliverNewIntentLocked(int callingUid, Intent intent) { 354 boolean sent = false; 355 if (state == ActivityState.RESUMED 356 && app != null && app.thread != null) { 357 try { 358 ArrayList<Intent> ar = new ArrayList<Intent>(); 359 intent = new Intent(intent); 360 ar.add(intent); 361 service.grantUriPermissionFromIntentLocked(callingUid, packageName, 362 intent, getUriPermissionsLocked()); 363 app.thread.scheduleNewIntent(ar, this); 364 sent = true; 365 } catch (RemoteException e) { 366 Slog.w(ActivityManagerService.TAG, 367 "Exception thrown sending new intent to " + this, e); 368 } catch (NullPointerException e) { 369 Slog.w(ActivityManagerService.TAG, 370 "Exception thrown sending new intent to " + this, e); 371 } 372 } 373 if (!sent) { 374 addNewIntentLocked(new Intent(intent)); 375 } 376 } 377 378 void removeUriPermissionsLocked() { 379 if (uriPermissions != null) { 380 uriPermissions.removeUriPermissionsLocked(); 381 uriPermissions = null; 382 } 383 } 384 385 void pauseKeyDispatchingLocked() { 386 if (!keysPaused) { 387 keysPaused = true; 388 service.mWindowManager.pauseKeyDispatching(this); 389 } 390 } 391 392 void resumeKeyDispatchingLocked() { 393 if (keysPaused) { 394 keysPaused = false; 395 service.mWindowManager.resumeKeyDispatching(this); 396 } 397 } 398 399 // IApplicationToken 400 401 public boolean mayFreezeScreenLocked(ProcessRecord app) { 402 // Only freeze the screen if this activity is currently attached to 403 // an application, and that application is not blocked or unresponding. 404 // In any other case, we can't count on getting the screen unfrozen, 405 // so it is best to leave as-is. 406 return app == null || (!app.crashing && !app.notResponding); 407 } 408 409 public void startFreezingScreenLocked(ProcessRecord app, int configChanges) { 410 if (mayFreezeScreenLocked(app)) { 411 service.mWindowManager.startAppFreezingScreen(this, configChanges); 412 } 413 } 414 415 public void stopFreezingScreenLocked(boolean force) { 416 if (force || frozenBeforeDestroy) { 417 frozenBeforeDestroy = false; 418 service.mWindowManager.stopAppFreezingScreen(this, force); 419 } 420 } 421 422 public void windowsVisible() { 423 synchronized(service) { 424 if (launchTime != 0) { 425 final long curTime = SystemClock.uptimeMillis(); 426 final long thisTime = curTime - launchTime; 427 final long totalTime = stack.mInitialStartTime != 0 428 ? (curTime - stack.mInitialStartTime) : thisTime; 429 if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) { 430 EventLog.writeEvent(EventLogTags.ACTIVITY_LAUNCH_TIME, 431 System.identityHashCode(this), shortComponentName, 432 thisTime, totalTime); 433 StringBuilder sb = service.mStringBuilder; 434 sb.setLength(0); 435 sb.append("Displayed "); 436 sb.append(shortComponentName); 437 sb.append(": "); 438 TimeUtils.formatDuration(thisTime, sb); 439 if (thisTime != totalTime) { 440 sb.append(" (total "); 441 TimeUtils.formatDuration(totalTime, sb); 442 sb.append(")"); 443 } 444 Log.i(ActivityManagerService.TAG, sb.toString()); 445 } 446 stack.reportActivityLaunchedLocked(false, this, thisTime, totalTime); 447 if (totalTime > 0) { 448 service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime); 449 } 450 launchTime = 0; 451 stack.mInitialStartTime = 0; 452 } 453 startTime = 0; 454 stack.reportActivityVisibleLocked(this); 455 if (ActivityManagerService.DEBUG_SWITCH) Log.v( 456 ActivityManagerService.TAG, "windowsVisible(): " + this); 457 if (!nowVisible) { 458 nowVisible = true; 459 if (!idle) { 460 // Instead of doing the full stop routine here, let's just 461 // hide any activities we now can, and let them stop when 462 // the normal idle happens. 463 stack.processStoppingActivitiesLocked(false); 464 } else { 465 // If this activity was already idle, then we now need to 466 // make sure we perform the full stop of any activities 467 // that are waiting to do so. This is because we won't 468 // do that while they are still waiting for this one to 469 // become visible. 470 final int N = stack.mWaitingVisibleActivities.size(); 471 if (N > 0) { 472 for (int i=0; i<N; i++) { 473 ActivityRecord r = (ActivityRecord) 474 stack.mWaitingVisibleActivities.get(i); 475 r.waitingVisible = false; 476 if (ActivityManagerService.DEBUG_SWITCH) Log.v( 477 ActivityManagerService.TAG, 478 "Was waiting for visible: " + r); 479 } 480 stack.mWaitingVisibleActivities.clear(); 481 Message msg = Message.obtain(); 482 msg.what = ActivityStack.IDLE_NOW_MSG; 483 stack.mHandler.sendMessage(msg); 484 } 485 } 486 service.scheduleAppGcsLocked(); 487 } 488 } 489 } 490 491 public void windowsGone() { 492 if (ActivityManagerService.DEBUG_SWITCH) Log.v( 493 ActivityManagerService.TAG, "windowsGone(): " + this); 494 nowVisible = false; 495 } 496 497 private ActivityRecord getWaitingHistoryRecordLocked() { 498 // First find the real culprit... if we are waiting 499 // for another app to start, then we have paused dispatching 500 // for this activity. 501 ActivityRecord r = this; 502 if (r.waitingVisible) { 503 // Hmmm, who might we be waiting for? 504 r = stack.mResumedActivity; 505 if (r == null) { 506 r = stack.mPausingActivity; 507 } 508 // Both of those null? Fall back to 'this' again 509 if (r == null) { 510 r = this; 511 } 512 } 513 514 return r; 515 } 516 517 public boolean keyDispatchingTimedOut() { 518 ActivityRecord r; 519 ProcessRecord anrApp = null; 520 synchronized(service) { 521 r = getWaitingHistoryRecordLocked(); 522 if (r != null && r.app != null) { 523 if (r.app.debugging) { 524 return false; 525 } 526 527 if (service.mDidDexOpt) { 528 // Give more time since we were dexopting. 529 service.mDidDexOpt = false; 530 return false; 531 } 532 533 if (r.app.instrumentationClass == null) { 534 anrApp = r.app; 535 } else { 536 Bundle info = new Bundle(); 537 info.putString("shortMsg", "keyDispatchingTimedOut"); 538 info.putString("longMsg", "Timed out while dispatching key event"); 539 service.finishInstrumentationLocked( 540 r.app, Activity.RESULT_CANCELED, info); 541 } 542 } 543 } 544 545 if (anrApp != null) { 546 service.appNotResponding(anrApp, r, this, 547 "keyDispatchingTimedOut"); 548 } 549 550 return true; 551 } 552 553 /** Returns the key dispatching timeout for this application token. */ 554 public long getKeyDispatchingTimeout() { 555 synchronized(service) { 556 ActivityRecord r = getWaitingHistoryRecordLocked(); 557 if (r == null || r.app == null 558 || r.app.instrumentationClass == null) { 559 return ActivityManagerService.KEY_DISPATCHING_TIMEOUT; 560 } 561 562 return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT; 563 } 564 } 565 566 /** 567 * This method will return true if the activity is either visible, is becoming visible, is 568 * currently pausing, or is resumed. 569 */ 570 public boolean isInterestingToUserLocked() { 571 return visible || nowVisible || state == ActivityState.PAUSING || 572 state == ActivityState.RESUMED; 573 } 574 575 public String toString() { 576 if (stringName != null) { 577 return stringName; 578 } 579 StringBuilder sb = new StringBuilder(128); 580 sb.append("HistoryRecord{"); 581 sb.append(Integer.toHexString(System.identityHashCode(this))); 582 sb.append(' '); 583 sb.append(intent.getComponent().flattenToShortString()); 584 sb.append('}'); 585 return stringName = sb.toString(); 586 } 587 } 588