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 android.app; 18 19 import android.app.backup.BackupAgent; 20 import android.content.BroadcastReceiver; 21 import android.content.ComponentCallbacks; 22 import android.content.ComponentName; 23 import android.content.ContentProvider; 24 import android.content.Context; 25 import android.content.IContentProvider; 26 import android.content.Intent; 27 import android.content.IIntentReceiver; 28 import android.content.pm.ActivityInfo; 29 import android.content.pm.ApplicationInfo; 30 import android.content.pm.IPackageManager; 31 import android.content.pm.InstrumentationInfo; 32 import android.content.pm.PackageManager; 33 import android.content.pm.ProviderInfo; 34 import android.content.pm.ServiceInfo; 35 import android.content.res.AssetManager; 36 import android.content.res.CompatibilityInfo; 37 import android.content.res.Configuration; 38 import android.content.res.Resources; 39 import android.database.sqlite.SQLiteDatabase; 40 import android.database.sqlite.SQLiteDebug; 41 import android.database.sqlite.SQLiteDebug.DbStats; 42 import android.graphics.Bitmap; 43 import android.graphics.Canvas; 44 import android.os.Build; 45 import android.os.Bundle; 46 import android.os.Debug; 47 import android.os.Handler; 48 import android.os.IBinder; 49 import android.os.Looper; 50 import android.os.Message; 51 import android.os.MessageQueue; 52 import android.os.ParcelFileDescriptor; 53 import android.os.Process; 54 import android.os.RemoteException; 55 import android.os.ServiceManager; 56 import android.os.StrictMode; 57 import android.os.SystemClock; 58 import android.util.AndroidRuntimeException; 59 import android.util.Config; 60 import android.util.DisplayMetrics; 61 import android.util.EventLog; 62 import android.util.Log; 63 import android.util.LogPrinter; 64 import android.util.Slog; 65 import android.view.Display; 66 import android.view.View; 67 import android.view.ViewDebug; 68 import android.view.ViewManager; 69 import android.view.ViewRoot; 70 import android.view.Window; 71 import android.view.WindowManager; 72 import android.view.WindowManagerImpl; 73 74 import com.android.internal.os.BinderInternal; 75 import com.android.internal.os.RuntimeInit; 76 import com.android.internal.os.SamplingProfilerIntegration; 77 78 import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl; 79 80 import java.io.File; 81 import java.io.FileDescriptor; 82 import java.io.FileOutputStream; 83 import java.io.IOException; 84 import java.io.PrintWriter; 85 import java.lang.ref.WeakReference; 86 import java.util.ArrayList; 87 import java.util.HashMap; 88 import java.util.Iterator; 89 import java.util.List; 90 import java.util.Locale; 91 import java.util.Map; 92 import java.util.TimeZone; 93 import java.util.regex.Pattern; 94 95 import dalvik.system.SamplingProfiler; 96 97 final class SuperNotCalledException extends AndroidRuntimeException { SuperNotCalledException(String msg)98 public SuperNotCalledException(String msg) { 99 super(msg); 100 } 101 } 102 103 final class RemoteServiceException extends AndroidRuntimeException { RemoteServiceException(String msg)104 public RemoteServiceException(String msg) { 105 super(msg); 106 } 107 } 108 109 /** 110 * This manages the execution of the main thread in an 111 * application process, scheduling and executing activities, 112 * broadcasts, and other operations on it as the activity 113 * manager requests. 114 * 115 * {@hide} 116 */ 117 public final class ActivityThread { 118 static final String TAG = "ActivityThread"; 119 private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565; 120 private static final boolean DEBUG = false; 121 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; 122 static final boolean DEBUG_MESSAGES = false; 123 static final boolean DEBUG_BROADCAST = false; 124 private static final boolean DEBUG_RESULTS = false; 125 private static final boolean DEBUG_BACKUP = false; 126 private static final boolean DEBUG_CONFIGURATION = false; 127 private static final long MIN_TIME_BETWEEN_GCS = 5*1000; 128 private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); 129 private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; 130 private static final int LOG_ON_PAUSE_CALLED = 30021; 131 private static final int LOG_ON_RESUME_CALLED = 30022; 132 133 static ContextImpl mSystemContext = null; 134 135 static IPackageManager sPackageManager; 136 137 final ApplicationThread mAppThread = new ApplicationThread(); 138 final Looper mLooper = Looper.myLooper(); 139 final H mH = new H(); 140 final HashMap<IBinder, ActivityClientRecord> mActivities 141 = new HashMap<IBinder, ActivityClientRecord>(); 142 // List of new activities (via ActivityRecord.nextIdle) that should 143 // be reported when next we idle. 144 ActivityClientRecord mNewActivities = null; 145 // Number of activities that are currently visible on-screen. 146 int mNumVisibleActivities = 0; 147 final HashMap<IBinder, Service> mServices 148 = new HashMap<IBinder, Service>(); 149 AppBindData mBoundApplication; 150 Configuration mConfiguration; 151 Configuration mResConfiguration; 152 Application mInitialApplication; 153 final ArrayList<Application> mAllApplications 154 = new ArrayList<Application>(); 155 // set of instantiated backup agents, keyed by package name 156 final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>(); 157 static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal(); 158 Instrumentation mInstrumentation; 159 String mInstrumentationAppDir = null; 160 String mInstrumentationAppPackage = null; 161 String mInstrumentedAppDir = null; 162 boolean mSystemThread = false; 163 boolean mJitEnabled = false; 164 165 // These can be accessed by multiple threads; mPackages is the lock. 166 // XXX For now we keep around information about all packages we have 167 // seen, not removing entries from this map. 168 final HashMap<String, WeakReference<LoadedApk>> mPackages 169 = new HashMap<String, WeakReference<LoadedApk>>(); 170 final HashMap<String, WeakReference<LoadedApk>> mResourcePackages 171 = new HashMap<String, WeakReference<LoadedApk>>(); 172 Display mDisplay = null; 173 DisplayMetrics mDisplayMetrics = null; 174 final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources 175 = new HashMap<ResourcesKey, WeakReference<Resources> >(); 176 final ArrayList<ActivityClientRecord> mRelaunchingActivities 177 = new ArrayList<ActivityClientRecord>(); 178 Configuration mPendingConfiguration = null; 179 180 // The lock of mProviderMap protects the following variables. 181 final HashMap<String, ProviderClientRecord> mProviderMap 182 = new HashMap<String, ProviderClientRecord>(); 183 final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap 184 = new HashMap<IBinder, ProviderRefCount>(); 185 final HashMap<IBinder, ProviderClientRecord> mLocalProviders 186 = new HashMap<IBinder, ProviderClientRecord>(); 187 188 final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners 189 = new HashMap<Activity, ArrayList<OnActivityPausedListener>>(); 190 191 final GcIdler mGcIdler = new GcIdler(); 192 boolean mGcIdlerScheduled = false; 193 194 static Handler sMainThreadHandler; // set once in main() 195 196 private static final class ActivityClientRecord { 197 IBinder token; 198 int ident; 199 Intent intent; 200 Bundle state; 201 Activity activity; 202 Window window; 203 Activity parent; 204 String embeddedID; 205 Object lastNonConfigurationInstance; 206 HashMap<String,Object> lastNonConfigurationChildInstances; 207 boolean paused; 208 boolean stopped; 209 boolean hideForNow; 210 Configuration newConfig; 211 Configuration createdConfig; 212 ActivityClientRecord nextIdle; 213 214 ActivityInfo activityInfo; 215 LoadedApk packageInfo; 216 217 List<ResultInfo> pendingResults; 218 List<Intent> pendingIntents; 219 220 boolean startsNotResumed; 221 boolean isForward; 222 ActivityClientRecord()223 ActivityClientRecord() { 224 parent = null; 225 embeddedID = null; 226 paused = false; 227 stopped = false; 228 hideForNow = false; 229 nextIdle = null; 230 } 231 toString()232 public String toString() { 233 ComponentName componentName = intent.getComponent(); 234 return "ActivityRecord{" 235 + Integer.toHexString(System.identityHashCode(this)) 236 + " token=" + token + " " + (componentName == null 237 ? "no component name" : componentName.toShortString()) 238 + "}"; 239 } 240 } 241 242 private final class ProviderClientRecord implements IBinder.DeathRecipient { 243 final String mName; 244 final IContentProvider mProvider; 245 final ContentProvider mLocalProvider; 246 ProviderClientRecord(String name, IContentProvider provider, ContentProvider localProvider)247 ProviderClientRecord(String name, IContentProvider provider, 248 ContentProvider localProvider) { 249 mName = name; 250 mProvider = provider; 251 mLocalProvider = localProvider; 252 } 253 binderDied()254 public void binderDied() { 255 removeDeadProvider(mName, mProvider); 256 } 257 } 258 259 private static final class NewIntentData { 260 List<Intent> intents; 261 IBinder token; toString()262 public String toString() { 263 return "NewIntentData{intents=" + intents + " token=" + token + "}"; 264 } 265 } 266 267 private static final class ReceiverData { 268 Intent intent; 269 ActivityInfo info; 270 int resultCode; 271 String resultData; 272 Bundle resultExtras; 273 boolean sync; 274 boolean resultAbort; toString()275 public String toString() { 276 return "ReceiverData{intent=" + intent + " packageName=" + 277 info.packageName + " resultCode=" + resultCode 278 + " resultData=" + resultData + " resultExtras=" + resultExtras + "}"; 279 } 280 } 281 282 private static final class CreateBackupAgentData { 283 ApplicationInfo appInfo; 284 int backupMode; toString()285 public String toString() { 286 return "CreateBackupAgentData{appInfo=" + appInfo 287 + " backupAgent=" + appInfo.backupAgentName 288 + " mode=" + backupMode + "}"; 289 } 290 } 291 292 private static final class CreateServiceData { 293 IBinder token; 294 ServiceInfo info; 295 Intent intent; toString()296 public String toString() { 297 return "CreateServiceData{token=" + token + " className=" 298 + info.name + " packageName=" + info.packageName 299 + " intent=" + intent + "}"; 300 } 301 } 302 303 private static final class BindServiceData { 304 IBinder token; 305 Intent intent; 306 boolean rebind; toString()307 public String toString() { 308 return "BindServiceData{token=" + token + " intent=" + intent + "}"; 309 } 310 } 311 312 private static final class ServiceArgsData { 313 IBinder token; 314 int startId; 315 int flags; 316 Intent args; toString()317 public String toString() { 318 return "ServiceArgsData{token=" + token + " startId=" + startId 319 + " args=" + args + "}"; 320 } 321 } 322 323 private static final class AppBindData { 324 LoadedApk info; 325 String processName; 326 ApplicationInfo appInfo; 327 List<ProviderInfo> providers; 328 ComponentName instrumentationName; 329 String profileFile; 330 Bundle instrumentationArgs; 331 IInstrumentationWatcher instrumentationWatcher; 332 int debugMode; 333 boolean restrictedBackupMode; 334 Configuration config; 335 boolean handlingProfiling; toString()336 public String toString() { 337 return "AppBindData{appInfo=" + appInfo + "}"; 338 } 339 } 340 341 private static final class DumpServiceInfo { 342 FileDescriptor fd; 343 IBinder service; 344 String[] args; 345 boolean dumped; 346 } 347 348 private static final class ResultData { 349 IBinder token; 350 List<ResultInfo> results; toString()351 public String toString() { 352 return "ResultData{token=" + token + " results" + results + "}"; 353 } 354 } 355 356 private static final class ContextCleanupInfo { 357 ContextImpl context; 358 String what; 359 String who; 360 } 361 362 private static final class ProfilerControlData { 363 String path; 364 ParcelFileDescriptor fd; 365 } 366 367 private final class ApplicationThread extends ApplicationThreadNative { 368 private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s"; 369 private static final String ONE_COUNT_COLUMN = "%17s %8d"; 370 private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d"; 371 private static final String TWO_COUNT_COLUMNS_DB = "%20s %8d %20s %8d"; 372 private static final String DB_INFO_FORMAT = " %8d %8d %14d %s"; 373 374 // Formatting for checkin service - update version if row format changes 375 private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1; 376 schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges)377 public final void schedulePauseActivity(IBinder token, boolean finished, 378 boolean userLeaving, int configChanges) { 379 queueOrSendMessage( 380 finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, 381 token, 382 (userLeaving ? 1 : 0), 383 configChanges); 384 } 385 scheduleStopActivity(IBinder token, boolean showWindow, int configChanges)386 public final void scheduleStopActivity(IBinder token, boolean showWindow, 387 int configChanges) { 388 queueOrSendMessage( 389 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE, 390 token, 0, configChanges); 391 } 392 scheduleWindowVisibility(IBinder token, boolean showWindow)393 public final void scheduleWindowVisibility(IBinder token, boolean showWindow) { 394 queueOrSendMessage( 395 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW, 396 token); 397 } 398 scheduleResumeActivity(IBinder token, boolean isForward)399 public final void scheduleResumeActivity(IBinder token, boolean isForward) { 400 queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0); 401 } 402 scheduleSendResult(IBinder token, List<ResultInfo> results)403 public final void scheduleSendResult(IBinder token, List<ResultInfo> results) { 404 ResultData res = new ResultData(); 405 res.token = token; 406 res.results = results; 407 queueOrSendMessage(H.SEND_RESULT, res); 408 } 409 410 // we use token to identify this activity without having to send the 411 // activity itself back to the activity manager. (matters more with ipc) scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Bundle state, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)412 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, 413 ActivityInfo info, Bundle state, List<ResultInfo> pendingResults, 414 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) { 415 ActivityClientRecord r = new ActivityClientRecord(); 416 417 r.token = token; 418 r.ident = ident; 419 r.intent = intent; 420 r.activityInfo = info; 421 r.state = state; 422 423 r.pendingResults = pendingResults; 424 r.pendingIntents = pendingNewIntents; 425 426 r.startsNotResumed = notResumed; 427 r.isForward = isForward; 428 429 queueOrSendMessage(H.LAUNCH_ACTIVITY, r); 430 } 431 scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config)432 public final void scheduleRelaunchActivity(IBinder token, 433 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, 434 int configChanges, boolean notResumed, Configuration config) { 435 ActivityClientRecord r = new ActivityClientRecord(); 436 437 r.token = token; 438 r.pendingResults = pendingResults; 439 r.pendingIntents = pendingNewIntents; 440 r.startsNotResumed = notResumed; 441 r.createdConfig = config; 442 443 synchronized (mPackages) { 444 mRelaunchingActivities.add(r); 445 } 446 447 queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges); 448 } 449 scheduleNewIntent(List<Intent> intents, IBinder token)450 public final void scheduleNewIntent(List<Intent> intents, IBinder token) { 451 NewIntentData data = new NewIntentData(); 452 data.intents = intents; 453 data.token = token; 454 455 queueOrSendMessage(H.NEW_INTENT, data); 456 } 457 scheduleDestroyActivity(IBinder token, boolean finishing, int configChanges)458 public final void scheduleDestroyActivity(IBinder token, boolean finishing, 459 int configChanges) { 460 queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0, 461 configChanges); 462 } 463 scheduleReceiver(Intent intent, ActivityInfo info, int resultCode, String data, Bundle extras, boolean sync)464 public final void scheduleReceiver(Intent intent, ActivityInfo info, 465 int resultCode, String data, Bundle extras, boolean sync) { 466 ReceiverData r = new ReceiverData(); 467 468 r.intent = intent; 469 r.info = info; 470 r.resultCode = resultCode; 471 r.resultData = data; 472 r.resultExtras = extras; 473 r.sync = sync; 474 475 queueOrSendMessage(H.RECEIVER, r); 476 } 477 scheduleCreateBackupAgent(ApplicationInfo app, int backupMode)478 public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) { 479 CreateBackupAgentData d = new CreateBackupAgentData(); 480 d.appInfo = app; 481 d.backupMode = backupMode; 482 483 queueOrSendMessage(H.CREATE_BACKUP_AGENT, d); 484 } 485 scheduleDestroyBackupAgent(ApplicationInfo app)486 public final void scheduleDestroyBackupAgent(ApplicationInfo app) { 487 CreateBackupAgentData d = new CreateBackupAgentData(); 488 d.appInfo = app; 489 490 queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d); 491 } 492 scheduleCreateService(IBinder token, ServiceInfo info)493 public final void scheduleCreateService(IBinder token, 494 ServiceInfo info) { 495 CreateServiceData s = new CreateServiceData(); 496 s.token = token; 497 s.info = info; 498 499 queueOrSendMessage(H.CREATE_SERVICE, s); 500 } 501 scheduleBindService(IBinder token, Intent intent, boolean rebind)502 public final void scheduleBindService(IBinder token, Intent intent, 503 boolean rebind) { 504 BindServiceData s = new BindServiceData(); 505 s.token = token; 506 s.intent = intent; 507 s.rebind = rebind; 508 509 queueOrSendMessage(H.BIND_SERVICE, s); 510 } 511 scheduleUnbindService(IBinder token, Intent intent)512 public final void scheduleUnbindService(IBinder token, Intent intent) { 513 BindServiceData s = new BindServiceData(); 514 s.token = token; 515 s.intent = intent; 516 517 queueOrSendMessage(H.UNBIND_SERVICE, s); 518 } 519 scheduleServiceArgs(IBinder token, int startId, int flags ,Intent args)520 public final void scheduleServiceArgs(IBinder token, int startId, 521 int flags ,Intent args) { 522 ServiceArgsData s = new ServiceArgsData(); 523 s.token = token; 524 s.startId = startId; 525 s.flags = flags; 526 s.args = args; 527 528 queueOrSendMessage(H.SERVICE_ARGS, s); 529 } 530 scheduleStopService(IBinder token)531 public final void scheduleStopService(IBinder token) { 532 queueOrSendMessage(H.STOP_SERVICE, token); 533 } 534 bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, String profileFile, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, int debugMode, boolean isRestrictedBackupMode, Configuration config, Map<String, IBinder> services)535 public final void bindApplication(String processName, 536 ApplicationInfo appInfo, List<ProviderInfo> providers, 537 ComponentName instrumentationName, String profileFile, 538 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, 539 int debugMode, boolean isRestrictedBackupMode, Configuration config, 540 Map<String, IBinder> services) { 541 542 if (services != null) { 543 // Setup the service cache in the ServiceManager 544 ServiceManager.initServiceCache(services); 545 } 546 547 AppBindData data = new AppBindData(); 548 data.processName = processName; 549 data.appInfo = appInfo; 550 data.providers = providers; 551 data.instrumentationName = instrumentationName; 552 data.profileFile = profileFile; 553 data.instrumentationArgs = instrumentationArgs; 554 data.instrumentationWatcher = instrumentationWatcher; 555 data.debugMode = debugMode; 556 data.restrictedBackupMode = isRestrictedBackupMode; 557 data.config = config; 558 queueOrSendMessage(H.BIND_APPLICATION, data); 559 } 560 scheduleExit()561 public final void scheduleExit() { 562 queueOrSendMessage(H.EXIT_APPLICATION, null); 563 } 564 scheduleSuicide()565 public final void scheduleSuicide() { 566 queueOrSendMessage(H.SUICIDE, null); 567 } 568 requestThumbnail(IBinder token)569 public void requestThumbnail(IBinder token) { 570 queueOrSendMessage(H.REQUEST_THUMBNAIL, token); 571 } 572 scheduleConfigurationChanged(Configuration config)573 public void scheduleConfigurationChanged(Configuration config) { 574 synchronized (mPackages) { 575 if (mPendingConfiguration == null || 576 mPendingConfiguration.isOtherSeqNewer(config)) { 577 mPendingConfiguration = config; 578 } 579 } 580 queueOrSendMessage(H.CONFIGURATION_CHANGED, config); 581 } 582 updateTimeZone()583 public void updateTimeZone() { 584 TimeZone.setDefault(null); 585 } 586 processInBackground()587 public void processInBackground() { 588 mH.removeMessages(H.GC_WHEN_IDLE); 589 mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE)); 590 } 591 dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)592 public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) { 593 DumpServiceInfo data = new DumpServiceInfo(); 594 data.fd = fd; 595 data.service = servicetoken; 596 data.args = args; 597 data.dumped = false; 598 queueOrSendMessage(H.DUMP_SERVICE, data); 599 synchronized (data) { 600 while (!data.dumped) { 601 try { 602 data.wait(); 603 } catch (InterruptedException e) { 604 // no need to do anything here, we will keep waiting until 605 // dumped is set 606 } 607 } 608 } 609 } 610 611 // This function exists to make sure all receiver dispatching is 612 // correctly ordered, since these are one-way calls and the binder driver 613 // applies transaction ordering per object for such calls. scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)614 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, 615 int resultCode, String dataStr, Bundle extras, boolean ordered, 616 boolean sticky) throws RemoteException { 617 receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky); 618 } 619 scheduleLowMemory()620 public void scheduleLowMemory() { 621 queueOrSendMessage(H.LOW_MEMORY, null); 622 } 623 scheduleActivityConfigurationChanged(IBinder token)624 public void scheduleActivityConfigurationChanged(IBinder token) { 625 queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token); 626 } 627 profilerControl(boolean start, String path, ParcelFileDescriptor fd)628 public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) { 629 ProfilerControlData pcd = new ProfilerControlData(); 630 pcd.path = path; 631 pcd.fd = fd; 632 queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0); 633 } 634 setSchedulingGroup(int group)635 public void setSchedulingGroup(int group) { 636 // Note: do this immediately, since going into the foreground 637 // should happen regardless of what pending work we have to do 638 // and the activity manager will wait for us to report back that 639 // we are done before sending us to the background. 640 try { 641 Process.setProcessGroup(Process.myPid(), group); 642 } catch (Exception e) { 643 Slog.w(TAG, "Failed setting process group to " + group, e); 644 } 645 } 646 getMemoryInfo(Debug.MemoryInfo outInfo)647 public void getMemoryInfo(Debug.MemoryInfo outInfo) { 648 Debug.getMemoryInfo(outInfo); 649 } 650 dispatchPackageBroadcast(int cmd, String[] packages)651 public void dispatchPackageBroadcast(int cmd, String[] packages) { 652 queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd); 653 } 654 scheduleCrash(String msg)655 public void scheduleCrash(String msg) { 656 queueOrSendMessage(H.SCHEDULE_CRASH, msg); 657 } 658 659 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)660 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 661 long nativeMax = Debug.getNativeHeapSize() / 1024; 662 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; 663 long nativeFree = Debug.getNativeHeapFreeSize() / 1024; 664 665 Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); 666 Debug.getMemoryInfo(memInfo); 667 668 final int nativeShared = memInfo.nativeSharedDirty; 669 final int dalvikShared = memInfo.dalvikSharedDirty; 670 final int otherShared = memInfo.otherSharedDirty; 671 672 final int nativePrivate = memInfo.nativePrivateDirty; 673 final int dalvikPrivate = memInfo.dalvikPrivateDirty; 674 final int otherPrivate = memInfo.otherPrivateDirty; 675 676 Runtime runtime = Runtime.getRuntime(); 677 678 long dalvikMax = runtime.totalMemory() / 1024; 679 long dalvikFree = runtime.freeMemory() / 1024; 680 long dalvikAllocated = dalvikMax - dalvikFree; 681 long viewInstanceCount = ViewDebug.getViewInstanceCount(); 682 long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount(); 683 long appContextInstanceCount = ContextImpl.getInstanceCount(); 684 long activityInstanceCount = Activity.getInstanceCount(); 685 int globalAssetCount = AssetManager.getGlobalAssetCount(); 686 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount(); 687 int binderLocalObjectCount = Debug.getBinderLocalObjectCount(); 688 int binderProxyObjectCount = Debug.getBinderProxyObjectCount(); 689 int binderDeathObjectCount = Debug.getBinderDeathObjectCount(); 690 int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount(); 691 long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024; 692 SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo(); 693 694 // Check to see if we were called by checkin server. If so, print terse format. 695 boolean doCheckinFormat = false; 696 if (args != null) { 697 for (String arg : args) { 698 if ("-c".equals(arg)) doCheckinFormat = true; 699 } 700 } 701 702 // For checkin, we print one long comma-separated list of values 703 if (doCheckinFormat) { 704 // NOTE: if you change anything significant below, also consider changing 705 // ACTIVITY_THREAD_CHECKIN_VERSION. 706 String processName = (mBoundApplication != null) 707 ? mBoundApplication.processName : "unknown"; 708 709 // Header 710 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(','); 711 pw.print(Process.myPid()); pw.print(','); 712 pw.print(processName); pw.print(','); 713 714 // Heap info - max 715 pw.print(nativeMax); pw.print(','); 716 pw.print(dalvikMax); pw.print(','); 717 pw.print("N/A,"); 718 pw.print(nativeMax + dalvikMax); pw.print(','); 719 720 // Heap info - allocated 721 pw.print(nativeAllocated); pw.print(','); 722 pw.print(dalvikAllocated); pw.print(','); 723 pw.print("N/A,"); 724 pw.print(nativeAllocated + dalvikAllocated); pw.print(','); 725 726 // Heap info - free 727 pw.print(nativeFree); pw.print(','); 728 pw.print(dalvikFree); pw.print(','); 729 pw.print("N/A,"); 730 pw.print(nativeFree + dalvikFree); pw.print(','); 731 732 // Heap info - proportional set size 733 pw.print(memInfo.nativePss); pw.print(','); 734 pw.print(memInfo.dalvikPss); pw.print(','); 735 pw.print(memInfo.otherPss); pw.print(','); 736 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(','); 737 738 // Heap info - shared 739 pw.print(nativeShared); pw.print(','); 740 pw.print(dalvikShared); pw.print(','); 741 pw.print(otherShared); pw.print(','); 742 pw.print(nativeShared + dalvikShared + otherShared); pw.print(','); 743 744 // Heap info - private 745 pw.print(nativePrivate); pw.print(','); 746 pw.print(dalvikPrivate); pw.print(','); 747 pw.print(otherPrivate); pw.print(','); 748 pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(','); 749 750 // Object counts 751 pw.print(viewInstanceCount); pw.print(','); 752 pw.print(viewRootInstanceCount); pw.print(','); 753 pw.print(appContextInstanceCount); pw.print(','); 754 pw.print(activityInstanceCount); pw.print(','); 755 756 pw.print(globalAssetCount); pw.print(','); 757 pw.print(globalAssetManagerCount); pw.print(','); 758 pw.print(binderLocalObjectCount); pw.print(','); 759 pw.print(binderProxyObjectCount); pw.print(','); 760 761 pw.print(binderDeathObjectCount); pw.print(','); 762 pw.print(openSslSocketCount); pw.print(','); 763 764 // SQL 765 pw.print(sqliteAllocated); pw.print(','); 766 pw.print(stats.memoryUsed / 1024); pw.print(','); 767 pw.print(stats.pageCacheOverflo / 1024); pw.print(','); 768 pw.print(stats.largestMemAlloc / 1024); pw.print(','); 769 for (int i = 0; i < stats.dbStats.size(); i++) { 770 DbStats dbStats = stats.dbStats.get(i); 771 printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize, 772 dbStats.lookaside, dbStats.dbName); 773 pw.print(','); 774 } 775 776 return; 777 } 778 779 // otherwise, show human-readable format 780 printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total"); 781 printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax); 782 printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A", 783 nativeAllocated + dalvikAllocated); 784 printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A", 785 nativeFree + dalvikFree); 786 787 printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss, 788 memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); 789 790 printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared, 791 nativeShared + dalvikShared + otherShared); 792 printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate, 793 nativePrivate + dalvikPrivate + otherPrivate); 794 795 pw.println(" "); 796 pw.println(" Objects"); 797 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:", 798 viewRootInstanceCount); 799 800 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount, 801 "Activities:", activityInstanceCount); 802 803 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount, 804 "AssetManagers:", globalAssetManagerCount); 805 806 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount, 807 "Proxy Binders:", binderProxyObjectCount); 808 printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount); 809 810 printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount); 811 812 // SQLite mem info 813 pw.println(" "); 814 pw.println(" SQL"); 815 printRow(pw, TWO_COUNT_COLUMNS_DB, "heap:", sqliteAllocated, "MEMORY_USED:", 816 stats.memoryUsed / 1024); 817 printRow(pw, TWO_COUNT_COLUMNS_DB, "PAGECACHE_OVERFLOW:", 818 stats.pageCacheOverflo / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024); 819 pw.println(" "); 820 int N = stats.dbStats.size(); 821 if (N > 0) { 822 pw.println(" DATABASES"); 823 printRow(pw, " %8s %8s %14s %s", "pgsz", "dbsz", "Lookaside(b)", "Dbname"); 824 for (int i = 0; i < N; i++) { 825 DbStats dbStats = stats.dbStats.get(i); 826 printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize, 827 dbStats.lookaside, dbStats.dbName); 828 } 829 } 830 831 // Asset details. 832 String assetAlloc = AssetManager.getAssetAllocations(); 833 if (assetAlloc != null) { 834 pw.println(" "); 835 pw.println(" Asset Allocations"); 836 pw.print(assetAlloc); 837 } 838 } 839 printRow(PrintWriter pw, String format, Object...objs)840 private void printRow(PrintWriter pw, String format, Object...objs) { 841 pw.println(String.format(format, objs)); 842 } 843 } 844 845 private final class H extends Handler { 846 public static final int LAUNCH_ACTIVITY = 100; 847 public static final int PAUSE_ACTIVITY = 101; 848 public static final int PAUSE_ACTIVITY_FINISHING= 102; 849 public static final int STOP_ACTIVITY_SHOW = 103; 850 public static final int STOP_ACTIVITY_HIDE = 104; 851 public static final int SHOW_WINDOW = 105; 852 public static final int HIDE_WINDOW = 106; 853 public static final int RESUME_ACTIVITY = 107; 854 public static final int SEND_RESULT = 108; 855 public static final int DESTROY_ACTIVITY = 109; 856 public static final int BIND_APPLICATION = 110; 857 public static final int EXIT_APPLICATION = 111; 858 public static final int NEW_INTENT = 112; 859 public static final int RECEIVER = 113; 860 public static final int CREATE_SERVICE = 114; 861 public static final int SERVICE_ARGS = 115; 862 public static final int STOP_SERVICE = 116; 863 public static final int REQUEST_THUMBNAIL = 117; 864 public static final int CONFIGURATION_CHANGED = 118; 865 public static final int CLEAN_UP_CONTEXT = 119; 866 public static final int GC_WHEN_IDLE = 120; 867 public static final int BIND_SERVICE = 121; 868 public static final int UNBIND_SERVICE = 122; 869 public static final int DUMP_SERVICE = 123; 870 public static final int LOW_MEMORY = 124; 871 public static final int ACTIVITY_CONFIGURATION_CHANGED = 125; 872 public static final int RELAUNCH_ACTIVITY = 126; 873 public static final int PROFILER_CONTROL = 127; 874 public static final int CREATE_BACKUP_AGENT = 128; 875 public static final int DESTROY_BACKUP_AGENT = 129; 876 public static final int SUICIDE = 130; 877 public static final int REMOVE_PROVIDER = 131; 878 public static final int ENABLE_JIT = 132; 879 public static final int DISPATCH_PACKAGE_BROADCAST = 133; 880 public static final int SCHEDULE_CRASH = 134; codeToString(int code)881 String codeToString(int code) { 882 if (DEBUG_MESSAGES) { 883 switch (code) { 884 case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY"; 885 case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY"; 886 case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING"; 887 case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW"; 888 case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE"; 889 case SHOW_WINDOW: return "SHOW_WINDOW"; 890 case HIDE_WINDOW: return "HIDE_WINDOW"; 891 case RESUME_ACTIVITY: return "RESUME_ACTIVITY"; 892 case SEND_RESULT: return "SEND_RESULT"; 893 case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY"; 894 case BIND_APPLICATION: return "BIND_APPLICATION"; 895 case EXIT_APPLICATION: return "EXIT_APPLICATION"; 896 case NEW_INTENT: return "NEW_INTENT"; 897 case RECEIVER: return "RECEIVER"; 898 case CREATE_SERVICE: return "CREATE_SERVICE"; 899 case SERVICE_ARGS: return "SERVICE_ARGS"; 900 case STOP_SERVICE: return "STOP_SERVICE"; 901 case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL"; 902 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED"; 903 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT"; 904 case GC_WHEN_IDLE: return "GC_WHEN_IDLE"; 905 case BIND_SERVICE: return "BIND_SERVICE"; 906 case UNBIND_SERVICE: return "UNBIND_SERVICE"; 907 case DUMP_SERVICE: return "DUMP_SERVICE"; 908 case LOW_MEMORY: return "LOW_MEMORY"; 909 case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED"; 910 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; 911 case PROFILER_CONTROL: return "PROFILER_CONTROL"; 912 case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT"; 913 case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT"; 914 case SUICIDE: return "SUICIDE"; 915 case REMOVE_PROVIDER: return "REMOVE_PROVIDER"; 916 case ENABLE_JIT: return "ENABLE_JIT"; 917 case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST"; 918 case SCHEDULE_CRASH: return "SCHEDULE_CRASH"; 919 } 920 } 921 return "(unknown)"; 922 } handleMessage(Message msg)923 public void handleMessage(Message msg) { 924 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what); 925 switch (msg.what) { 926 case LAUNCH_ACTIVITY: { 927 ActivityClientRecord r = (ActivityClientRecord)msg.obj; 928 929 r.packageInfo = getPackageInfoNoCheck( 930 r.activityInfo.applicationInfo); 931 handleLaunchActivity(r, null); 932 } break; 933 case RELAUNCH_ACTIVITY: { 934 ActivityClientRecord r = (ActivityClientRecord)msg.obj; 935 handleRelaunchActivity(r, msg.arg1); 936 } break; 937 case PAUSE_ACTIVITY: 938 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2); 939 maybeSnapshot(); 940 break; 941 case PAUSE_ACTIVITY_FINISHING: 942 handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2); 943 break; 944 case STOP_ACTIVITY_SHOW: 945 handleStopActivity((IBinder)msg.obj, true, msg.arg2); 946 break; 947 case STOP_ACTIVITY_HIDE: 948 handleStopActivity((IBinder)msg.obj, false, msg.arg2); 949 break; 950 case SHOW_WINDOW: 951 handleWindowVisibility((IBinder)msg.obj, true); 952 break; 953 case HIDE_WINDOW: 954 handleWindowVisibility((IBinder)msg.obj, false); 955 break; 956 case RESUME_ACTIVITY: 957 handleResumeActivity((IBinder)msg.obj, true, 958 msg.arg1 != 0); 959 break; 960 case SEND_RESULT: 961 handleSendResult((ResultData)msg.obj); 962 break; 963 case DESTROY_ACTIVITY: 964 handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0, 965 msg.arg2, false); 966 break; 967 case BIND_APPLICATION: 968 AppBindData data = (AppBindData)msg.obj; 969 handleBindApplication(data); 970 break; 971 case EXIT_APPLICATION: 972 if (mInitialApplication != null) { 973 mInitialApplication.onTerminate(); 974 } 975 Looper.myLooper().quit(); 976 break; 977 case NEW_INTENT: 978 handleNewIntent((NewIntentData)msg.obj); 979 break; 980 case RECEIVER: 981 handleReceiver((ReceiverData)msg.obj); 982 maybeSnapshot(); 983 break; 984 case CREATE_SERVICE: 985 handleCreateService((CreateServiceData)msg.obj); 986 break; 987 case BIND_SERVICE: 988 handleBindService((BindServiceData)msg.obj); 989 break; 990 case UNBIND_SERVICE: 991 handleUnbindService((BindServiceData)msg.obj); 992 break; 993 case SERVICE_ARGS: 994 handleServiceArgs((ServiceArgsData)msg.obj); 995 break; 996 case STOP_SERVICE: 997 handleStopService((IBinder)msg.obj); 998 maybeSnapshot(); 999 break; 1000 case REQUEST_THUMBNAIL: 1001 handleRequestThumbnail((IBinder)msg.obj); 1002 break; 1003 case CONFIGURATION_CHANGED: 1004 handleConfigurationChanged((Configuration)msg.obj); 1005 break; 1006 case CLEAN_UP_CONTEXT: 1007 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj; 1008 cci.context.performFinalCleanup(cci.who, cci.what); 1009 break; 1010 case GC_WHEN_IDLE: 1011 scheduleGcIdler(); 1012 break; 1013 case DUMP_SERVICE: 1014 handleDumpService((DumpServiceInfo)msg.obj); 1015 break; 1016 case LOW_MEMORY: 1017 handleLowMemory(); 1018 break; 1019 case ACTIVITY_CONFIGURATION_CHANGED: 1020 handleActivityConfigurationChanged((IBinder)msg.obj); 1021 break; 1022 case PROFILER_CONTROL: 1023 handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj); 1024 break; 1025 case CREATE_BACKUP_AGENT: 1026 handleCreateBackupAgent((CreateBackupAgentData)msg.obj); 1027 break; 1028 case DESTROY_BACKUP_AGENT: 1029 handleDestroyBackupAgent((CreateBackupAgentData)msg.obj); 1030 break; 1031 case SUICIDE: 1032 Process.killProcess(Process.myPid()); 1033 break; 1034 case REMOVE_PROVIDER: 1035 completeRemoveProvider((IContentProvider)msg.obj); 1036 break; 1037 case ENABLE_JIT: 1038 ensureJitEnabled(); 1039 break; 1040 case DISPATCH_PACKAGE_BROADCAST: 1041 handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj); 1042 break; 1043 case SCHEDULE_CRASH: 1044 throw new RemoteServiceException((String)msg.obj); 1045 } 1046 if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what); 1047 } 1048 maybeSnapshot()1049 void maybeSnapshot() { 1050 if (mBoundApplication != null) { 1051 SamplingProfilerIntegration.writeSnapshot( 1052 mBoundApplication.processName); 1053 } 1054 } 1055 } 1056 1057 private final class Idler implements MessageQueue.IdleHandler { queueIdle()1058 public final boolean queueIdle() { 1059 ActivityClientRecord a = mNewActivities; 1060 if (a != null) { 1061 mNewActivities = null; 1062 IActivityManager am = ActivityManagerNative.getDefault(); 1063 ActivityClientRecord prev; 1064 do { 1065 if (localLOGV) Slog.v( 1066 TAG, "Reporting idle of " + a + 1067 " finished=" + 1068 (a.activity != null ? a.activity.mFinished : false)); 1069 if (a.activity != null && !a.activity.mFinished) { 1070 try { 1071 am.activityIdle(a.token, a.createdConfig); 1072 a.createdConfig = null; 1073 } catch (RemoteException ex) { 1074 } 1075 } 1076 prev = a; 1077 a = a.nextIdle; 1078 prev.nextIdle = null; 1079 } while (a != null); 1080 } 1081 ensureJitEnabled(); 1082 return false; 1083 } 1084 } 1085 1086 final class GcIdler implements MessageQueue.IdleHandler { queueIdle()1087 public final boolean queueIdle() { 1088 doGcIfNeeded(); 1089 return false; 1090 } 1091 } 1092 1093 private final static class ResourcesKey { 1094 final private String mResDir; 1095 final private float mScale; 1096 final private int mHash; 1097 ResourcesKey(String resDir, float scale)1098 ResourcesKey(String resDir, float scale) { 1099 mResDir = resDir; 1100 mScale = scale; 1101 mHash = mResDir.hashCode() << 2 + (int) (mScale * 2); 1102 } 1103 1104 @Override hashCode()1105 public int hashCode() { 1106 return mHash; 1107 } 1108 1109 @Override equals(Object obj)1110 public boolean equals(Object obj) { 1111 if (!(obj instanceof ResourcesKey)) { 1112 return false; 1113 } 1114 ResourcesKey peer = (ResourcesKey) obj; 1115 return mResDir.equals(peer.mResDir) && mScale == peer.mScale; 1116 } 1117 } 1118 currentActivityThread()1119 public static final ActivityThread currentActivityThread() { 1120 return sThreadLocal.get(); 1121 } 1122 currentPackageName()1123 public static final String currentPackageName() { 1124 ActivityThread am = currentActivityThread(); 1125 return (am != null && am.mBoundApplication != null) 1126 ? am.mBoundApplication.processName : null; 1127 } 1128 currentApplication()1129 public static final Application currentApplication() { 1130 ActivityThread am = currentActivityThread(); 1131 return am != null ? am.mInitialApplication : null; 1132 } 1133 getPackageManager()1134 public static IPackageManager getPackageManager() { 1135 if (sPackageManager != null) { 1136 //Slog.v("PackageManager", "returning cur default = " + sPackageManager); 1137 return sPackageManager; 1138 } 1139 IBinder b = ServiceManager.getService("package"); 1140 //Slog.v("PackageManager", "default service binder = " + b); 1141 sPackageManager = IPackageManager.Stub.asInterface(b); 1142 //Slog.v("PackageManager", "default service = " + sPackageManager); 1143 return sPackageManager; 1144 } 1145 getDisplayMetricsLocked(boolean forceUpdate)1146 DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) { 1147 if (mDisplayMetrics != null && !forceUpdate) { 1148 return mDisplayMetrics; 1149 } 1150 if (mDisplay == null) { 1151 WindowManager wm = WindowManagerImpl.getDefault(); 1152 mDisplay = wm.getDefaultDisplay(); 1153 } 1154 DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics(); 1155 mDisplay.getMetrics(metrics); 1156 //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h=" 1157 // + metrics.heightPixels + " den=" + metrics.density 1158 // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi); 1159 return metrics; 1160 } 1161 1162 /** 1163 * Creates the top level Resources for applications with the given compatibility info. 1164 * 1165 * @param resDir the resource directory. 1166 * @param compInfo the compability info. It will use the default compatibility info when it's 1167 * null. 1168 */ getTopLevelResources(String resDir, CompatibilityInfo compInfo)1169 Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) { 1170 ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale); 1171 Resources r; 1172 synchronized (mPackages) { 1173 // Resources is app scale dependent. 1174 if (false) { 1175 Slog.w(TAG, "getTopLevelResources: " + resDir + " / " 1176 + compInfo.applicationScale); 1177 } 1178 WeakReference<Resources> wr = mActiveResources.get(key); 1179 r = wr != null ? wr.get() : null; 1180 //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate()); 1181 if (r != null && r.getAssets().isUpToDate()) { 1182 if (false) { 1183 Slog.w(TAG, "Returning cached resources " + r + " " + resDir 1184 + ": appScale=" + r.getCompatibilityInfo().applicationScale); 1185 } 1186 return r; 1187 } 1188 } 1189 1190 //if (r != null) { 1191 // Slog.w(TAG, "Throwing away out-of-date resources!!!! " 1192 // + r + " " + resDir); 1193 //} 1194 1195 AssetManager assets = new AssetManager(); 1196 if (assets.addAssetPath(resDir) == 0) { 1197 return null; 1198 } 1199 1200 //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics); 1201 DisplayMetrics metrics = getDisplayMetricsLocked(false); 1202 r = new Resources(assets, metrics, getConfiguration(), compInfo); 1203 if (false) { 1204 Slog.i(TAG, "Created app resources " + resDir + " " + r + ": " 1205 + r.getConfiguration() + " appScale=" 1206 + r.getCompatibilityInfo().applicationScale); 1207 } 1208 1209 synchronized (mPackages) { 1210 WeakReference<Resources> wr = mActiveResources.get(key); 1211 Resources existing = wr != null ? wr.get() : null; 1212 if (existing != null && existing.getAssets().isUpToDate()) { 1213 // Someone else already created the resources while we were 1214 // unlocked; go ahead and use theirs. 1215 r.getAssets().close(); 1216 return existing; 1217 } 1218 1219 // XXX need to remove entries when weak references go away 1220 mActiveResources.put(key, new WeakReference<Resources>(r)); 1221 return r; 1222 } 1223 } 1224 1225 /** 1226 * Creates the top level resources for the given package. 1227 */ getTopLevelResources(String resDir, LoadedApk pkgInfo)1228 Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) { 1229 return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo); 1230 } 1231 getHandler()1232 final Handler getHandler() { 1233 return mH; 1234 } 1235 getPackageInfo(String packageName, int flags)1236 public final LoadedApk getPackageInfo(String packageName, int flags) { 1237 synchronized (mPackages) { 1238 WeakReference<LoadedApk> ref; 1239 if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) { 1240 ref = mPackages.get(packageName); 1241 } else { 1242 ref = mResourcePackages.get(packageName); 1243 } 1244 LoadedApk packageInfo = ref != null ? ref.get() : null; 1245 //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo); 1246 //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir 1247 // + ": " + packageInfo.mResources.getAssets().isUpToDate()); 1248 if (packageInfo != null && (packageInfo.mResources == null 1249 || packageInfo.mResources.getAssets().isUpToDate())) { 1250 if (packageInfo.isSecurityViolation() 1251 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) { 1252 throw new SecurityException( 1253 "Requesting code from " + packageName 1254 + " to be run in process " 1255 + mBoundApplication.processName 1256 + "/" + mBoundApplication.appInfo.uid); 1257 } 1258 return packageInfo; 1259 } 1260 } 1261 1262 ApplicationInfo ai = null; 1263 try { 1264 ai = getPackageManager().getApplicationInfo(packageName, 1265 PackageManager.GET_SHARED_LIBRARY_FILES); 1266 } catch (RemoteException e) { 1267 } 1268 1269 if (ai != null) { 1270 return getPackageInfo(ai, flags); 1271 } 1272 1273 return null; 1274 } 1275 getPackageInfo(ApplicationInfo ai, int flags)1276 public final LoadedApk getPackageInfo(ApplicationInfo ai, int flags) { 1277 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0; 1278 boolean securityViolation = includeCode && ai.uid != 0 1279 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null 1280 ? ai.uid != mBoundApplication.appInfo.uid : true); 1281 if ((flags&(Context.CONTEXT_INCLUDE_CODE 1282 |Context.CONTEXT_IGNORE_SECURITY)) 1283 == Context.CONTEXT_INCLUDE_CODE) { 1284 if (securityViolation) { 1285 String msg = "Requesting code from " + ai.packageName 1286 + " (with uid " + ai.uid + ")"; 1287 if (mBoundApplication != null) { 1288 msg = msg + " to be run in process " 1289 + mBoundApplication.processName + " (with uid " 1290 + mBoundApplication.appInfo.uid + ")"; 1291 } 1292 throw new SecurityException(msg); 1293 } 1294 } 1295 return getPackageInfo(ai, null, securityViolation, includeCode); 1296 } 1297 getPackageInfoNoCheck(ApplicationInfo ai)1298 public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai) { 1299 return getPackageInfo(ai, null, false, true); 1300 } 1301 getPackageInfo(ApplicationInfo aInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode)1302 private final LoadedApk getPackageInfo(ApplicationInfo aInfo, 1303 ClassLoader baseLoader, boolean securityViolation, boolean includeCode) { 1304 synchronized (mPackages) { 1305 WeakReference<LoadedApk> ref; 1306 if (includeCode) { 1307 ref = mPackages.get(aInfo.packageName); 1308 } else { 1309 ref = mResourcePackages.get(aInfo.packageName); 1310 } 1311 LoadedApk packageInfo = ref != null ? ref.get() : null; 1312 if (packageInfo == null || (packageInfo.mResources != null 1313 && !packageInfo.mResources.getAssets().isUpToDate())) { 1314 if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package " 1315 : "Loading resource-only package ") + aInfo.packageName 1316 + " (in " + (mBoundApplication != null 1317 ? mBoundApplication.processName : null) 1318 + ")"); 1319 packageInfo = 1320 new LoadedApk(this, aInfo, this, baseLoader, 1321 securityViolation, includeCode && 1322 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0); 1323 if (includeCode) { 1324 mPackages.put(aInfo.packageName, 1325 new WeakReference<LoadedApk>(packageInfo)); 1326 } else { 1327 mResourcePackages.put(aInfo.packageName, 1328 new WeakReference<LoadedApk>(packageInfo)); 1329 } 1330 } 1331 return packageInfo; 1332 } 1333 } 1334 ActivityThread()1335 ActivityThread() { 1336 } 1337 getApplicationThread()1338 public ApplicationThread getApplicationThread() 1339 { 1340 return mAppThread; 1341 } 1342 getInstrumentation()1343 public Instrumentation getInstrumentation() 1344 { 1345 return mInstrumentation; 1346 } 1347 getConfiguration()1348 public Configuration getConfiguration() { 1349 return mConfiguration; 1350 } 1351 isProfiling()1352 public boolean isProfiling() { 1353 return mBoundApplication != null && mBoundApplication.profileFile != null; 1354 } 1355 getProfileFilePath()1356 public String getProfileFilePath() { 1357 return mBoundApplication.profileFile; 1358 } 1359 getLooper()1360 public Looper getLooper() { 1361 return mLooper; 1362 } 1363 getApplication()1364 public Application getApplication() { 1365 return mInitialApplication; 1366 } 1367 getProcessName()1368 public String getProcessName() { 1369 return mBoundApplication.processName; 1370 } 1371 getSystemContext()1372 public ContextImpl getSystemContext() { 1373 synchronized (this) { 1374 if (mSystemContext == null) { 1375 ContextImpl context = 1376 ContextImpl.createSystemContext(this); 1377 LoadedApk info = new LoadedApk(this, "android", context, null); 1378 context.init(info, null, this); 1379 context.getResources().updateConfiguration( 1380 getConfiguration(), getDisplayMetricsLocked(false)); 1381 mSystemContext = context; 1382 //Slog.i(TAG, "Created system resources " + context.getResources() 1383 // + ": " + context.getResources().getConfiguration()); 1384 } 1385 } 1386 return mSystemContext; 1387 } 1388 installSystemApplicationInfo(ApplicationInfo info)1389 public void installSystemApplicationInfo(ApplicationInfo info) { 1390 synchronized (this) { 1391 ContextImpl context = getSystemContext(); 1392 context.init(new LoadedApk(this, "android", context, info), null, this); 1393 } 1394 } 1395 ensureJitEnabled()1396 void ensureJitEnabled() { 1397 if (!mJitEnabled) { 1398 mJitEnabled = true; 1399 dalvik.system.VMRuntime.getRuntime().startJitCompilation(); 1400 } 1401 } 1402 scheduleGcIdler()1403 void scheduleGcIdler() { 1404 if (!mGcIdlerScheduled) { 1405 mGcIdlerScheduled = true; 1406 Looper.myQueue().addIdleHandler(mGcIdler); 1407 } 1408 mH.removeMessages(H.GC_WHEN_IDLE); 1409 } 1410 unscheduleGcIdler()1411 void unscheduleGcIdler() { 1412 if (mGcIdlerScheduled) { 1413 mGcIdlerScheduled = false; 1414 Looper.myQueue().removeIdleHandler(mGcIdler); 1415 } 1416 mH.removeMessages(H.GC_WHEN_IDLE); 1417 } 1418 doGcIfNeeded()1419 void doGcIfNeeded() { 1420 mGcIdlerScheduled = false; 1421 final long now = SystemClock.uptimeMillis(); 1422 //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime() 1423 // + "m now=" + now); 1424 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) { 1425 //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!"); 1426 BinderInternal.forceGc("bg"); 1427 } 1428 } 1429 registerOnActivityPausedListener(Activity activity, OnActivityPausedListener listener)1430 public void registerOnActivityPausedListener(Activity activity, 1431 OnActivityPausedListener listener) { 1432 synchronized (mOnPauseListeners) { 1433 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); 1434 if (list == null) { 1435 list = new ArrayList<OnActivityPausedListener>(); 1436 mOnPauseListeners.put(activity, list); 1437 } 1438 list.add(listener); 1439 } 1440 } 1441 unregisterOnActivityPausedListener(Activity activity, OnActivityPausedListener listener)1442 public void unregisterOnActivityPausedListener(Activity activity, 1443 OnActivityPausedListener listener) { 1444 synchronized (mOnPauseListeners) { 1445 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); 1446 if (list != null) { 1447 list.remove(listener); 1448 } 1449 } 1450 } 1451 resolveActivityInfo(Intent intent)1452 public final ActivityInfo resolveActivityInfo(Intent intent) { 1453 ActivityInfo aInfo = intent.resolveActivityInfo( 1454 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES); 1455 if (aInfo == null) { 1456 // Throw an exception. 1457 Instrumentation.checkStartActivityResult( 1458 IActivityManager.START_CLASS_NOT_FOUND, intent); 1459 } 1460 return aInfo; 1461 } 1462 startActivityNow(Activity parent, String id, Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state, Object lastNonConfigurationInstance)1463 public final Activity startActivityNow(Activity parent, String id, 1464 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state, 1465 Object lastNonConfigurationInstance) { 1466 ActivityClientRecord r = new ActivityClientRecord(); 1467 r.token = token; 1468 r.ident = 0; 1469 r.intent = intent; 1470 r.state = state; 1471 r.parent = parent; 1472 r.embeddedID = id; 1473 r.activityInfo = activityInfo; 1474 r.lastNonConfigurationInstance = lastNonConfigurationInstance; 1475 if (localLOGV) { 1476 ComponentName compname = intent.getComponent(); 1477 String name; 1478 if (compname != null) { 1479 name = compname.toShortString(); 1480 } else { 1481 name = "(Intent " + intent + ").getComponent() returned null"; 1482 } 1483 Slog.v(TAG, "Performing launch: action=" + intent.getAction() 1484 + ", comp=" + name 1485 + ", token=" + token); 1486 } 1487 return performLaunchActivity(r, null); 1488 } 1489 getActivity(IBinder token)1490 public final Activity getActivity(IBinder token) { 1491 return mActivities.get(token).activity; 1492 } 1493 sendActivityResult( IBinder token, String id, int requestCode, int resultCode, Intent data)1494 public final void sendActivityResult( 1495 IBinder token, String id, int requestCode, 1496 int resultCode, Intent data) { 1497 if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id 1498 + " req=" + requestCode + " res=" + resultCode + " data=" + data); 1499 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 1500 list.add(new ResultInfo(id, requestCode, resultCode, data)); 1501 mAppThread.scheduleSendResult(token, list); 1502 } 1503 1504 // if the thread hasn't started yet, we don't have the handler, so just 1505 // save the messages until we're ready. queueOrSendMessage(int what, Object obj)1506 private final void queueOrSendMessage(int what, Object obj) { 1507 queueOrSendMessage(what, obj, 0, 0); 1508 } 1509 queueOrSendMessage(int what, Object obj, int arg1)1510 private final void queueOrSendMessage(int what, Object obj, int arg1) { 1511 queueOrSendMessage(what, obj, arg1, 0); 1512 } 1513 queueOrSendMessage(int what, Object obj, int arg1, int arg2)1514 private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { 1515 synchronized (this) { 1516 if (DEBUG_MESSAGES) Slog.v( 1517 TAG, "SCHEDULE " + what + " " + mH.codeToString(what) 1518 + ": " + arg1 + " / " + obj); 1519 Message msg = Message.obtain(); 1520 msg.what = what; 1521 msg.obj = obj; 1522 msg.arg1 = arg1; 1523 msg.arg2 = arg2; 1524 mH.sendMessage(msg); 1525 } 1526 } 1527 scheduleContextCleanup(ContextImpl context, String who, String what)1528 final void scheduleContextCleanup(ContextImpl context, String who, 1529 String what) { 1530 ContextCleanupInfo cci = new ContextCleanupInfo(); 1531 cci.context = context; 1532 cci.who = who; 1533 cci.what = what; 1534 queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci); 1535 } 1536 performLaunchActivity(ActivityClientRecord r, Intent customIntent)1537 private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { 1538 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); 1539 1540 ActivityInfo aInfo = r.activityInfo; 1541 if (r.packageInfo == null) { 1542 r.packageInfo = getPackageInfo(aInfo.applicationInfo, 1543 Context.CONTEXT_INCLUDE_CODE); 1544 } 1545 1546 ComponentName component = r.intent.getComponent(); 1547 if (component == null) { 1548 component = r.intent.resolveActivity( 1549 mInitialApplication.getPackageManager()); 1550 r.intent.setComponent(component); 1551 } 1552 1553 if (r.activityInfo.targetActivity != null) { 1554 component = new ComponentName(r.activityInfo.packageName, 1555 r.activityInfo.targetActivity); 1556 } 1557 1558 Activity activity = null; 1559 try { 1560 java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); 1561 activity = mInstrumentation.newActivity( 1562 cl, component.getClassName(), r.intent); 1563 r.intent.setExtrasClassLoader(cl); 1564 if (r.state != null) { 1565 r.state.setClassLoader(cl); 1566 } 1567 } catch (Exception e) { 1568 if (!mInstrumentation.onException(activity, e)) { 1569 throw new RuntimeException( 1570 "Unable to instantiate activity " + component 1571 + ": " + e.toString(), e); 1572 } 1573 } 1574 1575 try { 1576 Application app = r.packageInfo.makeApplication(false, mInstrumentation); 1577 1578 if (localLOGV) Slog.v(TAG, "Performing launch of " + r); 1579 if (localLOGV) Slog.v( 1580 TAG, r + ": app=" + app 1581 + ", appName=" + app.getPackageName() 1582 + ", pkg=" + r.packageInfo.getPackageName() 1583 + ", comp=" + r.intent.getComponent().toShortString() 1584 + ", dir=" + r.packageInfo.getAppDir()); 1585 1586 if (activity != null) { 1587 ContextImpl appContext = new ContextImpl(); 1588 appContext.init(r.packageInfo, r.token, this); 1589 appContext.setOuterContext(activity); 1590 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); 1591 Configuration config = new Configuration(mConfiguration); 1592 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " 1593 + r.activityInfo.name + " with config " + config); 1594 activity.attach(appContext, this, getInstrumentation(), r.token, 1595 r.ident, app, r.intent, r.activityInfo, title, r.parent, 1596 r.embeddedID, r.lastNonConfigurationInstance, 1597 r.lastNonConfigurationChildInstances, config); 1598 1599 if (customIntent != null) { 1600 activity.mIntent = customIntent; 1601 } 1602 r.lastNonConfigurationInstance = null; 1603 r.lastNonConfigurationChildInstances = null; 1604 activity.mStartedActivity = false; 1605 int theme = r.activityInfo.getThemeResource(); 1606 if (theme != 0) { 1607 activity.setTheme(theme); 1608 } 1609 1610 activity.mCalled = false; 1611 mInstrumentation.callActivityOnCreate(activity, r.state); 1612 if (!activity.mCalled) { 1613 throw new SuperNotCalledException( 1614 "Activity " + r.intent.getComponent().toShortString() + 1615 " did not call through to super.onCreate()"); 1616 } 1617 r.activity = activity; 1618 r.stopped = true; 1619 if (!r.activity.mFinished) { 1620 activity.performStart(); 1621 r.stopped = false; 1622 } 1623 if (!r.activity.mFinished) { 1624 if (r.state != null) { 1625 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); 1626 } 1627 } 1628 if (!r.activity.mFinished) { 1629 activity.mCalled = false; 1630 mInstrumentation.callActivityOnPostCreate(activity, r.state); 1631 if (!activity.mCalled) { 1632 throw new SuperNotCalledException( 1633 "Activity " + r.intent.getComponent().toShortString() + 1634 " did not call through to super.onPostCreate()"); 1635 } 1636 } 1637 } 1638 r.paused = true; 1639 1640 mActivities.put(r.token, r); 1641 1642 } catch (SuperNotCalledException e) { 1643 throw e; 1644 1645 } catch (Exception e) { 1646 if (!mInstrumentation.onException(activity, e)) { 1647 throw new RuntimeException( 1648 "Unable to start activity " + component 1649 + ": " + e.toString(), e); 1650 } 1651 } 1652 1653 return activity; 1654 } 1655 handleLaunchActivity(ActivityClientRecord r, Intent customIntent)1656 private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { 1657 // If we are getting ready to gc after going to the background, well 1658 // we are back active so skip it. 1659 unscheduleGcIdler(); 1660 1661 if (localLOGV) Slog.v( 1662 TAG, "Handling launch of " + r); 1663 Activity a = performLaunchActivity(r, customIntent); 1664 1665 if (a != null) { 1666 r.createdConfig = new Configuration(mConfiguration); 1667 Bundle oldState = r.state; 1668 handleResumeActivity(r.token, false, r.isForward); 1669 1670 if (!r.activity.mFinished && r.startsNotResumed) { 1671 // The activity manager actually wants this one to start out 1672 // paused, because it needs to be visible but isn't in the 1673 // foreground. We accomplish this by going through the 1674 // normal startup (because activities expect to go through 1675 // onResume() the first time they run, before their window 1676 // is displayed), and then pausing it. However, in this case 1677 // we do -not- need to do the full pause cycle (of freezing 1678 // and such) because the activity manager assumes it can just 1679 // retain the current state it has. 1680 try { 1681 r.activity.mCalled = false; 1682 mInstrumentation.callActivityOnPause(r.activity); 1683 // We need to keep around the original state, in case 1684 // we need to be created again. 1685 r.state = oldState; 1686 if (!r.activity.mCalled) { 1687 throw new SuperNotCalledException( 1688 "Activity " + r.intent.getComponent().toShortString() + 1689 " did not call through to super.onPause()"); 1690 } 1691 1692 } catch (SuperNotCalledException e) { 1693 throw e; 1694 1695 } catch (Exception e) { 1696 if (!mInstrumentation.onException(r.activity, e)) { 1697 throw new RuntimeException( 1698 "Unable to pause activity " 1699 + r.intent.getComponent().toShortString() 1700 + ": " + e.toString(), e); 1701 } 1702 } 1703 r.paused = true; 1704 } 1705 } else { 1706 // If there was an error, for any reason, tell the activity 1707 // manager to stop us. 1708 try { 1709 ActivityManagerNative.getDefault() 1710 .finishActivity(r.token, Activity.RESULT_CANCELED, null); 1711 } catch (RemoteException ex) { 1712 } 1713 } 1714 } 1715 deliverNewIntents(ActivityClientRecord r, List<Intent> intents)1716 private final void deliverNewIntents(ActivityClientRecord r, 1717 List<Intent> intents) { 1718 final int N = intents.size(); 1719 for (int i=0; i<N; i++) { 1720 Intent intent = intents.get(i); 1721 intent.setExtrasClassLoader(r.activity.getClassLoader()); 1722 mInstrumentation.callActivityOnNewIntent(r.activity, intent); 1723 } 1724 } 1725 performNewIntents(IBinder token, List<Intent> intents)1726 public final void performNewIntents(IBinder token, 1727 List<Intent> intents) { 1728 ActivityClientRecord r = mActivities.get(token); 1729 if (r != null) { 1730 final boolean resumed = !r.paused; 1731 if (resumed) { 1732 mInstrumentation.callActivityOnPause(r.activity); 1733 } 1734 deliverNewIntents(r, intents); 1735 if (resumed) { 1736 mInstrumentation.callActivityOnResume(r.activity); 1737 } 1738 } 1739 } 1740 handleNewIntent(NewIntentData data)1741 private final void handleNewIntent(NewIntentData data) { 1742 performNewIntents(data.token, data.intents); 1743 } 1744 handleReceiver(ReceiverData data)1745 private final void handleReceiver(ReceiverData data) { 1746 // If we are getting ready to gc after going to the background, well 1747 // we are back active so skip it. 1748 unscheduleGcIdler(); 1749 1750 String component = data.intent.getComponent().getClassName(); 1751 1752 LoadedApk packageInfo = getPackageInfoNoCheck( 1753 data.info.applicationInfo); 1754 1755 IActivityManager mgr = ActivityManagerNative.getDefault(); 1756 1757 BroadcastReceiver receiver = null; 1758 try { 1759 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 1760 data.intent.setExtrasClassLoader(cl); 1761 if (data.resultExtras != null) { 1762 data.resultExtras.setClassLoader(cl); 1763 } 1764 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); 1765 } catch (Exception e) { 1766 try { 1767 if (DEBUG_BROADCAST) Slog.i(TAG, 1768 "Finishing failed broadcast to " + data.intent.getComponent()); 1769 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode, 1770 data.resultData, data.resultExtras, data.resultAbort); 1771 } catch (RemoteException ex) { 1772 } 1773 throw new RuntimeException( 1774 "Unable to instantiate receiver " + component 1775 + ": " + e.toString(), e); 1776 } 1777 1778 try { 1779 Application app = packageInfo.makeApplication(false, mInstrumentation); 1780 1781 if (localLOGV) Slog.v( 1782 TAG, "Performing receive of " + data.intent 1783 + ": app=" + app 1784 + ", appName=" + app.getPackageName() 1785 + ", pkg=" + packageInfo.getPackageName() 1786 + ", comp=" + data.intent.getComponent().toShortString() 1787 + ", dir=" + packageInfo.getAppDir()); 1788 1789 ContextImpl context = (ContextImpl)app.getBaseContext(); 1790 receiver.setOrderedHint(true); 1791 receiver.setResult(data.resultCode, data.resultData, 1792 data.resultExtras); 1793 receiver.setOrderedHint(data.sync); 1794 receiver.onReceive(context.getReceiverRestrictedContext(), 1795 data.intent); 1796 } catch (Exception e) { 1797 try { 1798 if (DEBUG_BROADCAST) Slog.i(TAG, 1799 "Finishing failed broadcast to " + data.intent.getComponent()); 1800 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode, 1801 data.resultData, data.resultExtras, data.resultAbort); 1802 } catch (RemoteException ex) { 1803 } 1804 if (!mInstrumentation.onException(receiver, e)) { 1805 throw new RuntimeException( 1806 "Unable to start receiver " + component 1807 + ": " + e.toString(), e); 1808 } 1809 } 1810 1811 QueuedWork.waitToFinish(); 1812 1813 try { 1814 if (data.sync) { 1815 if (DEBUG_BROADCAST) Slog.i(TAG, 1816 "Finishing ordered broadcast to " + data.intent.getComponent()); 1817 mgr.finishReceiver( 1818 mAppThread.asBinder(), receiver.getResultCode(), 1819 receiver.getResultData(), receiver.getResultExtras(false), 1820 receiver.getAbortBroadcast()); 1821 } else { 1822 if (DEBUG_BROADCAST) Slog.i(TAG, 1823 "Finishing broadcast to " + data.intent.getComponent()); 1824 mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false); 1825 } 1826 } catch (RemoteException ex) { 1827 } 1828 } 1829 1830 // Instantiate a BackupAgent and tell it that it's alive handleCreateBackupAgent(CreateBackupAgentData data)1831 private final void handleCreateBackupAgent(CreateBackupAgentData data) { 1832 if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data); 1833 1834 // no longer idle; we have backup work to do 1835 unscheduleGcIdler(); 1836 1837 // instantiate the BackupAgent class named in the manifest 1838 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo); 1839 String packageName = packageInfo.mPackageName; 1840 if (mBackupAgents.get(packageName) != null) { 1841 Slog.d(TAG, "BackupAgent " + " for " + packageName 1842 + " already exists"); 1843 return; 1844 } 1845 1846 BackupAgent agent = null; 1847 String classname = data.appInfo.backupAgentName; 1848 if (classname == null) { 1849 if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) { 1850 Slog.e(TAG, "Attempted incremental backup but no defined agent for " 1851 + packageName); 1852 return; 1853 } 1854 classname = "android.app.FullBackupAgent"; 1855 } 1856 try { 1857 IBinder binder = null; 1858 try { 1859 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 1860 agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance(); 1861 1862 // set up the agent's context 1863 if (DEBUG_BACKUP) Slog.v(TAG, "Initializing BackupAgent " 1864 + data.appInfo.backupAgentName); 1865 1866 ContextImpl context = new ContextImpl(); 1867 context.init(packageInfo, null, this); 1868 context.setOuterContext(agent); 1869 agent.attach(context); 1870 1871 agent.onCreate(); 1872 binder = agent.onBind(); 1873 mBackupAgents.put(packageName, agent); 1874 } catch (Exception e) { 1875 // If this is during restore, fail silently; otherwise go 1876 // ahead and let the user see the crash. 1877 Slog.e(TAG, "Agent threw during creation: " + e); 1878 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) { 1879 throw e; 1880 } 1881 // falling through with 'binder' still null 1882 } 1883 1884 // tell the OS that we're live now 1885 try { 1886 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder); 1887 } catch (RemoteException e) { 1888 // nothing to do. 1889 } 1890 } catch (Exception e) { 1891 throw new RuntimeException("Unable to create BackupAgent " 1892 + data.appInfo.backupAgentName + ": " + e.toString(), e); 1893 } 1894 } 1895 1896 // Tear down a BackupAgent handleDestroyBackupAgent(CreateBackupAgentData data)1897 private final void handleDestroyBackupAgent(CreateBackupAgentData data) { 1898 if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data); 1899 1900 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo); 1901 String packageName = packageInfo.mPackageName; 1902 BackupAgent agent = mBackupAgents.get(packageName); 1903 if (agent != null) { 1904 try { 1905 agent.onDestroy(); 1906 } catch (Exception e) { 1907 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo); 1908 e.printStackTrace(); 1909 } 1910 mBackupAgents.remove(packageName); 1911 } else { 1912 Slog.w(TAG, "Attempt to destroy unknown backup agent " + data); 1913 } 1914 } 1915 handleCreateService(CreateServiceData data)1916 private final void handleCreateService(CreateServiceData data) { 1917 // If we are getting ready to gc after going to the background, well 1918 // we are back active so skip it. 1919 unscheduleGcIdler(); 1920 1921 LoadedApk packageInfo = getPackageInfoNoCheck( 1922 data.info.applicationInfo); 1923 Service service = null; 1924 try { 1925 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 1926 service = (Service) cl.loadClass(data.info.name).newInstance(); 1927 } catch (Exception e) { 1928 if (!mInstrumentation.onException(service, e)) { 1929 throw new RuntimeException( 1930 "Unable to instantiate service " + data.info.name 1931 + ": " + e.toString(), e); 1932 } 1933 } 1934 1935 try { 1936 if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); 1937 1938 ContextImpl context = new ContextImpl(); 1939 context.init(packageInfo, null, this); 1940 1941 Application app = packageInfo.makeApplication(false, mInstrumentation); 1942 context.setOuterContext(service); 1943 service.attach(context, this, data.info.name, data.token, app, 1944 ActivityManagerNative.getDefault()); 1945 service.onCreate(); 1946 mServices.put(data.token, service); 1947 try { 1948 ActivityManagerNative.getDefault().serviceDoneExecuting( 1949 data.token, 0, 0, 0); 1950 } catch (RemoteException e) { 1951 // nothing to do. 1952 } 1953 } catch (Exception e) { 1954 if (!mInstrumentation.onException(service, e)) { 1955 throw new RuntimeException( 1956 "Unable to create service " + data.info.name 1957 + ": " + e.toString(), e); 1958 } 1959 } 1960 } 1961 handleBindService(BindServiceData data)1962 private final void handleBindService(BindServiceData data) { 1963 Service s = mServices.get(data.token); 1964 if (s != null) { 1965 try { 1966 data.intent.setExtrasClassLoader(s.getClassLoader()); 1967 try { 1968 if (!data.rebind) { 1969 IBinder binder = s.onBind(data.intent); 1970 ActivityManagerNative.getDefault().publishService( 1971 data.token, data.intent, binder); 1972 } else { 1973 s.onRebind(data.intent); 1974 ActivityManagerNative.getDefault().serviceDoneExecuting( 1975 data.token, 0, 0, 0); 1976 } 1977 ensureJitEnabled(); 1978 } catch (RemoteException ex) { 1979 } 1980 } catch (Exception e) { 1981 if (!mInstrumentation.onException(s, e)) { 1982 throw new RuntimeException( 1983 "Unable to bind to service " + s 1984 + " with " + data.intent + ": " + e.toString(), e); 1985 } 1986 } 1987 } 1988 } 1989 handleUnbindService(BindServiceData data)1990 private final void handleUnbindService(BindServiceData data) { 1991 Service s = mServices.get(data.token); 1992 if (s != null) { 1993 try { 1994 data.intent.setExtrasClassLoader(s.getClassLoader()); 1995 boolean doRebind = s.onUnbind(data.intent); 1996 try { 1997 if (doRebind) { 1998 ActivityManagerNative.getDefault().unbindFinished( 1999 data.token, data.intent, doRebind); 2000 } else { 2001 ActivityManagerNative.getDefault().serviceDoneExecuting( 2002 data.token, 0, 0, 0); 2003 } 2004 } catch (RemoteException ex) { 2005 } 2006 } catch (Exception e) { 2007 if (!mInstrumentation.onException(s, e)) { 2008 throw new RuntimeException( 2009 "Unable to unbind to service " + s 2010 + " with " + data.intent + ": " + e.toString(), e); 2011 } 2012 } 2013 } 2014 } 2015 handleDumpService(DumpServiceInfo info)2016 private void handleDumpService(DumpServiceInfo info) { 2017 try { 2018 Service s = mServices.get(info.service); 2019 if (s != null) { 2020 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd)); 2021 s.dump(info.fd, pw, info.args); 2022 pw.close(); 2023 } 2024 } finally { 2025 synchronized (info) { 2026 info.dumped = true; 2027 info.notifyAll(); 2028 } 2029 } 2030 } 2031 handleServiceArgs(ServiceArgsData data)2032 private final void handleServiceArgs(ServiceArgsData data) { 2033 Service s = mServices.get(data.token); 2034 if (s != null) { 2035 try { 2036 if (data.args != null) { 2037 data.args.setExtrasClassLoader(s.getClassLoader()); 2038 } 2039 int res = s.onStartCommand(data.args, data.flags, data.startId); 2040 2041 QueuedWork.waitToFinish(); 2042 2043 try { 2044 ActivityManagerNative.getDefault().serviceDoneExecuting( 2045 data.token, 1, data.startId, res); 2046 } catch (RemoteException e) { 2047 // nothing to do. 2048 } 2049 ensureJitEnabled(); 2050 } catch (Exception e) { 2051 if (!mInstrumentation.onException(s, e)) { 2052 throw new RuntimeException( 2053 "Unable to start service " + s 2054 + " with " + data.args + ": " + e.toString(), e); 2055 } 2056 } 2057 } 2058 } 2059 handleStopService(IBinder token)2060 private final void handleStopService(IBinder token) { 2061 Service s = mServices.remove(token); 2062 if (s != null) { 2063 try { 2064 if (localLOGV) Slog.v(TAG, "Destroying service " + s); 2065 s.onDestroy(); 2066 Context context = s.getBaseContext(); 2067 if (context instanceof ContextImpl) { 2068 final String who = s.getClassName(); 2069 ((ContextImpl) context).scheduleFinalCleanup(who, "Service"); 2070 } 2071 2072 QueuedWork.waitToFinish(); 2073 2074 try { 2075 ActivityManagerNative.getDefault().serviceDoneExecuting( 2076 token, 0, 0, 0); 2077 } catch (RemoteException e) { 2078 // nothing to do. 2079 } 2080 } catch (Exception e) { 2081 if (!mInstrumentation.onException(s, e)) { 2082 throw new RuntimeException( 2083 "Unable to stop service " + s 2084 + ": " + e.toString(), e); 2085 } 2086 } 2087 } 2088 //Slog.i(TAG, "Running services: " + mServices); 2089 } 2090 performResumeActivity(IBinder token, boolean clearHide)2091 public final ActivityClientRecord performResumeActivity(IBinder token, 2092 boolean clearHide) { 2093 ActivityClientRecord r = mActivities.get(token); 2094 if (localLOGV) Slog.v(TAG, "Performing resume of " + r 2095 + " finished=" + r.activity.mFinished); 2096 if (r != null && !r.activity.mFinished) { 2097 if (clearHide) { 2098 r.hideForNow = false; 2099 r.activity.mStartedActivity = false; 2100 } 2101 try { 2102 if (r.pendingIntents != null) { 2103 deliverNewIntents(r, r.pendingIntents); 2104 r.pendingIntents = null; 2105 } 2106 if (r.pendingResults != null) { 2107 deliverResults(r, r.pendingResults); 2108 r.pendingResults = null; 2109 } 2110 r.activity.performResume(); 2111 2112 EventLog.writeEvent(LOG_ON_RESUME_CALLED, 2113 r.activity.getComponentName().getClassName()); 2114 2115 r.paused = false; 2116 r.stopped = false; 2117 r.state = null; 2118 } catch (Exception e) { 2119 if (!mInstrumentation.onException(r.activity, e)) { 2120 throw new RuntimeException( 2121 "Unable to resume activity " 2122 + r.intent.getComponent().toShortString() 2123 + ": " + e.toString(), e); 2124 } 2125 } 2126 } 2127 return r; 2128 } 2129 handleResumeActivity(IBinder token, boolean clearHide, boolean isForward)2130 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) { 2131 // If we are getting ready to gc after going to the background, well 2132 // we are back active so skip it. 2133 unscheduleGcIdler(); 2134 2135 ActivityClientRecord r = performResumeActivity(token, clearHide); 2136 2137 if (r != null) { 2138 final Activity a = r.activity; 2139 2140 if (localLOGV) Slog.v( 2141 TAG, "Resume " + r + " started activity: " + 2142 a.mStartedActivity + ", hideForNow: " + r.hideForNow 2143 + ", finished: " + a.mFinished); 2144 2145 final int forwardBit = isForward ? 2146 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0; 2147 2148 // If the window hasn't yet been added to the window manager, 2149 // and this guy didn't finish itself or start another activity, 2150 // then go ahead and add the window. 2151 boolean willBeVisible = !a.mStartedActivity; 2152 if (!willBeVisible) { 2153 try { 2154 willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible( 2155 a.getActivityToken()); 2156 } catch (RemoteException e) { 2157 } 2158 } 2159 if (r.window == null && !a.mFinished && willBeVisible) { 2160 r.window = r.activity.getWindow(); 2161 View decor = r.window.getDecorView(); 2162 decor.setVisibility(View.INVISIBLE); 2163 ViewManager wm = a.getWindowManager(); 2164 WindowManager.LayoutParams l = r.window.getAttributes(); 2165 a.mDecor = decor; 2166 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 2167 l.softInputMode |= forwardBit; 2168 if (a.mVisibleFromClient) { 2169 a.mWindowAdded = true; 2170 wm.addView(decor, l); 2171 } 2172 2173 // If the window has already been added, but during resume 2174 // we started another activity, then don't yet make the 2175 // window visible. 2176 } else if (!willBeVisible) { 2177 if (localLOGV) Slog.v( 2178 TAG, "Launch " + r + " mStartedActivity set"); 2179 r.hideForNow = true; 2180 } 2181 2182 // The window is now visible if it has been added, we are not 2183 // simply finishing, and we are not starting another activity. 2184 if (!r.activity.mFinished && willBeVisible 2185 && r.activity.mDecor != null && !r.hideForNow) { 2186 if (r.newConfig != null) { 2187 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity " 2188 + r.activityInfo.name + " with newConfig " + r.newConfig); 2189 performConfigurationChanged(r.activity, r.newConfig); 2190 r.newConfig = null; 2191 } 2192 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" 2193 + isForward); 2194 WindowManager.LayoutParams l = r.window.getAttributes(); 2195 if ((l.softInputMode 2196 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) 2197 != forwardBit) { 2198 l.softInputMode = (l.softInputMode 2199 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)) 2200 | forwardBit; 2201 if (r.activity.mVisibleFromClient) { 2202 ViewManager wm = a.getWindowManager(); 2203 View decor = r.window.getDecorView(); 2204 wm.updateViewLayout(decor, l); 2205 } 2206 } 2207 r.activity.mVisibleFromServer = true; 2208 mNumVisibleActivities++; 2209 if (r.activity.mVisibleFromClient) { 2210 r.activity.makeVisible(); 2211 } 2212 } 2213 2214 r.nextIdle = mNewActivities; 2215 mNewActivities = r; 2216 if (localLOGV) Slog.v( 2217 TAG, "Scheduling idle handler for " + r); 2218 Looper.myQueue().addIdleHandler(new Idler()); 2219 2220 } else { 2221 // If an exception was thrown when trying to resume, then 2222 // just end this activity. 2223 try { 2224 ActivityManagerNative.getDefault() 2225 .finishActivity(token, Activity.RESULT_CANCELED, null); 2226 } catch (RemoteException ex) { 2227 } 2228 } 2229 } 2230 2231 private int mThumbnailWidth = -1; 2232 private int mThumbnailHeight = -1; 2233 createThumbnailBitmap(ActivityClientRecord r)2234 private final Bitmap createThumbnailBitmap(ActivityClientRecord r) { 2235 Bitmap thumbnail = null; 2236 try { 2237 int w = mThumbnailWidth; 2238 int h; 2239 if (w < 0) { 2240 Resources res = r.activity.getResources(); 2241 mThumbnailHeight = h = 2242 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); 2243 2244 mThumbnailWidth = w = 2245 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); 2246 } else { 2247 h = mThumbnailHeight; 2248 } 2249 2250 // On platforms where we don't want thumbnails, set dims to (0,0) 2251 if ((w > 0) && (h > 0)) { 2252 View topView = r.activity.getWindow().getDecorView(); 2253 2254 // Maximize bitmap by capturing in native aspect. 2255 if (topView.getWidth() >= topView.getHeight()) { 2256 thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT); 2257 } else { 2258 thumbnail = Bitmap.createBitmap(h, w, THUMBNAIL_FORMAT); 2259 } 2260 2261 thumbnail.eraseColor(0); 2262 Canvas cv = new Canvas(thumbnail); 2263 if (!r.activity.onCreateThumbnail(thumbnail, cv)) { 2264 thumbnail = null; 2265 } 2266 } 2267 2268 } catch (Exception e) { 2269 if (!mInstrumentation.onException(r.activity, e)) { 2270 throw new RuntimeException( 2271 "Unable to create thumbnail of " 2272 + r.intent.getComponent().toShortString() 2273 + ": " + e.toString(), e); 2274 } 2275 thumbnail = null; 2276 } 2277 2278 return thumbnail; 2279 } 2280 handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges)2281 private final void handlePauseActivity(IBinder token, boolean finished, 2282 boolean userLeaving, int configChanges) { 2283 ActivityClientRecord r = mActivities.get(token); 2284 if (r != null) { 2285 //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); 2286 if (userLeaving) { 2287 performUserLeavingActivity(r); 2288 } 2289 2290 r.activity.mConfigChangeFlags |= configChanges; 2291 Bundle state = performPauseActivity(token, finished, true); 2292 2293 // Make sure any pending writes are now committed. 2294 QueuedWork.waitToFinish(); 2295 2296 // Tell the activity manager we have paused. 2297 try { 2298 ActivityManagerNative.getDefault().activityPaused(token, state); 2299 } catch (RemoteException ex) { 2300 } 2301 } 2302 } 2303 performUserLeavingActivity(ActivityClientRecord r)2304 final void performUserLeavingActivity(ActivityClientRecord r) { 2305 mInstrumentation.callActivityOnUserLeaving(r.activity); 2306 } 2307 performPauseActivity(IBinder token, boolean finished, boolean saveState)2308 final Bundle performPauseActivity(IBinder token, boolean finished, 2309 boolean saveState) { 2310 ActivityClientRecord r = mActivities.get(token); 2311 return r != null ? performPauseActivity(r, finished, saveState) : null; 2312 } 2313 performPauseActivity(ActivityClientRecord r, boolean finished, boolean saveState)2314 final Bundle performPauseActivity(ActivityClientRecord r, boolean finished, 2315 boolean saveState) { 2316 if (r.paused) { 2317 if (r.activity.mFinished) { 2318 // If we are finishing, we won't call onResume() in certain cases. 2319 // So here we likewise don't want to call onPause() if the activity 2320 // isn't resumed. 2321 return null; 2322 } 2323 RuntimeException e = new RuntimeException( 2324 "Performing pause of activity that is not resumed: " 2325 + r.intent.getComponent().toShortString()); 2326 Slog.e(TAG, e.getMessage(), e); 2327 } 2328 Bundle state = null; 2329 if (finished) { 2330 r.activity.mFinished = true; 2331 } 2332 try { 2333 // Next have the activity save its current state and managed dialogs... 2334 if (!r.activity.mFinished && saveState) { 2335 state = new Bundle(); 2336 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); 2337 r.state = state; 2338 } 2339 // Now we are idle. 2340 r.activity.mCalled = false; 2341 mInstrumentation.callActivityOnPause(r.activity); 2342 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName()); 2343 if (!r.activity.mCalled) { 2344 throw new SuperNotCalledException( 2345 "Activity " + r.intent.getComponent().toShortString() + 2346 " did not call through to super.onPause()"); 2347 } 2348 2349 } catch (SuperNotCalledException e) { 2350 throw e; 2351 2352 } catch (Exception e) { 2353 if (!mInstrumentation.onException(r.activity, e)) { 2354 throw new RuntimeException( 2355 "Unable to pause activity " 2356 + r.intent.getComponent().toShortString() 2357 + ": " + e.toString(), e); 2358 } 2359 } 2360 r.paused = true; 2361 2362 // Notify any outstanding on paused listeners 2363 ArrayList<OnActivityPausedListener> listeners; 2364 synchronized (mOnPauseListeners) { 2365 listeners = mOnPauseListeners.remove(r.activity); 2366 } 2367 int size = (listeners != null ? listeners.size() : 0); 2368 for (int i = 0; i < size; i++) { 2369 listeners.get(i).onPaused(r.activity); 2370 } 2371 2372 return state; 2373 } 2374 performStopActivity(IBinder token)2375 final void performStopActivity(IBinder token) { 2376 ActivityClientRecord r = mActivities.get(token); 2377 performStopActivityInner(r, null, false); 2378 } 2379 2380 private static class StopInfo { 2381 Bitmap thumbnail; 2382 CharSequence description; 2383 } 2384 2385 private final class ProviderRefCount { 2386 public int count; ProviderRefCount(int pCount)2387 ProviderRefCount(int pCount) { 2388 count = pCount; 2389 } 2390 } 2391 performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown)2392 private final void performStopActivityInner(ActivityClientRecord r, 2393 StopInfo info, boolean keepShown) { 2394 if (localLOGV) Slog.v(TAG, "Performing stop of " + r); 2395 if (r != null) { 2396 if (!keepShown && r.stopped) { 2397 if (r.activity.mFinished) { 2398 // If we are finishing, we won't call onResume() in certain 2399 // cases. So here we likewise don't want to call onStop() 2400 // if the activity isn't resumed. 2401 return; 2402 } 2403 RuntimeException e = new RuntimeException( 2404 "Performing stop of activity that is not resumed: " 2405 + r.intent.getComponent().toShortString()); 2406 Slog.e(TAG, e.getMessage(), e); 2407 } 2408 2409 if (info != null) { 2410 try { 2411 // First create a thumbnail for the activity... 2412 info.thumbnail = createThumbnailBitmap(r); 2413 info.description = r.activity.onCreateDescription(); 2414 } catch (Exception e) { 2415 if (!mInstrumentation.onException(r.activity, e)) { 2416 throw new RuntimeException( 2417 "Unable to save state of activity " 2418 + r.intent.getComponent().toShortString() 2419 + ": " + e.toString(), e); 2420 } 2421 } 2422 } 2423 2424 if (!keepShown) { 2425 try { 2426 // Now we are idle. 2427 r.activity.performStop(); 2428 } catch (Exception e) { 2429 if (!mInstrumentation.onException(r.activity, e)) { 2430 throw new RuntimeException( 2431 "Unable to stop activity " 2432 + r.intent.getComponent().toShortString() 2433 + ": " + e.toString(), e); 2434 } 2435 } 2436 r.stopped = true; 2437 } 2438 2439 r.paused = true; 2440 } 2441 } 2442 updateVisibility(ActivityClientRecord r, boolean show)2443 private final void updateVisibility(ActivityClientRecord r, boolean show) { 2444 View v = r.activity.mDecor; 2445 if (v != null) { 2446 if (show) { 2447 if (!r.activity.mVisibleFromServer) { 2448 r.activity.mVisibleFromServer = true; 2449 mNumVisibleActivities++; 2450 if (r.activity.mVisibleFromClient) { 2451 r.activity.makeVisible(); 2452 } 2453 } 2454 if (r.newConfig != null) { 2455 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis " 2456 + r.activityInfo.name + " with new config " + r.newConfig); 2457 performConfigurationChanged(r.activity, r.newConfig); 2458 r.newConfig = null; 2459 } 2460 } else { 2461 if (r.activity.mVisibleFromServer) { 2462 r.activity.mVisibleFromServer = false; 2463 mNumVisibleActivities--; 2464 v.setVisibility(View.INVISIBLE); 2465 } 2466 } 2467 } 2468 } 2469 handleStopActivity(IBinder token, boolean show, int configChanges)2470 private final void handleStopActivity(IBinder token, boolean show, int configChanges) { 2471 ActivityClientRecord r = mActivities.get(token); 2472 r.activity.mConfigChangeFlags |= configChanges; 2473 2474 StopInfo info = new StopInfo(); 2475 performStopActivityInner(r, info, show); 2476 2477 if (localLOGV) Slog.v( 2478 TAG, "Finishing stop of " + r + ": show=" + show 2479 + " win=" + r.window); 2480 2481 updateVisibility(r, show); 2482 2483 // Tell activity manager we have been stopped. 2484 try { 2485 ActivityManagerNative.getDefault().activityStopped( 2486 r.token, info.thumbnail, info.description); 2487 } catch (RemoteException ex) { 2488 } 2489 } 2490 performRestartActivity(IBinder token)2491 final void performRestartActivity(IBinder token) { 2492 ActivityClientRecord r = mActivities.get(token); 2493 if (r.stopped) { 2494 r.activity.performRestart(); 2495 r.stopped = false; 2496 } 2497 } 2498 handleWindowVisibility(IBinder token, boolean show)2499 private final void handleWindowVisibility(IBinder token, boolean show) { 2500 ActivityClientRecord r = mActivities.get(token); 2501 if (!show && !r.stopped) { 2502 performStopActivityInner(r, null, show); 2503 } else if (show && r.stopped) { 2504 // If we are getting ready to gc after going to the background, well 2505 // we are back active so skip it. 2506 unscheduleGcIdler(); 2507 2508 r.activity.performRestart(); 2509 r.stopped = false; 2510 } 2511 if (r.activity.mDecor != null) { 2512 if (Config.LOGV) Slog.v( 2513 TAG, "Handle window " + r + " visibility: " + show); 2514 updateVisibility(r, show); 2515 } 2516 } 2517 deliverResults(ActivityClientRecord r, List<ResultInfo> results)2518 private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) { 2519 final int N = results.size(); 2520 for (int i=0; i<N; i++) { 2521 ResultInfo ri = results.get(i); 2522 try { 2523 if (ri.mData != null) { 2524 ri.mData.setExtrasClassLoader(r.activity.getClassLoader()); 2525 } 2526 if (DEBUG_RESULTS) Slog.v(TAG, 2527 "Delivering result to activity " + r + " : " + ri); 2528 r.activity.dispatchActivityResult(ri.mResultWho, 2529 ri.mRequestCode, ri.mResultCode, ri.mData); 2530 } catch (Exception e) { 2531 if (!mInstrumentation.onException(r.activity, e)) { 2532 throw new RuntimeException( 2533 "Failure delivering result " + ri + " to activity " 2534 + r.intent.getComponent().toShortString() 2535 + ": " + e.toString(), e); 2536 } 2537 } 2538 } 2539 } 2540 handleSendResult(ResultData res)2541 private final void handleSendResult(ResultData res) { 2542 ActivityClientRecord r = mActivities.get(res.token); 2543 if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r); 2544 if (r != null) { 2545 final boolean resumed = !r.paused; 2546 if (!r.activity.mFinished && r.activity.mDecor != null 2547 && r.hideForNow && resumed) { 2548 // We had hidden the activity because it started another 2549 // one... we have gotten a result back and we are not 2550 // paused, so make sure our window is visible. 2551 updateVisibility(r, true); 2552 } 2553 if (resumed) { 2554 try { 2555 // Now we are idle. 2556 r.activity.mCalled = false; 2557 mInstrumentation.callActivityOnPause(r.activity); 2558 if (!r.activity.mCalled) { 2559 throw new SuperNotCalledException( 2560 "Activity " + r.intent.getComponent().toShortString() 2561 + " did not call through to super.onPause()"); 2562 } 2563 } catch (SuperNotCalledException e) { 2564 throw e; 2565 } catch (Exception e) { 2566 if (!mInstrumentation.onException(r.activity, e)) { 2567 throw new RuntimeException( 2568 "Unable to pause activity " 2569 + r.intent.getComponent().toShortString() 2570 + ": " + e.toString(), e); 2571 } 2572 } 2573 } 2574 deliverResults(r, res.results); 2575 if (resumed) { 2576 mInstrumentation.callActivityOnResume(r.activity); 2577 } 2578 } 2579 } 2580 performDestroyActivity(IBinder token, boolean finishing)2581 public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) { 2582 return performDestroyActivity(token, finishing, 0, false); 2583 } 2584 performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance)2585 private final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, 2586 int configChanges, boolean getNonConfigInstance) { 2587 ActivityClientRecord r = mActivities.get(token); 2588 if (localLOGV) Slog.v(TAG, "Performing finish of " + r); 2589 if (r != null) { 2590 r.activity.mConfigChangeFlags |= configChanges; 2591 if (finishing) { 2592 r.activity.mFinished = true; 2593 } 2594 if (!r.paused) { 2595 try { 2596 r.activity.mCalled = false; 2597 mInstrumentation.callActivityOnPause(r.activity); 2598 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, 2599 r.activity.getComponentName().getClassName()); 2600 if (!r.activity.mCalled) { 2601 throw new SuperNotCalledException( 2602 "Activity " + safeToComponentShortString(r.intent) 2603 + " did not call through to super.onPause()"); 2604 } 2605 } catch (SuperNotCalledException e) { 2606 throw e; 2607 } catch (Exception e) { 2608 if (!mInstrumentation.onException(r.activity, e)) { 2609 throw new RuntimeException( 2610 "Unable to pause activity " 2611 + safeToComponentShortString(r.intent) 2612 + ": " + e.toString(), e); 2613 } 2614 } 2615 r.paused = true; 2616 } 2617 if (!r.stopped) { 2618 try { 2619 r.activity.performStop(); 2620 } catch (SuperNotCalledException e) { 2621 throw e; 2622 } catch (Exception e) { 2623 if (!mInstrumentation.onException(r.activity, e)) { 2624 throw new RuntimeException( 2625 "Unable to stop activity " 2626 + safeToComponentShortString(r.intent) 2627 + ": " + e.toString(), e); 2628 } 2629 } 2630 r.stopped = true; 2631 } 2632 if (getNonConfigInstance) { 2633 try { 2634 r.lastNonConfigurationInstance 2635 = r.activity.onRetainNonConfigurationInstance(); 2636 } catch (Exception e) { 2637 if (!mInstrumentation.onException(r.activity, e)) { 2638 throw new RuntimeException( 2639 "Unable to retain activity " 2640 + r.intent.getComponent().toShortString() 2641 + ": " + e.toString(), e); 2642 } 2643 } 2644 try { 2645 r.lastNonConfigurationChildInstances 2646 = r.activity.onRetainNonConfigurationChildInstances(); 2647 } catch (Exception e) { 2648 if (!mInstrumentation.onException(r.activity, e)) { 2649 throw new RuntimeException( 2650 "Unable to retain child activities " 2651 + safeToComponentShortString(r.intent) 2652 + ": " + e.toString(), e); 2653 } 2654 } 2655 2656 } 2657 try { 2658 r.activity.mCalled = false; 2659 r.activity.onDestroy(); 2660 if (!r.activity.mCalled) { 2661 throw new SuperNotCalledException( 2662 "Activity " + safeToComponentShortString(r.intent) + 2663 " did not call through to super.onDestroy()"); 2664 } 2665 if (r.window != null) { 2666 r.window.closeAllPanels(); 2667 } 2668 } catch (SuperNotCalledException e) { 2669 throw e; 2670 } catch (Exception e) { 2671 if (!mInstrumentation.onException(r.activity, e)) { 2672 throw new RuntimeException( 2673 "Unable to destroy activity " + safeToComponentShortString(r.intent) 2674 + ": " + e.toString(), e); 2675 } 2676 } 2677 } 2678 mActivities.remove(token); 2679 2680 return r; 2681 } 2682 safeToComponentShortString(Intent intent)2683 private static String safeToComponentShortString(Intent intent) { 2684 ComponentName component = intent.getComponent(); 2685 return component == null ? "[Unknown]" : component.toShortString(); 2686 } 2687 handleDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance)2688 private final void handleDestroyActivity(IBinder token, boolean finishing, 2689 int configChanges, boolean getNonConfigInstance) { 2690 ActivityClientRecord r = performDestroyActivity(token, finishing, 2691 configChanges, getNonConfigInstance); 2692 if (r != null) { 2693 WindowManager wm = r.activity.getWindowManager(); 2694 View v = r.activity.mDecor; 2695 if (v != null) { 2696 if (r.activity.mVisibleFromServer) { 2697 mNumVisibleActivities--; 2698 } 2699 IBinder wtoken = v.getWindowToken(); 2700 if (r.activity.mWindowAdded) { 2701 wm.removeViewImmediate(v); 2702 } 2703 if (wtoken != null) { 2704 WindowManagerImpl.getDefault().closeAll(wtoken, 2705 r.activity.getClass().getName(), "Activity"); 2706 } 2707 r.activity.mDecor = null; 2708 } 2709 WindowManagerImpl.getDefault().closeAll(token, 2710 r.activity.getClass().getName(), "Activity"); 2711 2712 // Mocked out contexts won't be participating in the normal 2713 // process lifecycle, but if we're running with a proper 2714 // ApplicationContext we need to have it tear down things 2715 // cleanly. 2716 Context c = r.activity.getBaseContext(); 2717 if (c instanceof ContextImpl) { 2718 ((ContextImpl) c).scheduleFinalCleanup( 2719 r.activity.getClass().getName(), "Activity"); 2720 } 2721 } 2722 if (finishing) { 2723 try { 2724 ActivityManagerNative.getDefault().activityDestroyed(token); 2725 } catch (RemoteException ex) { 2726 // If the system process has died, it's game over for everyone. 2727 } 2728 } 2729 } 2730 handleRelaunchActivity(ActivityClientRecord tmp, int configChanges)2731 private final void handleRelaunchActivity(ActivityClientRecord tmp, int configChanges) { 2732 // If we are getting ready to gc after going to the background, well 2733 // we are back active so skip it. 2734 unscheduleGcIdler(); 2735 2736 Configuration changedConfig = null; 2737 2738 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity " 2739 + tmp.token + " with configChanges=0x" 2740 + Integer.toHexString(configChanges)); 2741 2742 // First: make sure we have the most recent configuration and most 2743 // recent version of the activity, or skip it if some previous call 2744 // had taken a more recent version. 2745 synchronized (mPackages) { 2746 int N = mRelaunchingActivities.size(); 2747 IBinder token = tmp.token; 2748 tmp = null; 2749 for (int i=0; i<N; i++) { 2750 ActivityClientRecord r = mRelaunchingActivities.get(i); 2751 if (r.token == token) { 2752 tmp = r; 2753 mRelaunchingActivities.remove(i); 2754 i--; 2755 N--; 2756 } 2757 } 2758 2759 if (tmp == null) { 2760 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!"); 2761 return; 2762 } 2763 2764 if (mPendingConfiguration != null) { 2765 changedConfig = mPendingConfiguration; 2766 mPendingConfiguration = null; 2767 } 2768 } 2769 2770 if (tmp.createdConfig != null) { 2771 // If the activity manager is passing us its current config, 2772 // assume that is really what we want regardless of what we 2773 // may have pending. 2774 if (mConfiguration == null 2775 || (tmp.createdConfig.isOtherSeqNewer(mConfiguration) 2776 && mConfiguration.diff(tmp.createdConfig) != 0)) { 2777 if (changedConfig == null 2778 || tmp.createdConfig.isOtherSeqNewer(changedConfig)) { 2779 changedConfig = tmp.createdConfig; 2780 } 2781 } 2782 } 2783 2784 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity " 2785 + tmp.token + ": changedConfig=" + changedConfig); 2786 2787 // If there was a pending configuration change, execute it first. 2788 if (changedConfig != null) { 2789 handleConfigurationChanged(changedConfig); 2790 } 2791 2792 ActivityClientRecord r = mActivities.get(tmp.token); 2793 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r); 2794 if (r == null) { 2795 return; 2796 } 2797 2798 r.activity.mConfigChangeFlags |= configChanges; 2799 Intent currentIntent = r.activity.mIntent; 2800 2801 Bundle savedState = null; 2802 if (!r.paused) { 2803 savedState = performPauseActivity(r.token, false, true); 2804 } 2805 2806 handleDestroyActivity(r.token, false, configChanges, true); 2807 2808 r.activity = null; 2809 r.window = null; 2810 r.hideForNow = false; 2811 r.nextIdle = null; 2812 // Merge any pending results and pending intents; don't just replace them 2813 if (tmp.pendingResults != null) { 2814 if (r.pendingResults == null) { 2815 r.pendingResults = tmp.pendingResults; 2816 } else { 2817 r.pendingResults.addAll(tmp.pendingResults); 2818 } 2819 } 2820 if (tmp.pendingIntents != null) { 2821 if (r.pendingIntents == null) { 2822 r.pendingIntents = tmp.pendingIntents; 2823 } else { 2824 r.pendingIntents.addAll(tmp.pendingIntents); 2825 } 2826 } 2827 r.startsNotResumed = tmp.startsNotResumed; 2828 if (savedState != null) { 2829 r.state = savedState; 2830 } 2831 2832 handleLaunchActivity(r, currentIntent); 2833 } 2834 handleRequestThumbnail(IBinder token)2835 private final void handleRequestThumbnail(IBinder token) { 2836 ActivityClientRecord r = mActivities.get(token); 2837 Bitmap thumbnail = createThumbnailBitmap(r); 2838 CharSequence description = null; 2839 try { 2840 description = r.activity.onCreateDescription(); 2841 } catch (Exception e) { 2842 if (!mInstrumentation.onException(r.activity, e)) { 2843 throw new RuntimeException( 2844 "Unable to create description of activity " 2845 + r.intent.getComponent().toShortString() 2846 + ": " + e.toString(), e); 2847 } 2848 } 2849 //System.out.println("Reporting top thumbnail " + thumbnail); 2850 try { 2851 ActivityManagerNative.getDefault().reportThumbnail( 2852 token, thumbnail, description); 2853 } catch (RemoteException ex) { 2854 } 2855 } 2856 collectComponentCallbacksLocked( boolean allActivities, Configuration newConfig)2857 ArrayList<ComponentCallbacks> collectComponentCallbacksLocked( 2858 boolean allActivities, Configuration newConfig) { 2859 ArrayList<ComponentCallbacks> callbacks 2860 = new ArrayList<ComponentCallbacks>(); 2861 2862 if (mActivities.size() > 0) { 2863 Iterator<ActivityClientRecord> it = mActivities.values().iterator(); 2864 while (it.hasNext()) { 2865 ActivityClientRecord ar = it.next(); 2866 Activity a = ar.activity; 2867 if (a != null) { 2868 if (!ar.activity.mFinished && (allActivities || 2869 (a != null && !ar.paused))) { 2870 // If the activity is currently resumed, its configuration 2871 // needs to change right now. 2872 callbacks.add(a); 2873 } else if (newConfig != null) { 2874 // Otherwise, we will tell it about the change 2875 // the next time it is resumed or shown. Note that 2876 // the activity manager may, before then, decide the 2877 // activity needs to be destroyed to handle its new 2878 // configuration. 2879 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity " 2880 + ar.activityInfo.name + " newConfig=" + newConfig); 2881 ar.newConfig = newConfig; 2882 } 2883 } 2884 } 2885 } 2886 if (mServices.size() > 0) { 2887 Iterator<Service> it = mServices.values().iterator(); 2888 while (it.hasNext()) { 2889 callbacks.add(it.next()); 2890 } 2891 } 2892 synchronized (mProviderMap) { 2893 if (mLocalProviders.size() > 0) { 2894 Iterator<ProviderClientRecord> it = mLocalProviders.values().iterator(); 2895 while (it.hasNext()) { 2896 callbacks.add(it.next().mLocalProvider); 2897 } 2898 } 2899 } 2900 final int N = mAllApplications.size(); 2901 for (int i=0; i<N; i++) { 2902 callbacks.add(mAllApplications.get(i)); 2903 } 2904 2905 return callbacks; 2906 } 2907 performConfigurationChanged( ComponentCallbacks cb, Configuration config)2908 private final void performConfigurationChanged( 2909 ComponentCallbacks cb, Configuration config) { 2910 // Only for Activity objects, check that they actually call up to their 2911 // superclass implementation. ComponentCallbacks is an interface, so 2912 // we check the runtime type and act accordingly. 2913 Activity activity = (cb instanceof Activity) ? (Activity) cb : null; 2914 if (activity != null) { 2915 activity.mCalled = false; 2916 } 2917 2918 boolean shouldChangeConfig = false; 2919 if ((activity == null) || (activity.mCurrentConfig == null)) { 2920 shouldChangeConfig = true; 2921 } else { 2922 2923 // If the new config is the same as the config this Activity 2924 // is already running with then don't bother calling 2925 // onConfigurationChanged 2926 int diff = activity.mCurrentConfig.diff(config); 2927 if (diff != 0) { 2928 2929 // If this activity doesn't handle any of the config changes 2930 // then don't bother calling onConfigurationChanged as we're 2931 // going to destroy it. 2932 if ((~activity.mActivityInfo.configChanges & diff) == 0) { 2933 shouldChangeConfig = true; 2934 } 2935 } 2936 } 2937 2938 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb 2939 + ": shouldChangeConfig=" + shouldChangeConfig); 2940 if (shouldChangeConfig) { 2941 cb.onConfigurationChanged(config); 2942 2943 if (activity != null) { 2944 if (!activity.mCalled) { 2945 throw new SuperNotCalledException( 2946 "Activity " + activity.getLocalClassName() + 2947 " did not call through to super.onConfigurationChanged()"); 2948 } 2949 activity.mConfigChangeFlags = 0; 2950 activity.mCurrentConfig = new Configuration(config); 2951 } 2952 } 2953 } 2954 applyConfigurationToResourcesLocked(Configuration config)2955 final boolean applyConfigurationToResourcesLocked(Configuration config) { 2956 if (mResConfiguration == null) { 2957 mResConfiguration = new Configuration(); 2958 } 2959 if (!mResConfiguration.isOtherSeqNewer(config)) { 2960 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq=" 2961 + mResConfiguration.seq + ", newSeq=" + config.seq); 2962 return false; 2963 } 2964 int changes = mResConfiguration.updateFrom(config); 2965 DisplayMetrics dm = getDisplayMetricsLocked(true); 2966 2967 // set it for java, this also affects newly created Resources 2968 if (config.locale != null) { 2969 Locale.setDefault(config.locale); 2970 } 2971 2972 Resources.updateSystemConfiguration(config, dm); 2973 2974 ContextImpl.ApplicationPackageManager.configurationChanged(); 2975 //Slog.i(TAG, "Configuration changed in " + currentPackageName()); 2976 2977 Iterator<WeakReference<Resources>> it = 2978 mActiveResources.values().iterator(); 2979 //Iterator<Map.Entry<String, WeakReference<Resources>>> it = 2980 // mActiveResources.entrySet().iterator(); 2981 while (it.hasNext()) { 2982 WeakReference<Resources> v = it.next(); 2983 Resources r = v.get(); 2984 if (r != null) { 2985 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources " 2986 + r + " config to: " + config); 2987 r.updateConfiguration(config, dm); 2988 //Slog.i(TAG, "Updated app resources " + v.getKey() 2989 // + " " + r + ": " + r.getConfiguration()); 2990 } else { 2991 //Slog.i(TAG, "Removing old resources " + v.getKey()); 2992 it.remove(); 2993 } 2994 } 2995 2996 return changes != 0; 2997 } 2998 handleConfigurationChanged(Configuration config)2999 final void handleConfigurationChanged(Configuration config) { 3000 3001 ArrayList<ComponentCallbacks> callbacks = null; 3002 3003 synchronized (mPackages) { 3004 if (mPendingConfiguration != null) { 3005 if (!mPendingConfiguration.isOtherSeqNewer(config)) { 3006 config = mPendingConfiguration; 3007 } 3008 mPendingConfiguration = null; 3009 } 3010 3011 if (config == null) { 3012 return; 3013 } 3014 3015 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: " 3016 + config); 3017 3018 applyConfigurationToResourcesLocked(config); 3019 3020 if (mConfiguration == null) { 3021 mConfiguration = new Configuration(); 3022 } 3023 if (!mConfiguration.isOtherSeqNewer(config)) { 3024 return; 3025 } 3026 mConfiguration.updateFrom(config); 3027 3028 callbacks = collectComponentCallbacksLocked(false, config); 3029 } 3030 3031 if (callbacks != null) { 3032 final int N = callbacks.size(); 3033 for (int i=0; i<N; i++) { 3034 performConfigurationChanged(callbacks.get(i), config); 3035 } 3036 } 3037 } 3038 handleActivityConfigurationChanged(IBinder token)3039 final void handleActivityConfigurationChanged(IBinder token) { 3040 ActivityClientRecord r = mActivities.get(token); 3041 if (r == null || r.activity == null) { 3042 return; 3043 } 3044 3045 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: " 3046 + r.activityInfo.name); 3047 3048 performConfigurationChanged(r.activity, mConfiguration); 3049 } 3050 handleProfilerControl(boolean start, ProfilerControlData pcd)3051 final void handleProfilerControl(boolean start, ProfilerControlData pcd) { 3052 if (start) { 3053 try { 3054 Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(), 3055 8 * 1024 * 1024, 0); 3056 } catch (RuntimeException e) { 3057 Slog.w(TAG, "Profiling failed on path " + pcd.path 3058 + " -- can the process access this path?"); 3059 } finally { 3060 try { 3061 pcd.fd.close(); 3062 } catch (IOException e) { 3063 Slog.w(TAG, "Failure closing profile fd", e); 3064 } 3065 } 3066 } else { 3067 Debug.stopMethodTracing(); 3068 } 3069 } 3070 handleDispatchPackageBroadcast(int cmd, String[] packages)3071 final void handleDispatchPackageBroadcast(int cmd, String[] packages) { 3072 boolean hasPkgInfo = false; 3073 if (packages != null) { 3074 for (int i=packages.length-1; i>=0; i--) { 3075 //Slog.i(TAG, "Cleaning old package: " + packages[i]); 3076 if (!hasPkgInfo) { 3077 WeakReference<LoadedApk> ref; 3078 ref = mPackages.get(packages[i]); 3079 if (ref != null && ref.get() != null) { 3080 hasPkgInfo = true; 3081 } else { 3082 ref = mResourcePackages.get(packages[i]); 3083 if (ref != null && ref.get() != null) { 3084 hasPkgInfo = true; 3085 } 3086 } 3087 } 3088 mPackages.remove(packages[i]); 3089 mResourcePackages.remove(packages[i]); 3090 } 3091 } 3092 ContextImpl.ApplicationPackageManager.handlePackageBroadcast(cmd, packages, 3093 hasPkgInfo); 3094 } 3095 handleLowMemory()3096 final void handleLowMemory() { 3097 ArrayList<ComponentCallbacks> callbacks 3098 = new ArrayList<ComponentCallbacks>(); 3099 3100 synchronized (mPackages) { 3101 callbacks = collectComponentCallbacksLocked(true, null); 3102 } 3103 3104 final int N = callbacks.size(); 3105 for (int i=0; i<N; i++) { 3106 callbacks.get(i).onLowMemory(); 3107 } 3108 3109 // Ask SQLite to free up as much memory as it can, mostly from its page caches. 3110 if (Process.myUid() != Process.SYSTEM_UID) { 3111 int sqliteReleased = SQLiteDatabase.releaseMemory(); 3112 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); 3113 } 3114 3115 // Ask graphics to free up as much as possible (font/image caches) 3116 Canvas.freeCaches(); 3117 3118 BinderInternal.forceGc("mem"); 3119 } 3120 handleBindApplication(AppBindData data)3121 private final void handleBindApplication(AppBindData data) { 3122 mBoundApplication = data; 3123 mConfiguration = new Configuration(data.config); 3124 3125 // send up app name; do this *before* waiting for debugger 3126 Process.setArgV0(data.processName); 3127 android.ddm.DdmHandleAppName.setAppName(data.processName); 3128 3129 /* 3130 * Before spawning a new process, reset the time zone to be the system time zone. 3131 * This needs to be done because the system time zone could have changed after the 3132 * the spawning of this process. Without doing this this process would have the incorrect 3133 * system time zone. 3134 */ 3135 TimeZone.setDefault(null); 3136 3137 /* 3138 * Initialize the default locale in this process for the reasons we set the time zone. 3139 */ 3140 Locale.setDefault(data.config.locale); 3141 3142 /* 3143 * Update the system configuration since its preloaded and might not 3144 * reflect configuration changes. The configuration object passed 3145 * in AppBindData can be safely assumed to be up to date 3146 */ 3147 Resources.getSystem().updateConfiguration(mConfiguration, null); 3148 3149 data.info = getPackageInfoNoCheck(data.appInfo); 3150 3151 /** 3152 * For system applications on userdebug/eng builds, log stack 3153 * traces of disk and network access to dropbox for analysis. 3154 */ 3155 if ((data.appInfo.flags & 3156 (ApplicationInfo.FLAG_SYSTEM | 3157 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) { 3158 StrictMode.conditionallyEnableDebugLogging(); 3159 } 3160 3161 /** 3162 * Switch this process to density compatibility mode if needed. 3163 */ 3164 if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) 3165 == 0) { 3166 Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); 3167 } 3168 3169 if (data.debugMode != IApplicationThread.DEBUG_OFF) { 3170 // XXX should have option to change the port. 3171 Debug.changeDebugPort(8100); 3172 if (data.debugMode == IApplicationThread.DEBUG_WAIT) { 3173 Slog.w(TAG, "Application " + data.info.getPackageName() 3174 + " is waiting for the debugger on port 8100..."); 3175 3176 IActivityManager mgr = ActivityManagerNative.getDefault(); 3177 try { 3178 mgr.showWaitingForDebugger(mAppThread, true); 3179 } catch (RemoteException ex) { 3180 } 3181 3182 Debug.waitForDebugger(); 3183 3184 try { 3185 mgr.showWaitingForDebugger(mAppThread, false); 3186 } catch (RemoteException ex) { 3187 } 3188 3189 } else { 3190 Slog.w(TAG, "Application " + data.info.getPackageName() 3191 + " can be debugged on port 8100..."); 3192 } 3193 } 3194 3195 if (data.instrumentationName != null) { 3196 ContextImpl appContext = new ContextImpl(); 3197 appContext.init(data.info, null, this); 3198 InstrumentationInfo ii = null; 3199 try { 3200 ii = appContext.getPackageManager(). 3201 getInstrumentationInfo(data.instrumentationName, 0); 3202 } catch (PackageManager.NameNotFoundException e) { 3203 } 3204 if (ii == null) { 3205 throw new RuntimeException( 3206 "Unable to find instrumentation info for: " 3207 + data.instrumentationName); 3208 } 3209 3210 mInstrumentationAppDir = ii.sourceDir; 3211 mInstrumentationAppPackage = ii.packageName; 3212 mInstrumentedAppDir = data.info.getAppDir(); 3213 3214 ApplicationInfo instrApp = new ApplicationInfo(); 3215 instrApp.packageName = ii.packageName; 3216 instrApp.sourceDir = ii.sourceDir; 3217 instrApp.publicSourceDir = ii.publicSourceDir; 3218 instrApp.dataDir = ii.dataDir; 3219 instrApp.nativeLibraryDir = ii.nativeLibraryDir; 3220 LoadedApk pi = getPackageInfo(instrApp, 3221 appContext.getClassLoader(), false, true); 3222 ContextImpl instrContext = new ContextImpl(); 3223 instrContext.init(pi, null, this); 3224 3225 try { 3226 java.lang.ClassLoader cl = instrContext.getClassLoader(); 3227 mInstrumentation = (Instrumentation) 3228 cl.loadClass(data.instrumentationName.getClassName()).newInstance(); 3229 } catch (Exception e) { 3230 throw new RuntimeException( 3231 "Unable to instantiate instrumentation " 3232 + data.instrumentationName + ": " + e.toString(), e); 3233 } 3234 3235 mInstrumentation.init(this, instrContext, appContext, 3236 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher); 3237 3238 if (data.profileFile != null && !ii.handleProfiling) { 3239 data.handlingProfiling = true; 3240 File file = new File(data.profileFile); 3241 file.getParentFile().mkdirs(); 3242 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 3243 } 3244 3245 try { 3246 mInstrumentation.onCreate(data.instrumentationArgs); 3247 } 3248 catch (Exception e) { 3249 throw new RuntimeException( 3250 "Exception thrown in onCreate() of " 3251 + data.instrumentationName + ": " + e.toString(), e); 3252 } 3253 3254 } else { 3255 mInstrumentation = new Instrumentation(); 3256 } 3257 3258 // If the app is being launched for full backup or restore, bring it up in 3259 // a restricted environment with the base application class. 3260 Application app = data.info.makeApplication(data.restrictedBackupMode, null); 3261 mInitialApplication = app; 3262 3263 List<ProviderInfo> providers = data.providers; 3264 if (providers != null) { 3265 installContentProviders(app, providers); 3266 // For process that contain content providers, we want to 3267 // ensure that the JIT is enabled "at some point". 3268 mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); 3269 } 3270 3271 try { 3272 mInstrumentation.callApplicationOnCreate(app); 3273 } catch (Exception e) { 3274 if (!mInstrumentation.onException(app, e)) { 3275 throw new RuntimeException( 3276 "Unable to create application " + app.getClass().getName() 3277 + ": " + e.toString(), e); 3278 } 3279 } 3280 } 3281 finishInstrumentation(int resultCode, Bundle results)3282 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) { 3283 IActivityManager am = ActivityManagerNative.getDefault(); 3284 if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) { 3285 Debug.stopMethodTracing(); 3286 } 3287 //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault() 3288 // + ", app thr: " + mAppThread); 3289 try { 3290 am.finishInstrumentation(mAppThread, resultCode, results); 3291 } catch (RemoteException ex) { 3292 } 3293 } 3294 installContentProviders( Context context, List<ProviderInfo> providers)3295 private final void installContentProviders( 3296 Context context, List<ProviderInfo> providers) { 3297 final ArrayList<IActivityManager.ContentProviderHolder> results = 3298 new ArrayList<IActivityManager.ContentProviderHolder>(); 3299 3300 Iterator<ProviderInfo> i = providers.iterator(); 3301 while (i.hasNext()) { 3302 ProviderInfo cpi = i.next(); 3303 StringBuilder buf = new StringBuilder(128); 3304 buf.append("Pub "); 3305 buf.append(cpi.authority); 3306 buf.append(": "); 3307 buf.append(cpi.name); 3308 Log.i(TAG, buf.toString()); 3309 IContentProvider cp = installProvider(context, null, cpi, false); 3310 if (cp != null) { 3311 IActivityManager.ContentProviderHolder cph = 3312 new IActivityManager.ContentProviderHolder(cpi); 3313 cph.provider = cp; 3314 results.add(cph); 3315 // Don't ever unload this provider from the process. 3316 synchronized(mProviderMap) { 3317 mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000)); 3318 } 3319 } 3320 } 3321 3322 try { 3323 ActivityManagerNative.getDefault().publishContentProviders( 3324 getApplicationThread(), results); 3325 } catch (RemoteException ex) { 3326 } 3327 } 3328 getExistingProvider(Context context, String name)3329 private final IContentProvider getExistingProvider(Context context, String name) { 3330 synchronized(mProviderMap) { 3331 final ProviderClientRecord pr = mProviderMap.get(name); 3332 if (pr != null) { 3333 return pr.mProvider; 3334 } 3335 return null; 3336 } 3337 } 3338 getProvider(Context context, String name)3339 private final IContentProvider getProvider(Context context, String name) { 3340 IContentProvider existing = getExistingProvider(context, name); 3341 if (existing != null) { 3342 return existing; 3343 } 3344 3345 IActivityManager.ContentProviderHolder holder = null; 3346 try { 3347 holder = ActivityManagerNative.getDefault().getContentProvider( 3348 getApplicationThread(), name); 3349 } catch (RemoteException ex) { 3350 } 3351 if (holder == null) { 3352 Slog.e(TAG, "Failed to find provider info for " + name); 3353 return null; 3354 } 3355 3356 IContentProvider prov = installProvider(context, holder.provider, 3357 holder.info, true); 3358 //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded); 3359 if (holder.noReleaseNeeded || holder.provider == null) { 3360 // We are not going to release the provider if it is an external 3361 // provider that doesn't care about being released, or if it is 3362 // a local provider running in this process. 3363 //Slog.i(TAG, "*** NO RELEASE NEEDED"); 3364 synchronized(mProviderMap) { 3365 mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000)); 3366 } 3367 } 3368 return prov; 3369 } 3370 acquireProvider(Context c, String name)3371 public final IContentProvider acquireProvider(Context c, String name) { 3372 IContentProvider provider = getProvider(c, name); 3373 if(provider == null) 3374 return null; 3375 IBinder jBinder = provider.asBinder(); 3376 synchronized(mProviderMap) { 3377 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 3378 if(prc == null) { 3379 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); 3380 } else { 3381 prc.count++; 3382 } //end else 3383 } //end synchronized 3384 return provider; 3385 } 3386 acquireExistingProvider(Context c, String name)3387 public final IContentProvider acquireExistingProvider(Context c, String name) { 3388 IContentProvider provider = getExistingProvider(c, name); 3389 if(provider == null) 3390 return null; 3391 IBinder jBinder = provider.asBinder(); 3392 synchronized(mProviderMap) { 3393 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 3394 if(prc == null) { 3395 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); 3396 } else { 3397 prc.count++; 3398 } //end else 3399 } //end synchronized 3400 return provider; 3401 } 3402 releaseProvider(IContentProvider provider)3403 public final boolean releaseProvider(IContentProvider provider) { 3404 if(provider == null) { 3405 return false; 3406 } 3407 IBinder jBinder = provider.asBinder(); 3408 synchronized(mProviderMap) { 3409 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 3410 if(prc == null) { 3411 if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldn't be here"); 3412 return false; 3413 } else { 3414 prc.count--; 3415 if(prc.count == 0) { 3416 // Schedule the actual remove asynchronously, since we 3417 // don't know the context this will be called in. 3418 // TODO: it would be nice to post a delayed message, so 3419 // if we come back and need the same provider quickly 3420 // we will still have it available. 3421 Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider); 3422 mH.sendMessage(msg); 3423 } //end if 3424 } //end else 3425 } //end synchronized 3426 return true; 3427 } 3428 completeRemoveProvider(IContentProvider provider)3429 final void completeRemoveProvider(IContentProvider provider) { 3430 IBinder jBinder = provider.asBinder(); 3431 String name = null; 3432 synchronized(mProviderMap) { 3433 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 3434 if(prc != null && prc.count == 0) { 3435 mProviderRefCountMap.remove(jBinder); 3436 //invoke removeProvider to dereference provider 3437 name = removeProviderLocked(provider); 3438 } 3439 } 3440 3441 if (name != null) { 3442 try { 3443 if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " + 3444 "ActivityManagerNative.removeContentProvider(" + name); 3445 ActivityManagerNative.getDefault().removeContentProvider( 3446 getApplicationThread(), name); 3447 } catch (RemoteException e) { 3448 //do nothing content provider object is dead any way 3449 } //end catch 3450 } 3451 } 3452 removeProviderLocked(IContentProvider provider)3453 public final String removeProviderLocked(IContentProvider provider) { 3454 if (provider == null) { 3455 return null; 3456 } 3457 IBinder providerBinder = provider.asBinder(); 3458 3459 String name = null; 3460 3461 // remove the provider from mProviderMap 3462 Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator(); 3463 while (iter.hasNext()) { 3464 ProviderClientRecord pr = iter.next(); 3465 IBinder myBinder = pr.mProvider.asBinder(); 3466 if (myBinder == providerBinder) { 3467 //find if its published by this process itself 3468 if(pr.mLocalProvider != null) { 3469 if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning"); 3470 return name; 3471 } 3472 if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " + 3473 "death recipient"); 3474 //content provider is in another process 3475 myBinder.unlinkToDeath(pr, 0); 3476 iter.remove(); 3477 //invoke remove only once for the very first name seen 3478 if(name == null) { 3479 name = pr.mName; 3480 } 3481 } //end if myBinder 3482 } //end while iter 3483 3484 return name; 3485 } 3486 removeDeadProvider(String name, IContentProvider provider)3487 final void removeDeadProvider(String name, IContentProvider provider) { 3488 synchronized(mProviderMap) { 3489 ProviderClientRecord pr = mProviderMap.get(name); 3490 if (pr.mProvider.asBinder() == provider.asBinder()) { 3491 Slog.i(TAG, "Removing dead content provider: " + name); 3492 ProviderClientRecord removed = mProviderMap.remove(name); 3493 if (removed != null) { 3494 removed.mProvider.asBinder().unlinkToDeath(removed, 0); 3495 } 3496 } 3497 } 3498 } 3499 removeDeadProviderLocked(String name, IContentProvider provider)3500 final void removeDeadProviderLocked(String name, IContentProvider provider) { 3501 ProviderClientRecord pr = mProviderMap.get(name); 3502 if (pr.mProvider.asBinder() == provider.asBinder()) { 3503 Slog.i(TAG, "Removing dead content provider: " + name); 3504 ProviderClientRecord removed = mProviderMap.remove(name); 3505 if (removed != null) { 3506 removed.mProvider.asBinder().unlinkToDeath(removed, 0); 3507 } 3508 } 3509 } 3510 installProvider(Context context, IContentProvider provider, ProviderInfo info, boolean noisy)3511 private final IContentProvider installProvider(Context context, 3512 IContentProvider provider, ProviderInfo info, boolean noisy) { 3513 ContentProvider localProvider = null; 3514 if (provider == null) { 3515 if (noisy) { 3516 Slog.d(TAG, "Loading provider " + info.authority + ": " 3517 + info.name); 3518 } 3519 Context c = null; 3520 ApplicationInfo ai = info.applicationInfo; 3521 if (context.getPackageName().equals(ai.packageName)) { 3522 c = context; 3523 } else if (mInitialApplication != null && 3524 mInitialApplication.getPackageName().equals(ai.packageName)) { 3525 c = mInitialApplication; 3526 } else { 3527 try { 3528 c = context.createPackageContext(ai.packageName, 3529 Context.CONTEXT_INCLUDE_CODE); 3530 } catch (PackageManager.NameNotFoundException e) { 3531 } 3532 } 3533 if (c == null) { 3534 Slog.w(TAG, "Unable to get context for package " + 3535 ai.packageName + 3536 " while loading content provider " + 3537 info.name); 3538 return null; 3539 } 3540 try { 3541 final java.lang.ClassLoader cl = c.getClassLoader(); 3542 localProvider = (ContentProvider)cl. 3543 loadClass(info.name).newInstance(); 3544 provider = localProvider.getIContentProvider(); 3545 if (provider == null) { 3546 Slog.e(TAG, "Failed to instantiate class " + 3547 info.name + " from sourceDir " + 3548 info.applicationInfo.sourceDir); 3549 return null; 3550 } 3551 if (Config.LOGV) Slog.v( 3552 TAG, "Instantiating local provider " + info.name); 3553 // XXX Need to create the correct context for this provider. 3554 localProvider.attachInfo(c, info); 3555 } catch (java.lang.Exception e) { 3556 if (!mInstrumentation.onException(null, e)) { 3557 throw new RuntimeException( 3558 "Unable to get provider " + info.name 3559 + ": " + e.toString(), e); 3560 } 3561 return null; 3562 } 3563 } else if (localLOGV) { 3564 Slog.v(TAG, "Installing external provider " + info.authority + ": " 3565 + info.name); 3566 } 3567 3568 synchronized (mProviderMap) { 3569 // Cache the pointer for the remote provider. 3570 String names[] = PATTERN_SEMICOLON.split(info.authority); 3571 for (int i=0; i<names.length; i++) { 3572 ProviderClientRecord pr = new ProviderClientRecord(names[i], provider, 3573 localProvider); 3574 try { 3575 provider.asBinder().linkToDeath(pr, 0); 3576 mProviderMap.put(names[i], pr); 3577 } catch (RemoteException e) { 3578 return null; 3579 } 3580 } 3581 if (localProvider != null) { 3582 mLocalProviders.put(provider.asBinder(), 3583 new ProviderClientRecord(null, provider, localProvider)); 3584 } 3585 } 3586 3587 return provider; 3588 } 3589 attach(boolean system)3590 private final void attach(boolean system) { 3591 sThreadLocal.set(this); 3592 mSystemThread = system; 3593 if (!system) { 3594 ViewRoot.addFirstDrawHandler(new Runnable() { 3595 public void run() { 3596 ensureJitEnabled(); 3597 } 3598 }); 3599 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>"); 3600 RuntimeInit.setApplicationObject(mAppThread.asBinder()); 3601 IActivityManager mgr = ActivityManagerNative.getDefault(); 3602 try { 3603 mgr.attachApplication(mAppThread); 3604 } catch (RemoteException ex) { 3605 } 3606 } else { 3607 // Don't set application object here -- if the system crashes, 3608 // we can't display an alert, we just want to die die die. 3609 android.ddm.DdmHandleAppName.setAppName("system_process"); 3610 try { 3611 mInstrumentation = new Instrumentation(); 3612 ContextImpl context = new ContextImpl(); 3613 context.init(getSystemContext().mPackageInfo, null, this); 3614 Application app = Instrumentation.newApplication(Application.class, context); 3615 mAllApplications.add(app); 3616 mInitialApplication = app; 3617 app.onCreate(); 3618 } catch (Exception e) { 3619 throw new RuntimeException( 3620 "Unable to instantiate Application():" + e.toString(), e); 3621 } 3622 } 3623 3624 ViewRoot.addConfigCallback(new ComponentCallbacks() { 3625 public void onConfigurationChanged(Configuration newConfig) { 3626 synchronized (mPackages) { 3627 // We need to apply this change to the resources 3628 // immediately, because upon returning the view 3629 // hierarchy will be informed about it. 3630 if (applyConfigurationToResourcesLocked(newConfig)) { 3631 // This actually changed the resources! Tell 3632 // everyone about it. 3633 if (mPendingConfiguration == null || 3634 mPendingConfiguration.isOtherSeqNewer(newConfig)) { 3635 mPendingConfiguration = newConfig; 3636 3637 queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig); 3638 } 3639 } 3640 } 3641 } 3642 public void onLowMemory() { 3643 } 3644 }); 3645 } 3646 detach()3647 private final void detach() 3648 { 3649 sThreadLocal.set(null); 3650 } 3651 systemMain()3652 public static final ActivityThread systemMain() { 3653 ActivityThread thread = new ActivityThread(); 3654 thread.attach(true); 3655 return thread; 3656 } 3657 installSystemProviders(List providers)3658 public final void installSystemProviders(List providers) { 3659 if (providers != null) { 3660 installContentProviders(mInitialApplication, 3661 (List<ProviderInfo>)providers); 3662 } 3663 } 3664 main(String[] args)3665 public static final void main(String[] args) { 3666 SamplingProfilerIntegration.start(); 3667 3668 Process.setArgV0("<pre-initialized>"); 3669 3670 Looper.prepareMainLooper(); 3671 if (sMainThreadHandler == null) { 3672 sMainThreadHandler = new Handler(); 3673 } 3674 3675 ActivityThread thread = new ActivityThread(); 3676 thread.attach(false); 3677 3678 if (false) { 3679 Looper.myLooper().setMessageLogging(new 3680 LogPrinter(Log.DEBUG, "ActivityThread")); 3681 } 3682 3683 Looper.loop(); 3684 3685 if (Process.supportsProcesses()) { 3686 throw new RuntimeException("Main thread loop unexpectedly exited"); 3687 } 3688 3689 thread.detach(); 3690 String name = (thread.mInitialApplication != null) 3691 ? thread.mInitialApplication.getPackageName() 3692 : "<unknown>"; 3693 Slog.i(TAG, "Main thread of " + name + " is now exiting"); 3694 } 3695 } 3696