ActivityThread.java revision 7c5016787ec862445b1d4301787f46d52acfa88d
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.app; 18 19import android.app.backup.BackupAgent; 20import android.content.BroadcastReceiver; 21import android.content.ComponentCallbacks2; 22import android.content.ComponentName; 23import android.content.ContentProvider; 24import android.content.Context; 25import android.content.IContentProvider; 26import android.content.Intent; 27import android.content.IIntentReceiver; 28import android.content.pm.ActivityInfo; 29import android.content.pm.ApplicationInfo; 30import android.content.pm.IPackageManager; 31import android.content.pm.InstrumentationInfo; 32import android.content.pm.PackageManager; 33import android.content.pm.PackageManager.NameNotFoundException; 34import android.content.pm.ProviderInfo; 35import android.content.pm.ServiceInfo; 36import android.content.res.AssetManager; 37import android.content.res.CompatibilityInfo; 38import android.content.res.Configuration; 39import android.content.res.Resources; 40import android.database.sqlite.SQLiteDatabase; 41import android.database.sqlite.SQLiteDebug; 42import android.database.sqlite.SQLiteDebug.DbStats; 43import android.graphics.Bitmap; 44import android.graphics.Canvas; 45import android.net.IConnectivityManager; 46import android.net.Proxy; 47import android.net.ProxyProperties; 48import android.opengl.GLUtils; 49import android.os.AsyncTask; 50import android.os.Binder; 51import android.os.Bundle; 52import android.os.Debug; 53import android.os.Handler; 54import android.os.IBinder; 55import android.os.Looper; 56import android.os.Message; 57import android.os.MessageQueue; 58import android.os.ParcelFileDescriptor; 59import android.os.Process; 60import android.os.RemoteException; 61import android.os.ServiceManager; 62import android.os.StrictMode; 63import android.os.SystemClock; 64import android.os.UserId; 65import android.util.AndroidRuntimeException; 66import android.util.DisplayMetrics; 67import android.util.EventLog; 68import android.util.Log; 69import android.util.LogPrinter; 70import android.util.PrintWriterPrinter; 71import android.util.Slog; 72import android.view.Display; 73import android.view.HardwareRenderer; 74import android.view.View; 75import android.view.ViewDebug; 76import android.view.ViewManager; 77import android.view.ViewRootImpl; 78import android.view.Window; 79import android.view.WindowManager; 80import android.view.WindowManagerImpl; 81import android.renderscript.RenderScript; 82 83import com.android.internal.os.BinderInternal; 84import com.android.internal.os.RuntimeInit; 85import com.android.internal.os.SamplingProfilerIntegration; 86 87import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl; 88 89import java.io.File; 90import java.io.FileDescriptor; 91import java.io.FileOutputStream; 92import java.io.IOException; 93import java.io.PrintWriter; 94import java.lang.ref.WeakReference; 95import java.net.InetAddress; 96import java.util.ArrayList; 97import java.util.HashMap; 98import java.util.Iterator; 99import java.util.List; 100import java.util.Locale; 101import java.util.Map; 102import java.util.TimeZone; 103import java.util.regex.Pattern; 104 105import dalvik.system.CloseGuard; 106 107final class SuperNotCalledException extends AndroidRuntimeException { 108 public SuperNotCalledException(String msg) { 109 super(msg); 110 } 111} 112 113final class RemoteServiceException extends AndroidRuntimeException { 114 public RemoteServiceException(String msg) { 115 super(msg); 116 } 117} 118 119/** 120 * This manages the execution of the main thread in an 121 * application process, scheduling and executing activities, 122 * broadcasts, and other operations on it as the activity 123 * manager requests. 124 * 125 * {@hide} 126 */ 127public final class ActivityThread { 128 /** @hide */ 129 public static final String TAG = "ActivityThread"; 130 private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565; 131 static final boolean localLOGV = false; 132 static final boolean DEBUG_MESSAGES = false; 133 /** @hide */ 134 public static final boolean DEBUG_BROADCAST = false; 135 private static final boolean DEBUG_RESULTS = false; 136 private static final boolean DEBUG_BACKUP = true; 137 private static final boolean DEBUG_CONFIGURATION = false; 138 private static final boolean DEBUG_SERVICE = false; 139 private static final long MIN_TIME_BETWEEN_GCS = 5*1000; 140 private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); 141 private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; 142 private static final int LOG_ON_PAUSE_CALLED = 30021; 143 private static final int LOG_ON_RESUME_CALLED = 30022; 144 145 static ContextImpl mSystemContext = null; 146 147 static IPackageManager sPackageManager; 148 149 final ApplicationThread mAppThread = new ApplicationThread(); 150 final Looper mLooper = Looper.myLooper(); 151 final H mH = new H(); 152 final HashMap<IBinder, ActivityClientRecord> mActivities 153 = new HashMap<IBinder, ActivityClientRecord>(); 154 // List of new activities (via ActivityRecord.nextIdle) that should 155 // be reported when next we idle. 156 ActivityClientRecord mNewActivities = null; 157 // Number of activities that are currently visible on-screen. 158 int mNumVisibleActivities = 0; 159 final HashMap<IBinder, Service> mServices 160 = new HashMap<IBinder, Service>(); 161 AppBindData mBoundApplication; 162 Profiler mProfiler; 163 Configuration mConfiguration; 164 Configuration mCompatConfiguration; 165 Configuration mResConfiguration; 166 CompatibilityInfo mResCompatibilityInfo; 167 Application mInitialApplication; 168 final ArrayList<Application> mAllApplications 169 = new ArrayList<Application>(); 170 // set of instantiated backup agents, keyed by package name 171 final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>(); 172 static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>(); 173 Instrumentation mInstrumentation; 174 String mInstrumentationAppDir = null; 175 String mInstrumentationAppPackage = null; 176 String mInstrumentedAppDir = null; 177 boolean mSystemThread = false; 178 boolean mJitEnabled = false; 179 180 // These can be accessed by multiple threads; mPackages is the lock. 181 // XXX For now we keep around information about all packages we have 182 // seen, not removing entries from this map. 183 // NOTE: The activity and window managers need to call in to 184 // ActivityThread to do things like update resource configurations, 185 // which means this lock gets held while the activity and window managers 186 // holds their own lock. Thus you MUST NEVER call back into the activity manager 187 // or window manager or anything that depends on them while holding this lock. 188 final HashMap<String, WeakReference<LoadedApk>> mPackages 189 = new HashMap<String, WeakReference<LoadedApk>>(); 190 final HashMap<String, WeakReference<LoadedApk>> mResourcePackages 191 = new HashMap<String, WeakReference<LoadedApk>>(); 192 final HashMap<CompatibilityInfo, DisplayMetrics> mDisplayMetrics 193 = new HashMap<CompatibilityInfo, DisplayMetrics>(); 194 final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources 195 = new HashMap<ResourcesKey, WeakReference<Resources> >(); 196 final ArrayList<ActivityClientRecord> mRelaunchingActivities 197 = new ArrayList<ActivityClientRecord>(); 198 Configuration mPendingConfiguration = null; 199 200 // The lock of mProviderMap protects the following variables. 201 final HashMap<String, ProviderClientRecord> mProviderMap 202 = new HashMap<String, ProviderClientRecord>(); 203 final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap 204 = new HashMap<IBinder, ProviderRefCount>(); 205 final HashMap<IBinder, ProviderClientRecord> mLocalProviders 206 = new HashMap<IBinder, ProviderClientRecord>(); 207 208 final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners 209 = new HashMap<Activity, ArrayList<OnActivityPausedListener>>(); 210 211 final GcIdler mGcIdler = new GcIdler(); 212 boolean mGcIdlerScheduled = false; 213 214 static Handler sMainThreadHandler; // set once in main() 215 216 Bundle mCoreSettings = null; 217 218 static final class ActivityClientRecord { 219 IBinder token; 220 int ident; 221 Intent intent; 222 Bundle state; 223 Activity activity; 224 Window window; 225 Activity parent; 226 String embeddedID; 227 Activity.NonConfigurationInstances lastNonConfigurationInstances; 228 boolean paused; 229 boolean stopped; 230 boolean hideForNow; 231 Configuration newConfig; 232 Configuration createdConfig; 233 ActivityClientRecord nextIdle; 234 235 String profileFile; 236 ParcelFileDescriptor profileFd; 237 boolean autoStopProfiler; 238 239 ActivityInfo activityInfo; 240 CompatibilityInfo compatInfo; 241 LoadedApk packageInfo; 242 243 List<ResultInfo> pendingResults; 244 List<Intent> pendingIntents; 245 246 boolean startsNotResumed; 247 boolean isForward; 248 int pendingConfigChanges; 249 boolean onlyLocalRequest; 250 251 View mPendingRemoveWindow; 252 WindowManager mPendingRemoveWindowManager; 253 254 ActivityClientRecord() { 255 parent = null; 256 embeddedID = null; 257 paused = false; 258 stopped = false; 259 hideForNow = false; 260 nextIdle = null; 261 } 262 263 public boolean isPreHoneycomb() { 264 if (activity != null) { 265 return activity.getApplicationInfo().targetSdkVersion 266 < android.os.Build.VERSION_CODES.HONEYCOMB; 267 } 268 return false; 269 } 270 271 public String toString() { 272 ComponentName componentName = intent.getComponent(); 273 return "ActivityRecord{" 274 + Integer.toHexString(System.identityHashCode(this)) 275 + " token=" + token + " " + (componentName == null 276 ? "no component name" : componentName.toShortString()) 277 + "}"; 278 } 279 } 280 281 final class ProviderClientRecord implements IBinder.DeathRecipient { 282 final String mName; 283 final IContentProvider mProvider; 284 final ContentProvider mLocalProvider; 285 286 ProviderClientRecord(String name, IContentProvider provider, 287 ContentProvider localProvider) { 288 mName = name; 289 mProvider = provider; 290 mLocalProvider = localProvider; 291 } 292 293 public void binderDied() { 294 removeDeadProvider(mName, mProvider); 295 } 296 } 297 298 static final class NewIntentData { 299 List<Intent> intents; 300 IBinder token; 301 public String toString() { 302 return "NewIntentData{intents=" + intents + " token=" + token + "}"; 303 } 304 } 305 306 static final class ReceiverData extends BroadcastReceiver.PendingResult { 307 public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras, 308 boolean ordered, boolean sticky, IBinder token) { 309 super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token); 310 this.intent = intent; 311 } 312 313 Intent intent; 314 ActivityInfo info; 315 CompatibilityInfo compatInfo; 316 public String toString() { 317 return "ReceiverData{intent=" + intent + " packageName=" + 318 info.packageName + " resultCode=" + getResultCode() 319 + " resultData=" + getResultData() + " resultExtras=" 320 + getResultExtras(false) + "}"; 321 } 322 } 323 324 static final class CreateBackupAgentData { 325 ApplicationInfo appInfo; 326 CompatibilityInfo compatInfo; 327 int backupMode; 328 public String toString() { 329 return "CreateBackupAgentData{appInfo=" + appInfo 330 + " backupAgent=" + appInfo.backupAgentName 331 + " mode=" + backupMode + "}"; 332 } 333 } 334 335 static final class CreateServiceData { 336 IBinder token; 337 ServiceInfo info; 338 CompatibilityInfo compatInfo; 339 Intent intent; 340 public String toString() { 341 return "CreateServiceData{token=" + token + " className=" 342 + info.name + " packageName=" + info.packageName 343 + " intent=" + intent + "}"; 344 } 345 } 346 347 static final class BindServiceData { 348 IBinder token; 349 Intent intent; 350 boolean rebind; 351 public String toString() { 352 return "BindServiceData{token=" + token + " intent=" + intent + "}"; 353 } 354 } 355 356 static final class ServiceArgsData { 357 IBinder token; 358 boolean taskRemoved; 359 int startId; 360 int flags; 361 Intent args; 362 public String toString() { 363 return "ServiceArgsData{token=" + token + " startId=" + startId 364 + " args=" + args + "}"; 365 } 366 } 367 368 static final class AppBindData { 369 LoadedApk info; 370 String processName; 371 ApplicationInfo appInfo; 372 List<ProviderInfo> providers; 373 ComponentName instrumentationName; 374 Bundle instrumentationArgs; 375 IInstrumentationWatcher instrumentationWatcher; 376 int debugMode; 377 boolean restrictedBackupMode; 378 boolean persistent; 379 Configuration config; 380 CompatibilityInfo compatInfo; 381 382 /** Initial values for {@link Profiler}. */ 383 String initProfileFile; 384 ParcelFileDescriptor initProfileFd; 385 boolean initAutoStopProfiler; 386 387 public String toString() { 388 return "AppBindData{appInfo=" + appInfo + "}"; 389 } 390 } 391 392 static final class Profiler { 393 String profileFile; 394 ParcelFileDescriptor profileFd; 395 boolean autoStopProfiler; 396 boolean profiling; 397 boolean handlingProfiling; 398 public void setProfiler(String file, ParcelFileDescriptor fd) { 399 if (profiling) { 400 if (fd != null) { 401 try { 402 fd.close(); 403 } catch (IOException e) { 404 } 405 } 406 return; 407 } 408 if (profileFd != null) { 409 try { 410 profileFd.close(); 411 } catch (IOException e) { 412 } 413 } 414 profileFile = file; 415 profileFd = fd; 416 } 417 public void startProfiling() { 418 if (profileFd == null || profiling) { 419 return; 420 } 421 try { 422 Debug.startMethodTracing(profileFile, profileFd.getFileDescriptor(), 423 8 * 1024 * 1024, 0); 424 profiling = true; 425 } catch (RuntimeException e) { 426 Slog.w(TAG, "Profiling failed on path " + profileFile); 427 try { 428 profileFd.close(); 429 profileFd = null; 430 } catch (IOException e2) { 431 Slog.w(TAG, "Failure closing profile fd", e2); 432 } 433 } 434 } 435 public void stopProfiling() { 436 if (profiling) { 437 profiling = false; 438 Debug.stopMethodTracing(); 439 if (profileFd != null) { 440 try { 441 profileFd.close(); 442 } catch (IOException e) { 443 } 444 } 445 profileFd = null; 446 profileFile = null; 447 } 448 } 449 } 450 451 static final class DumpComponentInfo { 452 ParcelFileDescriptor fd; 453 IBinder token; 454 String prefix; 455 String[] args; 456 } 457 458 static final class ResultData { 459 IBinder token; 460 List<ResultInfo> results; 461 public String toString() { 462 return "ResultData{token=" + token + " results" + results + "}"; 463 } 464 } 465 466 static final class ContextCleanupInfo { 467 ContextImpl context; 468 String what; 469 String who; 470 } 471 472 static final class ProfilerControlData { 473 String path; 474 ParcelFileDescriptor fd; 475 } 476 477 static final class DumpHeapData { 478 String path; 479 ParcelFileDescriptor fd; 480 } 481 482 static final class UpdateCompatibilityData { 483 String pkg; 484 CompatibilityInfo info; 485 } 486 487 private native void dumpGraphicsInfo(FileDescriptor fd); 488 489 private class ApplicationThread extends ApplicationThreadNative { 490 private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s"; 491 private static final String ONE_COUNT_COLUMN = "%21s %8d"; 492 private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d"; 493 private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s"; 494 495 // Formatting for checkin service - update version if row format changes 496 private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1; 497 498 private void updatePendingConfiguration(Configuration config) { 499 synchronized (mPackages) { 500 if (mPendingConfiguration == null || 501 mPendingConfiguration.isOtherSeqNewer(config)) { 502 mPendingConfiguration = config; 503 } 504 } 505 } 506 507 public final void schedulePauseActivity(IBinder token, boolean finished, 508 boolean userLeaving, int configChanges) { 509 queueOrSendMessage( 510 finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, 511 token, 512 (userLeaving ? 1 : 0), 513 configChanges); 514 } 515 516 public final void scheduleStopActivity(IBinder token, boolean showWindow, 517 int configChanges) { 518 queueOrSendMessage( 519 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE, 520 token, 0, configChanges); 521 } 522 523 public final void scheduleWindowVisibility(IBinder token, boolean showWindow) { 524 queueOrSendMessage( 525 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW, 526 token); 527 } 528 529 public final void scheduleSleeping(IBinder token, boolean sleeping) { 530 queueOrSendMessage(H.SLEEPING, token, sleeping ? 1 : 0); 531 } 532 533 public final void scheduleResumeActivity(IBinder token, boolean isForward) { 534 queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0); 535 } 536 537 public final void scheduleSendResult(IBinder token, List<ResultInfo> results) { 538 ResultData res = new ResultData(); 539 res.token = token; 540 res.results = results; 541 queueOrSendMessage(H.SEND_RESULT, res); 542 } 543 544 // we use token to identify this activity without having to send the 545 // activity itself back to the activity manager. (matters more with ipc) 546 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, 547 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, 548 Bundle state, List<ResultInfo> pendingResults, 549 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, 550 String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { 551 ActivityClientRecord r = new ActivityClientRecord(); 552 553 r.token = token; 554 r.ident = ident; 555 r.intent = intent; 556 r.activityInfo = info; 557 r.compatInfo = compatInfo; 558 r.state = state; 559 560 r.pendingResults = pendingResults; 561 r.pendingIntents = pendingNewIntents; 562 563 r.startsNotResumed = notResumed; 564 r.isForward = isForward; 565 566 r.profileFile = profileName; 567 r.profileFd = profileFd; 568 r.autoStopProfiler = autoStopProfiler; 569 570 updatePendingConfiguration(curConfig); 571 572 queueOrSendMessage(H.LAUNCH_ACTIVITY, r); 573 } 574 575 public final void scheduleRelaunchActivity(IBinder token, 576 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, 577 int configChanges, boolean notResumed, Configuration config) { 578 requestRelaunchActivity(token, pendingResults, pendingNewIntents, 579 configChanges, notResumed, config, true); 580 } 581 582 public final void scheduleNewIntent(List<Intent> intents, IBinder token) { 583 NewIntentData data = new NewIntentData(); 584 data.intents = intents; 585 data.token = token; 586 587 queueOrSendMessage(H.NEW_INTENT, data); 588 } 589 590 public final void scheduleDestroyActivity(IBinder token, boolean finishing, 591 int configChanges) { 592 queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0, 593 configChanges); 594 } 595 596 public final void scheduleReceiver(Intent intent, ActivityInfo info, 597 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, 598 boolean sync) { 599 ReceiverData r = new ReceiverData(intent, resultCode, data, extras, 600 sync, false, mAppThread.asBinder()); 601 r.info = info; 602 r.compatInfo = compatInfo; 603 queueOrSendMessage(H.RECEIVER, r); 604 } 605 606 public final void scheduleCreateBackupAgent(ApplicationInfo app, 607 CompatibilityInfo compatInfo, int backupMode) { 608 CreateBackupAgentData d = new CreateBackupAgentData(); 609 d.appInfo = app; 610 d.compatInfo = compatInfo; 611 d.backupMode = backupMode; 612 613 queueOrSendMessage(H.CREATE_BACKUP_AGENT, d); 614 } 615 616 public final void scheduleDestroyBackupAgent(ApplicationInfo app, 617 CompatibilityInfo compatInfo) { 618 CreateBackupAgentData d = new CreateBackupAgentData(); 619 d.appInfo = app; 620 d.compatInfo = compatInfo; 621 622 queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d); 623 } 624 625 public final void scheduleCreateService(IBinder token, 626 ServiceInfo info, CompatibilityInfo compatInfo) { 627 CreateServiceData s = new CreateServiceData(); 628 s.token = token; 629 s.info = info; 630 s.compatInfo = compatInfo; 631 632 queueOrSendMessage(H.CREATE_SERVICE, s); 633 } 634 635 public final void scheduleBindService(IBinder token, Intent intent, 636 boolean rebind) { 637 BindServiceData s = new BindServiceData(); 638 s.token = token; 639 s.intent = intent; 640 s.rebind = rebind; 641 642 if (DEBUG_SERVICE) 643 Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid=" 644 + Binder.getCallingUid() + " pid=" + Binder.getCallingPid()); 645 queueOrSendMessage(H.BIND_SERVICE, s); 646 } 647 648 public final void scheduleUnbindService(IBinder token, Intent intent) { 649 BindServiceData s = new BindServiceData(); 650 s.token = token; 651 s.intent = intent; 652 653 queueOrSendMessage(H.UNBIND_SERVICE, s); 654 } 655 656 public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId, 657 int flags ,Intent args) { 658 ServiceArgsData s = new ServiceArgsData(); 659 s.token = token; 660 s.taskRemoved = taskRemoved; 661 s.startId = startId; 662 s.flags = flags; 663 s.args = args; 664 665 queueOrSendMessage(H.SERVICE_ARGS, s); 666 } 667 668 public final void scheduleStopService(IBinder token) { 669 queueOrSendMessage(H.STOP_SERVICE, token); 670 } 671 672 public final void bindApplication(String processName, 673 ApplicationInfo appInfo, List<ProviderInfo> providers, 674 ComponentName instrumentationName, String profileFile, 675 ParcelFileDescriptor profileFd, boolean autoStopProfiler, 676 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, 677 int debugMode, boolean isRestrictedBackupMode, boolean persistent, 678 Configuration config, CompatibilityInfo compatInfo, 679 Map<String, IBinder> services, Bundle coreSettings) { 680 681 if (services != null) { 682 // Setup the service cache in the ServiceManager 683 ServiceManager.initServiceCache(services); 684 } 685 686 setCoreSettings(coreSettings); 687 688 AppBindData data = new AppBindData(); 689 data.processName = processName; 690 data.appInfo = appInfo; 691 data.providers = providers; 692 data.instrumentationName = instrumentationName; 693 data.instrumentationArgs = instrumentationArgs; 694 data.instrumentationWatcher = instrumentationWatcher; 695 data.debugMode = debugMode; 696 data.restrictedBackupMode = isRestrictedBackupMode; 697 data.persistent = persistent; 698 data.config = config; 699 data.compatInfo = compatInfo; 700 data.initProfileFile = profileFile; 701 data.initProfileFd = profileFd; 702 data.initAutoStopProfiler = false; 703 queueOrSendMessage(H.BIND_APPLICATION, data); 704 } 705 706 public final void scheduleExit() { 707 queueOrSendMessage(H.EXIT_APPLICATION, null); 708 } 709 710 public final void scheduleSuicide() { 711 queueOrSendMessage(H.SUICIDE, null); 712 } 713 714 public void requestThumbnail(IBinder token) { 715 queueOrSendMessage(H.REQUEST_THUMBNAIL, token); 716 } 717 718 public void scheduleConfigurationChanged(Configuration config) { 719 updatePendingConfiguration(config); 720 queueOrSendMessage(H.CONFIGURATION_CHANGED, config); 721 } 722 723 public void updateTimeZone() { 724 TimeZone.setDefault(null); 725 } 726 727 public void clearDnsCache() { 728 // a non-standard API to get this to libcore 729 InetAddress.clearDnsCache(); 730 } 731 732 public void setHttpProxy(String host, String port, String exclList) { 733 Proxy.setHttpProxySystemProperty(host, port, exclList); 734 } 735 736 public void processInBackground() { 737 mH.removeMessages(H.GC_WHEN_IDLE); 738 mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE)); 739 } 740 741 public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) { 742 DumpComponentInfo data = new DumpComponentInfo(); 743 try { 744 data.fd = ParcelFileDescriptor.dup(fd); 745 data.token = servicetoken; 746 data.args = args; 747 queueOrSendMessage(H.DUMP_SERVICE, data); 748 } catch (IOException e) { 749 Slog.w(TAG, "dumpService failed", e); 750 } 751 } 752 753 // This function exists to make sure all receiver dispatching is 754 // correctly ordered, since these are one-way calls and the binder driver 755 // applies transaction ordering per object for such calls. 756 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, 757 int resultCode, String dataStr, Bundle extras, boolean ordered, 758 boolean sticky) throws RemoteException { 759 receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky); 760 } 761 762 public void scheduleLowMemory() { 763 queueOrSendMessage(H.LOW_MEMORY, null); 764 } 765 766 public void scheduleActivityConfigurationChanged(IBinder token) { 767 queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token); 768 } 769 770 public void profilerControl(boolean start, String path, ParcelFileDescriptor fd, 771 int profileType) { 772 ProfilerControlData pcd = new ProfilerControlData(); 773 pcd.path = path; 774 pcd.fd = fd; 775 queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType); 776 } 777 778 public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) { 779 DumpHeapData dhd = new DumpHeapData(); 780 dhd.path = path; 781 dhd.fd = fd; 782 queueOrSendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0); 783 } 784 785 public void setSchedulingGroup(int group) { 786 // Note: do this immediately, since going into the foreground 787 // should happen regardless of what pending work we have to do 788 // and the activity manager will wait for us to report back that 789 // we are done before sending us to the background. 790 try { 791 Process.setProcessGroup(Process.myPid(), group); 792 } catch (Exception e) { 793 Slog.w(TAG, "Failed setting process group to " + group, e); 794 } 795 } 796 797 public void getMemoryInfo(Debug.MemoryInfo outInfo) { 798 Debug.getMemoryInfo(outInfo); 799 } 800 801 public void dispatchPackageBroadcast(int cmd, String[] packages) { 802 queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd); 803 } 804 805 public void scheduleCrash(String msg) { 806 queueOrSendMessage(H.SCHEDULE_CRASH, msg); 807 } 808 809 public void dumpActivity(FileDescriptor fd, IBinder activitytoken, 810 String prefix, String[] args) { 811 DumpComponentInfo data = new DumpComponentInfo(); 812 try { 813 data.fd = ParcelFileDescriptor.dup(fd); 814 data.token = activitytoken; 815 data.prefix = prefix; 816 data.args = args; 817 queueOrSendMessage(H.DUMP_ACTIVITY, data); 818 } catch (IOException e) { 819 Slog.w(TAG, "dumpActivity failed", e); 820 } 821 } 822 823 public void dumpProvider(FileDescriptor fd, IBinder providertoken, 824 String[] args) { 825 DumpComponentInfo data = new DumpComponentInfo(); 826 try { 827 data.fd = ParcelFileDescriptor.dup(fd); 828 data.token = providertoken; 829 data.args = args; 830 queueOrSendMessage(H.DUMP_PROVIDER, data); 831 } catch (IOException e) { 832 Slog.w(TAG, "dumpProvider failed", e); 833 } 834 } 835 836 @Override 837 public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin, 838 boolean all, String[] args) { 839 FileOutputStream fout = new FileOutputStream(fd); 840 PrintWriter pw = new PrintWriter(fout); 841 try { 842 return dumpMemInfo(pw, checkin, all, args); 843 } finally { 844 pw.flush(); 845 } 846 } 847 848 private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, boolean checkin, boolean all, 849 String[] args) { 850 long nativeMax = Debug.getNativeHeapSize() / 1024; 851 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; 852 long nativeFree = Debug.getNativeHeapFreeSize() / 1024; 853 854 Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); 855 Debug.getMemoryInfo(memInfo); 856 857 if (!all) { 858 return memInfo; 859 } 860 861 Runtime runtime = Runtime.getRuntime(); 862 863 long dalvikMax = runtime.totalMemory() / 1024; 864 long dalvikFree = runtime.freeMemory() / 1024; 865 long dalvikAllocated = dalvikMax - dalvikFree; 866 long viewInstanceCount = ViewDebug.getViewInstanceCount(); 867 long viewRootInstanceCount = ViewDebug.getViewRootImplCount(); 868 long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class); 869 long activityInstanceCount = Debug.countInstancesOfClass(Activity.class); 870 int globalAssetCount = AssetManager.getGlobalAssetCount(); 871 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount(); 872 int binderLocalObjectCount = Debug.getBinderLocalObjectCount(); 873 int binderProxyObjectCount = Debug.getBinderProxyObjectCount(); 874 int binderDeathObjectCount = Debug.getBinderDeathObjectCount(); 875 long openSslSocketCount = Debug.countInstancesOfClass(OpenSSLSocketImpl.class); 876 SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo(); 877 878 // For checkin, we print one long comma-separated list of values 879 if (checkin) { 880 // NOTE: if you change anything significant below, also consider changing 881 // ACTIVITY_THREAD_CHECKIN_VERSION. 882 String processName = (mBoundApplication != null) 883 ? mBoundApplication.processName : "unknown"; 884 885 // Header 886 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(','); 887 pw.print(Process.myPid()); pw.print(','); 888 pw.print(processName); pw.print(','); 889 890 // Heap info - max 891 pw.print(nativeMax); pw.print(','); 892 pw.print(dalvikMax); pw.print(','); 893 pw.print("N/A,"); 894 pw.print(nativeMax + dalvikMax); pw.print(','); 895 896 // Heap info - allocated 897 pw.print(nativeAllocated); pw.print(','); 898 pw.print(dalvikAllocated); pw.print(','); 899 pw.print("N/A,"); 900 pw.print(nativeAllocated + dalvikAllocated); pw.print(','); 901 902 // Heap info - free 903 pw.print(nativeFree); pw.print(','); 904 pw.print(dalvikFree); pw.print(','); 905 pw.print("N/A,"); 906 pw.print(nativeFree + dalvikFree); pw.print(','); 907 908 // Heap info - proportional set size 909 pw.print(memInfo.nativePss); pw.print(','); 910 pw.print(memInfo.dalvikPss); pw.print(','); 911 pw.print(memInfo.otherPss); pw.print(','); 912 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(','); 913 914 // Heap info - shared 915 pw.print(memInfo.nativeSharedDirty); pw.print(','); 916 pw.print(memInfo.dalvikSharedDirty); pw.print(','); 917 pw.print(memInfo.otherSharedDirty); pw.print(','); 918 pw.print(memInfo.nativeSharedDirty + memInfo.dalvikSharedDirty 919 + memInfo.otherSharedDirty); pw.print(','); 920 921 // Heap info - private 922 pw.print(memInfo.nativePrivateDirty); pw.print(','); 923 pw.print(memInfo.dalvikPrivateDirty); pw.print(','); 924 pw.print(memInfo.otherPrivateDirty); pw.print(','); 925 pw.print(memInfo.nativePrivateDirty + memInfo.dalvikPrivateDirty 926 + memInfo.otherPrivateDirty); pw.print(','); 927 928 // Object counts 929 pw.print(viewInstanceCount); pw.print(','); 930 pw.print(viewRootInstanceCount); pw.print(','); 931 pw.print(appContextInstanceCount); pw.print(','); 932 pw.print(activityInstanceCount); pw.print(','); 933 934 pw.print(globalAssetCount); pw.print(','); 935 pw.print(globalAssetManagerCount); pw.print(','); 936 pw.print(binderLocalObjectCount); pw.print(','); 937 pw.print(binderProxyObjectCount); pw.print(','); 938 939 pw.print(binderDeathObjectCount); pw.print(','); 940 pw.print(openSslSocketCount); pw.print(','); 941 942 // SQL 943 pw.print(stats.memoryUsed / 1024); pw.print(','); 944 pw.print(stats.memoryUsed / 1024); pw.print(','); 945 pw.print(stats.pageCacheOverflow / 1024); pw.print(','); 946 pw.print(stats.largestMemAlloc / 1024); 947 for (int i = 0; i < stats.dbStats.size(); i++) { 948 DbStats dbStats = stats.dbStats.get(i); 949 pw.print(','); pw.print(dbStats.dbName); 950 pw.print(','); pw.print(dbStats.pageSize); 951 pw.print(','); pw.print(dbStats.dbSize); 952 pw.print(','); pw.print(dbStats.lookaside); 953 pw.print(','); pw.print(dbStats.cache); 954 pw.print(','); pw.print(dbStats.cache); 955 } 956 pw.println(); 957 958 return memInfo; 959 } 960 961 // otherwise, show human-readable format 962 printRow(pw, HEAP_COLUMN, "", "", "Shared", "Private", "Heap", "Heap", "Heap"); 963 printRow(pw, HEAP_COLUMN, "", "Pss", "Dirty", "Dirty", "Size", "Alloc", "Free"); 964 printRow(pw, HEAP_COLUMN, "", "------", "------", "------", "------", "------", 965 "------"); 966 printRow(pw, HEAP_COLUMN, "Native", memInfo.nativePss, memInfo.nativeSharedDirty, 967 memInfo.nativePrivateDirty, nativeMax, nativeAllocated, nativeFree); 968 printRow(pw, HEAP_COLUMN, "Dalvik", memInfo.dalvikPss, memInfo.dalvikSharedDirty, 969 memInfo.dalvikPrivateDirty, dalvikMax, dalvikAllocated, dalvikFree); 970 971 int otherPss = memInfo.otherPss; 972 int otherSharedDirty = memInfo.otherSharedDirty; 973 int otherPrivateDirty = memInfo.otherPrivateDirty; 974 975 for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) { 976 printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i), 977 memInfo.getOtherPss(i), memInfo.getOtherSharedDirty(i), 978 memInfo.getOtherPrivateDirty(i), "", "", ""); 979 otherPss -= memInfo.getOtherPss(i); 980 otherSharedDirty -= memInfo.getOtherSharedDirty(i); 981 otherPrivateDirty -= memInfo.getOtherPrivateDirty(i); 982 } 983 984 printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSharedDirty, 985 otherPrivateDirty, "", "", ""); 986 printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(), 987 memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(), 988 nativeMax+dalvikMax, nativeAllocated+dalvikAllocated, 989 nativeFree+dalvikFree); 990 991 pw.println(" "); 992 pw.println(" Objects"); 993 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:", 994 viewRootInstanceCount); 995 996 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount, 997 "Activities:", activityInstanceCount); 998 999 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount, 1000 "AssetManagers:", globalAssetManagerCount); 1001 1002 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount, 1003 "Proxy Binders:", binderProxyObjectCount); 1004 printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount); 1005 1006 printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount); 1007 1008 // SQLite mem info 1009 pw.println(" "); 1010 pw.println(" SQL"); 1011 printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024); 1012 printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:", 1013 stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024); 1014 pw.println(" "); 1015 int N = stats.dbStats.size(); 1016 if (N > 0) { 1017 pw.println(" DATABASES"); 1018 printRow(pw, " %8s %8s %14s %14s %s", "pgsz", "dbsz", "Lookaside(b)", "cache", 1019 "Dbname"); 1020 for (int i = 0; i < N; i++) { 1021 DbStats dbStats = stats.dbStats.get(i); 1022 printRow(pw, DB_INFO_FORMAT, 1023 (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ", 1024 (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ", 1025 (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ", 1026 dbStats.cache, dbStats.dbName); 1027 } 1028 } 1029 1030 // Asset details. 1031 String assetAlloc = AssetManager.getAssetAllocations(); 1032 if (assetAlloc != null) { 1033 pw.println(" "); 1034 pw.println(" Asset Allocations"); 1035 pw.print(assetAlloc); 1036 } 1037 1038 return memInfo; 1039 } 1040 1041 @Override 1042 public void dumpGfxInfo(FileDescriptor fd, String[] args) { 1043 dumpGraphicsInfo(fd); 1044 WindowManagerImpl.getDefault().dumpGfxInfo(fd); 1045 } 1046 1047 @Override 1048 public void dumpDbInfo(FileDescriptor fd, String[] args) { 1049 PrintWriter pw = new PrintWriter(new FileOutputStream(fd)); 1050 PrintWriterPrinter printer = new PrintWriterPrinter(pw); 1051 SQLiteDebug.dump(printer, args); 1052 pw.flush(); 1053 } 1054 1055 private void printRow(PrintWriter pw, String format, Object...objs) { 1056 pw.println(String.format(format, objs)); 1057 } 1058 1059 public void setCoreSettings(Bundle coreSettings) { 1060 queueOrSendMessage(H.SET_CORE_SETTINGS, coreSettings); 1061 } 1062 1063 public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) { 1064 UpdateCompatibilityData ucd = new UpdateCompatibilityData(); 1065 ucd.pkg = pkg; 1066 ucd.info = info; 1067 queueOrSendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd); 1068 } 1069 1070 public void scheduleTrimMemory(int level) { 1071 queueOrSendMessage(H.TRIM_MEMORY, null, level); 1072 } 1073 1074 } 1075 1076 private class H extends Handler { 1077 public static final int LAUNCH_ACTIVITY = 100; 1078 public static final int PAUSE_ACTIVITY = 101; 1079 public static final int PAUSE_ACTIVITY_FINISHING= 102; 1080 public static final int STOP_ACTIVITY_SHOW = 103; 1081 public static final int STOP_ACTIVITY_HIDE = 104; 1082 public static final int SHOW_WINDOW = 105; 1083 public static final int HIDE_WINDOW = 106; 1084 public static final int RESUME_ACTIVITY = 107; 1085 public static final int SEND_RESULT = 108; 1086 public static final int DESTROY_ACTIVITY = 109; 1087 public static final int BIND_APPLICATION = 110; 1088 public static final int EXIT_APPLICATION = 111; 1089 public static final int NEW_INTENT = 112; 1090 public static final int RECEIVER = 113; 1091 public static final int CREATE_SERVICE = 114; 1092 public static final int SERVICE_ARGS = 115; 1093 public static final int STOP_SERVICE = 116; 1094 public static final int REQUEST_THUMBNAIL = 117; 1095 public static final int CONFIGURATION_CHANGED = 118; 1096 public static final int CLEAN_UP_CONTEXT = 119; 1097 public static final int GC_WHEN_IDLE = 120; 1098 public static final int BIND_SERVICE = 121; 1099 public static final int UNBIND_SERVICE = 122; 1100 public static final int DUMP_SERVICE = 123; 1101 public static final int LOW_MEMORY = 124; 1102 public static final int ACTIVITY_CONFIGURATION_CHANGED = 125; 1103 public static final int RELAUNCH_ACTIVITY = 126; 1104 public static final int PROFILER_CONTROL = 127; 1105 public static final int CREATE_BACKUP_AGENT = 128; 1106 public static final int DESTROY_BACKUP_AGENT = 129; 1107 public static final int SUICIDE = 130; 1108 public static final int REMOVE_PROVIDER = 131; 1109 public static final int ENABLE_JIT = 132; 1110 public static final int DISPATCH_PACKAGE_BROADCAST = 133; 1111 public static final int SCHEDULE_CRASH = 134; 1112 public static final int DUMP_HEAP = 135; 1113 public static final int DUMP_ACTIVITY = 136; 1114 public static final int SLEEPING = 137; 1115 public static final int SET_CORE_SETTINGS = 138; 1116 public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139; 1117 public static final int TRIM_MEMORY = 140; 1118 public static final int DUMP_PROVIDER = 141; 1119 String codeToString(int code) { 1120 if (DEBUG_MESSAGES) { 1121 switch (code) { 1122 case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY"; 1123 case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY"; 1124 case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING"; 1125 case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW"; 1126 case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE"; 1127 case SHOW_WINDOW: return "SHOW_WINDOW"; 1128 case HIDE_WINDOW: return "HIDE_WINDOW"; 1129 case RESUME_ACTIVITY: return "RESUME_ACTIVITY"; 1130 case SEND_RESULT: return "SEND_RESULT"; 1131 case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY"; 1132 case BIND_APPLICATION: return "BIND_APPLICATION"; 1133 case EXIT_APPLICATION: return "EXIT_APPLICATION"; 1134 case NEW_INTENT: return "NEW_INTENT"; 1135 case RECEIVER: return "RECEIVER"; 1136 case CREATE_SERVICE: return "CREATE_SERVICE"; 1137 case SERVICE_ARGS: return "SERVICE_ARGS"; 1138 case STOP_SERVICE: return "STOP_SERVICE"; 1139 case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL"; 1140 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED"; 1141 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT"; 1142 case GC_WHEN_IDLE: return "GC_WHEN_IDLE"; 1143 case BIND_SERVICE: return "BIND_SERVICE"; 1144 case UNBIND_SERVICE: return "UNBIND_SERVICE"; 1145 case DUMP_SERVICE: return "DUMP_SERVICE"; 1146 case LOW_MEMORY: return "LOW_MEMORY"; 1147 case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED"; 1148 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; 1149 case PROFILER_CONTROL: return "PROFILER_CONTROL"; 1150 case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT"; 1151 case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT"; 1152 case SUICIDE: return "SUICIDE"; 1153 case REMOVE_PROVIDER: return "REMOVE_PROVIDER"; 1154 case ENABLE_JIT: return "ENABLE_JIT"; 1155 case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST"; 1156 case SCHEDULE_CRASH: return "SCHEDULE_CRASH"; 1157 case DUMP_HEAP: return "DUMP_HEAP"; 1158 case DUMP_ACTIVITY: return "DUMP_ACTIVITY"; 1159 case SLEEPING: return "SLEEPING"; 1160 case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS"; 1161 case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO"; 1162 case TRIM_MEMORY: return "TRIM_MEMORY"; 1163 case DUMP_PROVIDER: return "DUMP_PROVIDER"; 1164 } 1165 } 1166 return "(unknown)"; 1167 } 1168 public void handleMessage(Message msg) { 1169 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what); 1170 switch (msg.what) { 1171 case LAUNCH_ACTIVITY: { 1172 ActivityClientRecord r = (ActivityClientRecord)msg.obj; 1173 1174 r.packageInfo = getPackageInfoNoCheck( 1175 r.activityInfo.applicationInfo, r.compatInfo); 1176 handleLaunchActivity(r, null); 1177 } break; 1178 case RELAUNCH_ACTIVITY: { 1179 ActivityClientRecord r = (ActivityClientRecord)msg.obj; 1180 handleRelaunchActivity(r); 1181 } break; 1182 case PAUSE_ACTIVITY: 1183 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2); 1184 maybeSnapshot(); 1185 break; 1186 case PAUSE_ACTIVITY_FINISHING: 1187 handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2); 1188 break; 1189 case STOP_ACTIVITY_SHOW: 1190 handleStopActivity((IBinder)msg.obj, true, msg.arg2); 1191 break; 1192 case STOP_ACTIVITY_HIDE: 1193 handleStopActivity((IBinder)msg.obj, false, msg.arg2); 1194 break; 1195 case SHOW_WINDOW: 1196 handleWindowVisibility((IBinder)msg.obj, true); 1197 break; 1198 case HIDE_WINDOW: 1199 handleWindowVisibility((IBinder)msg.obj, false); 1200 break; 1201 case RESUME_ACTIVITY: 1202 handleResumeActivity((IBinder)msg.obj, true, 1203 msg.arg1 != 0); 1204 break; 1205 case SEND_RESULT: 1206 handleSendResult((ResultData)msg.obj); 1207 break; 1208 case DESTROY_ACTIVITY: 1209 handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0, 1210 msg.arg2, false); 1211 break; 1212 case BIND_APPLICATION: 1213 AppBindData data = (AppBindData)msg.obj; 1214 handleBindApplication(data); 1215 break; 1216 case EXIT_APPLICATION: 1217 if (mInitialApplication != null) { 1218 mInitialApplication.onTerminate(); 1219 } 1220 Looper.myLooper().quit(); 1221 break; 1222 case NEW_INTENT: 1223 handleNewIntent((NewIntentData)msg.obj); 1224 break; 1225 case RECEIVER: 1226 handleReceiver((ReceiverData)msg.obj); 1227 maybeSnapshot(); 1228 break; 1229 case CREATE_SERVICE: 1230 handleCreateService((CreateServiceData)msg.obj); 1231 break; 1232 case BIND_SERVICE: 1233 handleBindService((BindServiceData)msg.obj); 1234 break; 1235 case UNBIND_SERVICE: 1236 handleUnbindService((BindServiceData)msg.obj); 1237 break; 1238 case SERVICE_ARGS: 1239 handleServiceArgs((ServiceArgsData)msg.obj); 1240 break; 1241 case STOP_SERVICE: 1242 handleStopService((IBinder)msg.obj); 1243 maybeSnapshot(); 1244 break; 1245 case REQUEST_THUMBNAIL: 1246 handleRequestThumbnail((IBinder)msg.obj); 1247 break; 1248 case CONFIGURATION_CHANGED: 1249 handleConfigurationChanged((Configuration)msg.obj, null); 1250 break; 1251 case CLEAN_UP_CONTEXT: 1252 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj; 1253 cci.context.performFinalCleanup(cci.who, cci.what); 1254 break; 1255 case GC_WHEN_IDLE: 1256 scheduleGcIdler(); 1257 break; 1258 case DUMP_SERVICE: 1259 handleDumpService((DumpComponentInfo)msg.obj); 1260 break; 1261 case LOW_MEMORY: 1262 handleLowMemory(); 1263 break; 1264 case ACTIVITY_CONFIGURATION_CHANGED: 1265 handleActivityConfigurationChanged((IBinder)msg.obj); 1266 break; 1267 case PROFILER_CONTROL: 1268 handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2); 1269 break; 1270 case CREATE_BACKUP_AGENT: 1271 handleCreateBackupAgent((CreateBackupAgentData)msg.obj); 1272 break; 1273 case DESTROY_BACKUP_AGENT: 1274 handleDestroyBackupAgent((CreateBackupAgentData)msg.obj); 1275 break; 1276 case SUICIDE: 1277 Process.killProcess(Process.myPid()); 1278 break; 1279 case REMOVE_PROVIDER: 1280 completeRemoveProvider((IContentProvider)msg.obj); 1281 break; 1282 case ENABLE_JIT: 1283 ensureJitEnabled(); 1284 break; 1285 case DISPATCH_PACKAGE_BROADCAST: 1286 handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj); 1287 break; 1288 case SCHEDULE_CRASH: 1289 throw new RemoteServiceException((String)msg.obj); 1290 case DUMP_HEAP: 1291 handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj); 1292 break; 1293 case DUMP_ACTIVITY: 1294 handleDumpActivity((DumpComponentInfo)msg.obj); 1295 break; 1296 case DUMP_PROVIDER: 1297 handleDumpProvider((DumpComponentInfo)msg.obj); 1298 break; 1299 case SLEEPING: 1300 handleSleeping((IBinder)msg.obj, msg.arg1 != 0); 1301 break; 1302 case SET_CORE_SETTINGS: 1303 handleSetCoreSettings((Bundle) msg.obj); 1304 break; 1305 case UPDATE_PACKAGE_COMPATIBILITY_INFO: 1306 handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj); 1307 break; 1308 case TRIM_MEMORY: 1309 handleTrimMemory(msg.arg1); 1310 break; 1311 } 1312 if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what); 1313 } 1314 1315 private void maybeSnapshot() { 1316 if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) { 1317 // convert the *private* ActivityThread.PackageInfo to *public* known 1318 // android.content.pm.PackageInfo 1319 String packageName = mBoundApplication.info.mPackageName; 1320 android.content.pm.PackageInfo packageInfo = null; 1321 try { 1322 Context context = getSystemContext(); 1323 if(context == null) { 1324 Log.e(TAG, "cannot get a valid context"); 1325 return; 1326 } 1327 PackageManager pm = context.getPackageManager(); 1328 if(pm == null) { 1329 Log.e(TAG, "cannot get a valid PackageManager"); 1330 return; 1331 } 1332 packageInfo = pm.getPackageInfo( 1333 packageName, PackageManager.GET_ACTIVITIES); 1334 } catch (NameNotFoundException e) { 1335 Log.e(TAG, "cannot get package info for " + packageName, e); 1336 } 1337 SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo); 1338 } 1339 } 1340 } 1341 1342 private class Idler implements MessageQueue.IdleHandler { 1343 public final boolean queueIdle() { 1344 ActivityClientRecord a = mNewActivities; 1345 boolean stopProfiling = false; 1346 if (mBoundApplication != null && mProfiler.profileFd != null 1347 && mProfiler.autoStopProfiler) { 1348 stopProfiling = true; 1349 } 1350 if (a != null) { 1351 mNewActivities = null; 1352 IActivityManager am = ActivityManagerNative.getDefault(); 1353 ActivityClientRecord prev; 1354 do { 1355 if (localLOGV) Slog.v( 1356 TAG, "Reporting idle of " + a + 1357 " finished=" + 1358 (a.activity != null && a.activity.mFinished)); 1359 if (a.activity != null && !a.activity.mFinished) { 1360 try { 1361 am.activityIdle(a.token, a.createdConfig, stopProfiling); 1362 a.createdConfig = null; 1363 } catch (RemoteException ex) { 1364 // Ignore 1365 } 1366 } 1367 prev = a; 1368 a = a.nextIdle; 1369 prev.nextIdle = null; 1370 } while (a != null); 1371 } 1372 if (stopProfiling) { 1373 mProfiler.stopProfiling(); 1374 } 1375 ensureJitEnabled(); 1376 return false; 1377 } 1378 } 1379 1380 final class GcIdler implements MessageQueue.IdleHandler { 1381 public final boolean queueIdle() { 1382 doGcIfNeeded(); 1383 return false; 1384 } 1385 } 1386 1387 private static class ResourcesKey { 1388 final private String mResDir; 1389 final private float mScale; 1390 final private int mHash; 1391 1392 ResourcesKey(String resDir, float scale) { 1393 mResDir = resDir; 1394 mScale = scale; 1395 mHash = mResDir.hashCode() << 2 + (int) (mScale * 2); 1396 } 1397 1398 @Override 1399 public int hashCode() { 1400 return mHash; 1401 } 1402 1403 @Override 1404 public boolean equals(Object obj) { 1405 if (!(obj instanceof ResourcesKey)) { 1406 return false; 1407 } 1408 ResourcesKey peer = (ResourcesKey) obj; 1409 return mResDir.equals(peer.mResDir) && mScale == peer.mScale; 1410 } 1411 } 1412 1413 public static ActivityThread currentActivityThread() { 1414 return sThreadLocal.get(); 1415 } 1416 1417 public static String currentPackageName() { 1418 ActivityThread am = currentActivityThread(); 1419 return (am != null && am.mBoundApplication != null) 1420 ? am.mBoundApplication.processName : null; 1421 } 1422 1423 public static Application currentApplication() { 1424 ActivityThread am = currentActivityThread(); 1425 return am != null ? am.mInitialApplication : null; 1426 } 1427 1428 public static IPackageManager getPackageManager() { 1429 if (sPackageManager != null) { 1430 //Slog.v("PackageManager", "returning cur default = " + sPackageManager); 1431 return sPackageManager; 1432 } 1433 IBinder b = ServiceManager.getService("package"); 1434 //Slog.v("PackageManager", "default service binder = " + b); 1435 sPackageManager = IPackageManager.Stub.asInterface(b); 1436 //Slog.v("PackageManager", "default service = " + sPackageManager); 1437 return sPackageManager; 1438 } 1439 1440 DisplayMetrics getDisplayMetricsLocked(CompatibilityInfo ci, boolean forceUpdate) { 1441 DisplayMetrics dm = mDisplayMetrics.get(ci); 1442 if (dm != null && !forceUpdate) { 1443 return dm; 1444 } 1445 if (dm == null) { 1446 dm = new DisplayMetrics(); 1447 mDisplayMetrics.put(ci, dm); 1448 } 1449 Display d = WindowManagerImpl.getDefault(ci).getDefaultDisplay(); 1450 d.getMetrics(dm); 1451 //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h=" 1452 // + metrics.heightPixels + " den=" + metrics.density 1453 // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi); 1454 return dm; 1455 } 1456 1457 static Configuration applyConfigCompat(Configuration config, CompatibilityInfo compat) { 1458 if (config == null) { 1459 return null; 1460 } 1461 if (compat != null && !compat.supportsScreen()) { 1462 config = new Configuration(config); 1463 compat.applyToConfiguration(config); 1464 } 1465 return config; 1466 } 1467 1468 private Configuration mMainThreadConfig = new Configuration(); 1469 Configuration applyConfigCompatMainThread(Configuration config, CompatibilityInfo compat) { 1470 if (config == null) { 1471 return null; 1472 } 1473 if (compat != null && !compat.supportsScreen()) { 1474 mMainThreadConfig.setTo(config); 1475 config = mMainThreadConfig; 1476 compat.applyToConfiguration(config); 1477 } 1478 return config; 1479 } 1480 1481 /** 1482 * Creates the top level Resources for applications with the given compatibility info. 1483 * 1484 * @param resDir the resource directory. 1485 * @param compInfo the compability info. It will use the default compatibility info when it's 1486 * null. 1487 */ 1488 Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) { 1489 ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale); 1490 Resources r; 1491 synchronized (mPackages) { 1492 // Resources is app scale dependent. 1493 if (false) { 1494 Slog.w(TAG, "getTopLevelResources: " + resDir + " / " 1495 + compInfo.applicationScale); 1496 } 1497 WeakReference<Resources> wr = mActiveResources.get(key); 1498 r = wr != null ? wr.get() : null; 1499 //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate()); 1500 if (r != null && r.getAssets().isUpToDate()) { 1501 if (false) { 1502 Slog.w(TAG, "Returning cached resources " + r + " " + resDir 1503 + ": appScale=" + r.getCompatibilityInfo().applicationScale); 1504 } 1505 return r; 1506 } 1507 } 1508 1509 //if (r != null) { 1510 // Slog.w(TAG, "Throwing away out-of-date resources!!!! " 1511 // + r + " " + resDir); 1512 //} 1513 1514 AssetManager assets = new AssetManager(); 1515 if (assets.addAssetPath(resDir) == 0) { 1516 return null; 1517 } 1518 1519 //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics); 1520 DisplayMetrics metrics = getDisplayMetricsLocked(null, false); 1521 r = new Resources(assets, metrics, getConfiguration(), compInfo); 1522 if (false) { 1523 Slog.i(TAG, "Created app resources " + resDir + " " + r + ": " 1524 + r.getConfiguration() + " appScale=" 1525 + r.getCompatibilityInfo().applicationScale); 1526 } 1527 1528 synchronized (mPackages) { 1529 WeakReference<Resources> wr = mActiveResources.get(key); 1530 Resources existing = wr != null ? wr.get() : null; 1531 if (existing != null && existing.getAssets().isUpToDate()) { 1532 // Someone else already created the resources while we were 1533 // unlocked; go ahead and use theirs. 1534 r.getAssets().close(); 1535 return existing; 1536 } 1537 1538 // XXX need to remove entries when weak references go away 1539 mActiveResources.put(key, new WeakReference<Resources>(r)); 1540 return r; 1541 } 1542 } 1543 1544 /** 1545 * Creates the top level resources for the given package. 1546 */ 1547 Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) { 1548 return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo.get()); 1549 } 1550 1551 final Handler getHandler() { 1552 return mH; 1553 } 1554 1555 public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, 1556 int flags) { 1557 synchronized (mPackages) { 1558 WeakReference<LoadedApk> ref; 1559 if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) { 1560 ref = mPackages.get(packageName); 1561 } else { 1562 ref = mResourcePackages.get(packageName); 1563 } 1564 LoadedApk packageInfo = ref != null ? ref.get() : null; 1565 //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo); 1566 //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir 1567 // + ": " + packageInfo.mResources.getAssets().isUpToDate()); 1568 if (packageInfo != null && (packageInfo.mResources == null 1569 || packageInfo.mResources.getAssets().isUpToDate())) { 1570 if (packageInfo.isSecurityViolation() 1571 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) { 1572 throw new SecurityException( 1573 "Requesting code from " + packageName 1574 + " to be run in process " 1575 + mBoundApplication.processName 1576 + "/" + mBoundApplication.appInfo.uid); 1577 } 1578 return packageInfo; 1579 } 1580 } 1581 1582 ApplicationInfo ai = null; 1583 try { 1584 ai = getPackageManager().getApplicationInfo(packageName, 1585 PackageManager.GET_SHARED_LIBRARY_FILES); 1586 } catch (RemoteException e) { 1587 // Ignore 1588 } 1589 1590 if (ai != null) { 1591 return getPackageInfo(ai, compatInfo, flags); 1592 } 1593 1594 return null; 1595 } 1596 1597 public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo, 1598 int flags) { 1599 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0; 1600 boolean securityViolation = includeCode && ai.uid != 0 1601 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null 1602 ? !UserId.isSameApp(ai.uid, mBoundApplication.appInfo.uid) 1603 : true); 1604 if ((flags&(Context.CONTEXT_INCLUDE_CODE 1605 |Context.CONTEXT_IGNORE_SECURITY)) 1606 == Context.CONTEXT_INCLUDE_CODE) { 1607 if (securityViolation) { 1608 String msg = "Requesting code from " + ai.packageName 1609 + " (with uid " + ai.uid + ")"; 1610 if (mBoundApplication != null) { 1611 msg = msg + " to be run in process " 1612 + mBoundApplication.processName + " (with uid " 1613 + mBoundApplication.appInfo.uid + ")"; 1614 } 1615 throw new SecurityException(msg); 1616 } 1617 } 1618 return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode); 1619 } 1620 1621 public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, 1622 CompatibilityInfo compatInfo) { 1623 return getPackageInfo(ai, compatInfo, null, false, true); 1624 } 1625 1626 public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) { 1627 synchronized (mPackages) { 1628 WeakReference<LoadedApk> ref; 1629 if (includeCode) { 1630 ref = mPackages.get(packageName); 1631 } else { 1632 ref = mResourcePackages.get(packageName); 1633 } 1634 return ref != null ? ref.get() : null; 1635 } 1636 } 1637 1638 private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, 1639 ClassLoader baseLoader, boolean securityViolation, boolean includeCode) { 1640 synchronized (mPackages) { 1641 WeakReference<LoadedApk> ref; 1642 if (includeCode) { 1643 ref = mPackages.get(aInfo.packageName); 1644 } else { 1645 ref = mResourcePackages.get(aInfo.packageName); 1646 } 1647 LoadedApk packageInfo = ref != null ? ref.get() : null; 1648 if (packageInfo == null || (packageInfo.mResources != null 1649 && !packageInfo.mResources.getAssets().isUpToDate())) { 1650 if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package " 1651 : "Loading resource-only package ") + aInfo.packageName 1652 + " (in " + (mBoundApplication != null 1653 ? mBoundApplication.processName : null) 1654 + ")"); 1655 packageInfo = 1656 new LoadedApk(this, aInfo, compatInfo, this, baseLoader, 1657 securityViolation, includeCode && 1658 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0); 1659 if (includeCode) { 1660 mPackages.put(aInfo.packageName, 1661 new WeakReference<LoadedApk>(packageInfo)); 1662 } else { 1663 mResourcePackages.put(aInfo.packageName, 1664 new WeakReference<LoadedApk>(packageInfo)); 1665 } 1666 } 1667 return packageInfo; 1668 } 1669 } 1670 1671 ActivityThread() { 1672 } 1673 1674 public ApplicationThread getApplicationThread() 1675 { 1676 return mAppThread; 1677 } 1678 1679 public Instrumentation getInstrumentation() 1680 { 1681 return mInstrumentation; 1682 } 1683 1684 public Configuration getConfiguration() { 1685 return mResConfiguration; 1686 } 1687 1688 public boolean isProfiling() { 1689 return mProfiler != null && mProfiler.profileFile != null 1690 && mProfiler.profileFd == null; 1691 } 1692 1693 public String getProfileFilePath() { 1694 return mProfiler.profileFile; 1695 } 1696 1697 public Looper getLooper() { 1698 return mLooper; 1699 } 1700 1701 public Application getApplication() { 1702 return mInitialApplication; 1703 } 1704 1705 public String getProcessName() { 1706 return mBoundApplication.processName; 1707 } 1708 1709 public ContextImpl getSystemContext() { 1710 synchronized (this) { 1711 if (mSystemContext == null) { 1712 ContextImpl context = 1713 ContextImpl.createSystemContext(this); 1714 LoadedApk info = new LoadedApk(this, "android", context, null, 1715 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO); 1716 context.init(info, null, this); 1717 context.getResources().updateConfiguration( 1718 getConfiguration(), getDisplayMetricsLocked( 1719 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false)); 1720 mSystemContext = context; 1721 //Slog.i(TAG, "Created system resources " + context.getResources() 1722 // + ": " + context.getResources().getConfiguration()); 1723 } 1724 } 1725 return mSystemContext; 1726 } 1727 1728 public void installSystemApplicationInfo(ApplicationInfo info) { 1729 synchronized (this) { 1730 ContextImpl context = getSystemContext(); 1731 context.init(new LoadedApk(this, "android", context, info, 1732 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this); 1733 1734 // give ourselves a default profiler 1735 mProfiler = new Profiler(); 1736 } 1737 } 1738 1739 void ensureJitEnabled() { 1740 if (!mJitEnabled) { 1741 mJitEnabled = true; 1742 dalvik.system.VMRuntime.getRuntime().startJitCompilation(); 1743 } 1744 } 1745 1746 void scheduleGcIdler() { 1747 if (!mGcIdlerScheduled) { 1748 mGcIdlerScheduled = true; 1749 Looper.myQueue().addIdleHandler(mGcIdler); 1750 } 1751 mH.removeMessages(H.GC_WHEN_IDLE); 1752 } 1753 1754 void unscheduleGcIdler() { 1755 if (mGcIdlerScheduled) { 1756 mGcIdlerScheduled = false; 1757 Looper.myQueue().removeIdleHandler(mGcIdler); 1758 } 1759 mH.removeMessages(H.GC_WHEN_IDLE); 1760 } 1761 1762 void doGcIfNeeded() { 1763 mGcIdlerScheduled = false; 1764 final long now = SystemClock.uptimeMillis(); 1765 //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime() 1766 // + "m now=" + now); 1767 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) { 1768 //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!"); 1769 BinderInternal.forceGc("bg"); 1770 } 1771 } 1772 1773 public void registerOnActivityPausedListener(Activity activity, 1774 OnActivityPausedListener listener) { 1775 synchronized (mOnPauseListeners) { 1776 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); 1777 if (list == null) { 1778 list = new ArrayList<OnActivityPausedListener>(); 1779 mOnPauseListeners.put(activity, list); 1780 } 1781 list.add(listener); 1782 } 1783 } 1784 1785 public void unregisterOnActivityPausedListener(Activity activity, 1786 OnActivityPausedListener listener) { 1787 synchronized (mOnPauseListeners) { 1788 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); 1789 if (list != null) { 1790 list.remove(listener); 1791 } 1792 } 1793 } 1794 1795 public final ActivityInfo resolveActivityInfo(Intent intent) { 1796 ActivityInfo aInfo = intent.resolveActivityInfo( 1797 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES); 1798 if (aInfo == null) { 1799 // Throw an exception. 1800 Instrumentation.checkStartActivityResult( 1801 IActivityManager.START_CLASS_NOT_FOUND, intent); 1802 } 1803 return aInfo; 1804 } 1805 1806 public final Activity startActivityNow(Activity parent, String id, 1807 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state, 1808 Activity.NonConfigurationInstances lastNonConfigurationInstances) { 1809 ActivityClientRecord r = new ActivityClientRecord(); 1810 r.token = token; 1811 r.ident = 0; 1812 r.intent = intent; 1813 r.state = state; 1814 r.parent = parent; 1815 r.embeddedID = id; 1816 r.activityInfo = activityInfo; 1817 r.lastNonConfigurationInstances = lastNonConfigurationInstances; 1818 if (localLOGV) { 1819 ComponentName compname = intent.getComponent(); 1820 String name; 1821 if (compname != null) { 1822 name = compname.toShortString(); 1823 } else { 1824 name = "(Intent " + intent + ").getComponent() returned null"; 1825 } 1826 Slog.v(TAG, "Performing launch: action=" + intent.getAction() 1827 + ", comp=" + name 1828 + ", token=" + token); 1829 } 1830 return performLaunchActivity(r, null); 1831 } 1832 1833 public final Activity getActivity(IBinder token) { 1834 return mActivities.get(token).activity; 1835 } 1836 1837 public final void sendActivityResult( 1838 IBinder token, String id, int requestCode, 1839 int resultCode, Intent data) { 1840 if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id 1841 + " req=" + requestCode + " res=" + resultCode + " data=" + data); 1842 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 1843 list.add(new ResultInfo(id, requestCode, resultCode, data)); 1844 mAppThread.scheduleSendResult(token, list); 1845 } 1846 1847 // if the thread hasn't started yet, we don't have the handler, so just 1848 // save the messages until we're ready. 1849 private void queueOrSendMessage(int what, Object obj) { 1850 queueOrSendMessage(what, obj, 0, 0); 1851 } 1852 1853 private void queueOrSendMessage(int what, Object obj, int arg1) { 1854 queueOrSendMessage(what, obj, arg1, 0); 1855 } 1856 1857 private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { 1858 synchronized (this) { 1859 if (DEBUG_MESSAGES) Slog.v( 1860 TAG, "SCHEDULE " + what + " " + mH.codeToString(what) 1861 + ": " + arg1 + " / " + obj); 1862 Message msg = Message.obtain(); 1863 msg.what = what; 1864 msg.obj = obj; 1865 msg.arg1 = arg1; 1866 msg.arg2 = arg2; 1867 mH.sendMessage(msg); 1868 } 1869 } 1870 1871 final void scheduleContextCleanup(ContextImpl context, String who, 1872 String what) { 1873 ContextCleanupInfo cci = new ContextCleanupInfo(); 1874 cci.context = context; 1875 cci.who = who; 1876 cci.what = what; 1877 queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci); 1878 } 1879 1880 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { 1881 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); 1882 1883 ActivityInfo aInfo = r.activityInfo; 1884 if (r.packageInfo == null) { 1885 r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, 1886 Context.CONTEXT_INCLUDE_CODE); 1887 } 1888 1889 ComponentName component = r.intent.getComponent(); 1890 if (component == null) { 1891 component = r.intent.resolveActivity( 1892 mInitialApplication.getPackageManager()); 1893 r.intent.setComponent(component); 1894 } 1895 1896 if (r.activityInfo.targetActivity != null) { 1897 component = new ComponentName(r.activityInfo.packageName, 1898 r.activityInfo.targetActivity); 1899 } 1900 1901 Activity activity = null; 1902 try { 1903 java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); 1904 activity = mInstrumentation.newActivity( 1905 cl, component.getClassName(), r.intent); 1906 StrictMode.incrementExpectedActivityCount(activity.getClass()); 1907 r.intent.setExtrasClassLoader(cl); 1908 if (r.state != null) { 1909 r.state.setClassLoader(cl); 1910 } 1911 } catch (Exception e) { 1912 if (!mInstrumentation.onException(activity, e)) { 1913 throw new RuntimeException( 1914 "Unable to instantiate activity " + component 1915 + ": " + e.toString(), e); 1916 } 1917 } 1918 1919 try { 1920 Application app = r.packageInfo.makeApplication(false, mInstrumentation); 1921 1922 if (localLOGV) Slog.v(TAG, "Performing launch of " + r); 1923 if (localLOGV) Slog.v( 1924 TAG, r + ": app=" + app 1925 + ", appName=" + app.getPackageName() 1926 + ", pkg=" + r.packageInfo.getPackageName() 1927 + ", comp=" + r.intent.getComponent().toShortString() 1928 + ", dir=" + r.packageInfo.getAppDir()); 1929 1930 if (activity != null) { 1931 ContextImpl appContext = new ContextImpl(); 1932 appContext.init(r.packageInfo, r.token, this); 1933 appContext.setOuterContext(activity); 1934 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); 1935 Configuration config = new Configuration(mCompatConfiguration); 1936 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " 1937 + r.activityInfo.name + " with config " + config); 1938 activity.attach(appContext, this, getInstrumentation(), r.token, 1939 r.ident, app, r.intent, r.activityInfo, title, r.parent, 1940 r.embeddedID, r.lastNonConfigurationInstances, config); 1941 1942 if (customIntent != null) { 1943 activity.mIntent = customIntent; 1944 } 1945 r.lastNonConfigurationInstances = null; 1946 activity.mStartedActivity = false; 1947 int theme = r.activityInfo.getThemeResource(); 1948 if (theme != 0) { 1949 activity.setTheme(theme); 1950 } 1951 1952 activity.mCalled = false; 1953 mInstrumentation.callActivityOnCreate(activity, r.state); 1954 if (!activity.mCalled) { 1955 throw new SuperNotCalledException( 1956 "Activity " + r.intent.getComponent().toShortString() + 1957 " did not call through to super.onCreate()"); 1958 } 1959 r.activity = activity; 1960 r.stopped = true; 1961 if (!r.activity.mFinished) { 1962 activity.performStart(); 1963 r.stopped = false; 1964 } 1965 if (!r.activity.mFinished) { 1966 if (r.state != null) { 1967 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); 1968 } 1969 } 1970 if (!r.activity.mFinished) { 1971 activity.mCalled = false; 1972 mInstrumentation.callActivityOnPostCreate(activity, r.state); 1973 if (!activity.mCalled) { 1974 throw new SuperNotCalledException( 1975 "Activity " + r.intent.getComponent().toShortString() + 1976 " did not call through to super.onPostCreate()"); 1977 } 1978 } 1979 } 1980 r.paused = true; 1981 1982 mActivities.put(r.token, r); 1983 1984 } catch (SuperNotCalledException e) { 1985 throw e; 1986 1987 } catch (Exception e) { 1988 if (!mInstrumentation.onException(activity, e)) { 1989 throw new RuntimeException( 1990 "Unable to start activity " + component 1991 + ": " + e.toString(), e); 1992 } 1993 } 1994 1995 return activity; 1996 } 1997 1998 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { 1999 // If we are getting ready to gc after going to the background, well 2000 // we are back active so skip it. 2001 unscheduleGcIdler(); 2002 2003 if (r.profileFd != null) { 2004 mProfiler.setProfiler(r.profileFile, r.profileFd); 2005 mProfiler.startProfiling(); 2006 mProfiler.autoStopProfiler = r.autoStopProfiler; 2007 } 2008 2009 // Make sure we are running with the most recent config. 2010 handleConfigurationChanged(null, null); 2011 2012 if (localLOGV) Slog.v( 2013 TAG, "Handling launch of " + r); 2014 Activity a = performLaunchActivity(r, customIntent); 2015 2016 if (a != null) { 2017 r.createdConfig = new Configuration(mConfiguration); 2018 Bundle oldState = r.state; 2019 handleResumeActivity(r.token, false, r.isForward); 2020 2021 if (!r.activity.mFinished && r.startsNotResumed) { 2022 // The activity manager actually wants this one to start out 2023 // paused, because it needs to be visible but isn't in the 2024 // foreground. We accomplish this by going through the 2025 // normal startup (because activities expect to go through 2026 // onResume() the first time they run, before their window 2027 // is displayed), and then pausing it. However, in this case 2028 // we do -not- need to do the full pause cycle (of freezing 2029 // and such) because the activity manager assumes it can just 2030 // retain the current state it has. 2031 try { 2032 r.activity.mCalled = false; 2033 mInstrumentation.callActivityOnPause(r.activity); 2034 // We need to keep around the original state, in case 2035 // we need to be created again. 2036 r.state = oldState; 2037 if (!r.activity.mCalled) { 2038 throw new SuperNotCalledException( 2039 "Activity " + r.intent.getComponent().toShortString() + 2040 " did not call through to super.onPause()"); 2041 } 2042 2043 } catch (SuperNotCalledException e) { 2044 throw e; 2045 2046 } catch (Exception e) { 2047 if (!mInstrumentation.onException(r.activity, e)) { 2048 throw new RuntimeException( 2049 "Unable to pause activity " 2050 + r.intent.getComponent().toShortString() 2051 + ": " + e.toString(), e); 2052 } 2053 } 2054 r.paused = true; 2055 } 2056 } else { 2057 // If there was an error, for any reason, tell the activity 2058 // manager to stop us. 2059 try { 2060 ActivityManagerNative.getDefault() 2061 .finishActivity(r.token, Activity.RESULT_CANCELED, null); 2062 } catch (RemoteException ex) { 2063 // Ignore 2064 } 2065 } 2066 } 2067 2068 private void deliverNewIntents(ActivityClientRecord r, 2069 List<Intent> intents) { 2070 final int N = intents.size(); 2071 for (int i=0; i<N; i++) { 2072 Intent intent = intents.get(i); 2073 intent.setExtrasClassLoader(r.activity.getClassLoader()); 2074 r.activity.mFragments.noteStateNotSaved(); 2075 mInstrumentation.callActivityOnNewIntent(r.activity, intent); 2076 } 2077 } 2078 2079 public final void performNewIntents(IBinder token, 2080 List<Intent> intents) { 2081 ActivityClientRecord r = mActivities.get(token); 2082 if (r != null) { 2083 final boolean resumed = !r.paused; 2084 if (resumed) { 2085 r.activity.mTemporaryPause = true; 2086 mInstrumentation.callActivityOnPause(r.activity); 2087 } 2088 deliverNewIntents(r, intents); 2089 if (resumed) { 2090 r.activity.performResume(); 2091 r.activity.mTemporaryPause = false; 2092 } 2093 } 2094 } 2095 2096 private void handleNewIntent(NewIntentData data) { 2097 performNewIntents(data.token, data.intents); 2098 } 2099 2100 private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>(); 2101 2102 /** 2103 * Return the Intent that's currently being handled by a 2104 * BroadcastReceiver on this thread, or null if none. 2105 * @hide 2106 */ 2107 public static Intent getIntentBeingBroadcast() { 2108 return sCurrentBroadcastIntent.get(); 2109 } 2110 2111 private void handleReceiver(ReceiverData data) { 2112 // If we are getting ready to gc after going to the background, well 2113 // we are back active so skip it. 2114 unscheduleGcIdler(); 2115 2116 String component = data.intent.getComponent().getClassName(); 2117 2118 LoadedApk packageInfo = getPackageInfoNoCheck( 2119 data.info.applicationInfo, data.compatInfo); 2120 2121 IActivityManager mgr = ActivityManagerNative.getDefault(); 2122 2123 BroadcastReceiver receiver; 2124 try { 2125 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2126 data.intent.setExtrasClassLoader(cl); 2127 data.setExtrasClassLoader(cl); 2128 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); 2129 } catch (Exception e) { 2130 if (DEBUG_BROADCAST) Slog.i(TAG, 2131 "Finishing failed broadcast to " + data.intent.getComponent()); 2132 data.sendFinished(mgr); 2133 throw new RuntimeException( 2134 "Unable to instantiate receiver " + component 2135 + ": " + e.toString(), e); 2136 } 2137 2138 try { 2139 Application app = packageInfo.makeApplication(false, mInstrumentation); 2140 2141 if (localLOGV) Slog.v( 2142 TAG, "Performing receive of " + data.intent 2143 + ": app=" + app 2144 + ", appName=" + app.getPackageName() 2145 + ", pkg=" + packageInfo.getPackageName() 2146 + ", comp=" + data.intent.getComponent().toShortString() 2147 + ", dir=" + packageInfo.getAppDir()); 2148 2149 ContextImpl context = (ContextImpl)app.getBaseContext(); 2150 sCurrentBroadcastIntent.set(data.intent); 2151 receiver.setPendingResult(data); 2152 receiver.onReceive(context.getReceiverRestrictedContext(), 2153 data.intent); 2154 } catch (Exception e) { 2155 if (DEBUG_BROADCAST) Slog.i(TAG, 2156 "Finishing failed broadcast to " + data.intent.getComponent()); 2157 data.sendFinished(mgr); 2158 if (!mInstrumentation.onException(receiver, e)) { 2159 throw new RuntimeException( 2160 "Unable to start receiver " + component 2161 + ": " + e.toString(), e); 2162 } 2163 } finally { 2164 sCurrentBroadcastIntent.set(null); 2165 } 2166 2167 if (receiver.getPendingResult() != null) { 2168 data.finish(); 2169 } 2170 } 2171 2172 // Instantiate a BackupAgent and tell it that it's alive 2173 private void handleCreateBackupAgent(CreateBackupAgentData data) { 2174 if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data); 2175 2176 // no longer idle; we have backup work to do 2177 unscheduleGcIdler(); 2178 2179 // instantiate the BackupAgent class named in the manifest 2180 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 2181 String packageName = packageInfo.mPackageName; 2182 if (mBackupAgents.get(packageName) != null) { 2183 Slog.d(TAG, "BackupAgent " + " for " + packageName 2184 + " already exists"); 2185 return; 2186 } 2187 2188 BackupAgent agent = null; 2189 String classname = data.appInfo.backupAgentName; 2190 2191 // full backup operation but no app-supplied agent? use the default implementation 2192 if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL 2193 || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) { 2194 classname = "android.app.backup.FullBackupAgent"; 2195 } 2196 2197 try { 2198 IBinder binder = null; 2199 try { 2200 if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname); 2201 2202 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2203 agent = (BackupAgent) cl.loadClass(classname).newInstance(); 2204 2205 // set up the agent's context 2206 ContextImpl context = new ContextImpl(); 2207 context.init(packageInfo, null, this); 2208 context.setOuterContext(agent); 2209 agent.attach(context); 2210 2211 agent.onCreate(); 2212 binder = agent.onBind(); 2213 mBackupAgents.put(packageName, agent); 2214 } catch (Exception e) { 2215 // If this is during restore, fail silently; otherwise go 2216 // ahead and let the user see the crash. 2217 Slog.e(TAG, "Agent threw during creation: " + e); 2218 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE 2219 && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) { 2220 throw e; 2221 } 2222 // falling through with 'binder' still null 2223 } 2224 2225 // tell the OS that we're live now 2226 try { 2227 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder); 2228 } catch (RemoteException e) { 2229 // nothing to do. 2230 } 2231 } catch (Exception e) { 2232 throw new RuntimeException("Unable to create BackupAgent " 2233 + classname + ": " + e.toString(), e); 2234 } 2235 } 2236 2237 // Tear down a BackupAgent 2238 private void handleDestroyBackupAgent(CreateBackupAgentData data) { 2239 if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data); 2240 2241 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 2242 String packageName = packageInfo.mPackageName; 2243 BackupAgent agent = mBackupAgents.get(packageName); 2244 if (agent != null) { 2245 try { 2246 agent.onDestroy(); 2247 } catch (Exception e) { 2248 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo); 2249 e.printStackTrace(); 2250 } 2251 mBackupAgents.remove(packageName); 2252 } else { 2253 Slog.w(TAG, "Attempt to destroy unknown backup agent " + data); 2254 } 2255 } 2256 2257 private void handleCreateService(CreateServiceData data) { 2258 // If we are getting ready to gc after going to the background, well 2259 // we are back active so skip it. 2260 unscheduleGcIdler(); 2261 2262 LoadedApk packageInfo = getPackageInfoNoCheck( 2263 data.info.applicationInfo, data.compatInfo); 2264 Service service = null; 2265 try { 2266 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2267 service = (Service) cl.loadClass(data.info.name).newInstance(); 2268 } catch (Exception e) { 2269 if (!mInstrumentation.onException(service, e)) { 2270 throw new RuntimeException( 2271 "Unable to instantiate service " + data.info.name 2272 + ": " + e.toString(), e); 2273 } 2274 } 2275 2276 try { 2277 if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); 2278 2279 ContextImpl context = new ContextImpl(); 2280 context.init(packageInfo, null, this); 2281 2282 Application app = packageInfo.makeApplication(false, mInstrumentation); 2283 context.setOuterContext(service); 2284 service.attach(context, this, data.info.name, data.token, app, 2285 ActivityManagerNative.getDefault()); 2286 service.onCreate(); 2287 mServices.put(data.token, service); 2288 try { 2289 ActivityManagerNative.getDefault().serviceDoneExecuting( 2290 data.token, 0, 0, 0); 2291 } catch (RemoteException e) { 2292 // nothing to do. 2293 } 2294 } catch (Exception e) { 2295 if (!mInstrumentation.onException(service, e)) { 2296 throw new RuntimeException( 2297 "Unable to create service " + data.info.name 2298 + ": " + e.toString(), e); 2299 } 2300 } 2301 } 2302 2303 private void handleBindService(BindServiceData data) { 2304 Service s = mServices.get(data.token); 2305 if (DEBUG_SERVICE) 2306 Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind); 2307 if (s != null) { 2308 try { 2309 data.intent.setExtrasClassLoader(s.getClassLoader()); 2310 try { 2311 if (!data.rebind) { 2312 IBinder binder = s.onBind(data.intent); 2313 ActivityManagerNative.getDefault().publishService( 2314 data.token, data.intent, binder); 2315 } else { 2316 s.onRebind(data.intent); 2317 ActivityManagerNative.getDefault().serviceDoneExecuting( 2318 data.token, 0, 0, 0); 2319 } 2320 ensureJitEnabled(); 2321 } catch (RemoteException ex) { 2322 } 2323 } catch (Exception e) { 2324 if (!mInstrumentation.onException(s, e)) { 2325 throw new RuntimeException( 2326 "Unable to bind to service " + s 2327 + " with " + data.intent + ": " + e.toString(), e); 2328 } 2329 } 2330 } 2331 } 2332 2333 private void handleUnbindService(BindServiceData data) { 2334 Service s = mServices.get(data.token); 2335 if (s != null) { 2336 try { 2337 data.intent.setExtrasClassLoader(s.getClassLoader()); 2338 boolean doRebind = s.onUnbind(data.intent); 2339 try { 2340 if (doRebind) { 2341 ActivityManagerNative.getDefault().unbindFinished( 2342 data.token, data.intent, doRebind); 2343 } else { 2344 ActivityManagerNative.getDefault().serviceDoneExecuting( 2345 data.token, 0, 0, 0); 2346 } 2347 } catch (RemoteException ex) { 2348 } 2349 } catch (Exception e) { 2350 if (!mInstrumentation.onException(s, e)) { 2351 throw new RuntimeException( 2352 "Unable to unbind to service " + s 2353 + " with " + data.intent + ": " + e.toString(), e); 2354 } 2355 } 2356 } 2357 } 2358 2359 private void handleDumpService(DumpComponentInfo info) { 2360 Service s = mServices.get(info.token); 2361 if (s != null) { 2362 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor())); 2363 s.dump(info.fd.getFileDescriptor(), pw, info.args); 2364 pw.flush(); 2365 try { 2366 info.fd.close(); 2367 } catch (IOException e) { 2368 } 2369 } 2370 } 2371 2372 private void handleDumpActivity(DumpComponentInfo info) { 2373 ActivityClientRecord r = mActivities.get(info.token); 2374 if (r != null && r.activity != null) { 2375 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor())); 2376 r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args); 2377 pw.flush(); 2378 try { 2379 info.fd.close(); 2380 } catch (IOException e) { 2381 } 2382 } 2383 } 2384 2385 private void handleDumpProvider(DumpComponentInfo info) { 2386 ProviderClientRecord r = mLocalProviders.get(info.token); 2387 if (r != null && r.mLocalProvider != null) { 2388 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor())); 2389 r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args); 2390 pw.flush(); 2391 try { 2392 info.fd.close(); 2393 } catch (IOException e) { 2394 } 2395 } 2396 } 2397 2398 private void handleServiceArgs(ServiceArgsData data) { 2399 Service s = mServices.get(data.token); 2400 if (s != null) { 2401 try { 2402 if (data.args != null) { 2403 data.args.setExtrasClassLoader(s.getClassLoader()); 2404 } 2405 int res; 2406 if (!data.taskRemoved) { 2407 res = s.onStartCommand(data.args, data.flags, data.startId); 2408 } else { 2409 s.onTaskRemoved(data.args); 2410 res = Service.START_TASK_REMOVED_COMPLETE; 2411 } 2412 2413 QueuedWork.waitToFinish(); 2414 2415 try { 2416 ActivityManagerNative.getDefault().serviceDoneExecuting( 2417 data.token, 1, data.startId, res); 2418 } catch (RemoteException e) { 2419 // nothing to do. 2420 } 2421 ensureJitEnabled(); 2422 } catch (Exception e) { 2423 if (!mInstrumentation.onException(s, e)) { 2424 throw new RuntimeException( 2425 "Unable to start service " + s 2426 + " with " + data.args + ": " + e.toString(), e); 2427 } 2428 } 2429 } 2430 } 2431 2432 private void handleStopService(IBinder token) { 2433 Service s = mServices.remove(token); 2434 if (s != null) { 2435 try { 2436 if (localLOGV) Slog.v(TAG, "Destroying service " + s); 2437 s.onDestroy(); 2438 Context context = s.getBaseContext(); 2439 if (context instanceof ContextImpl) { 2440 final String who = s.getClassName(); 2441 ((ContextImpl) context).scheduleFinalCleanup(who, "Service"); 2442 } 2443 2444 QueuedWork.waitToFinish(); 2445 2446 try { 2447 ActivityManagerNative.getDefault().serviceDoneExecuting( 2448 token, 0, 0, 0); 2449 } catch (RemoteException e) { 2450 // nothing to do. 2451 } 2452 } catch (Exception e) { 2453 if (!mInstrumentation.onException(s, e)) { 2454 throw new RuntimeException( 2455 "Unable to stop service " + s 2456 + ": " + e.toString(), e); 2457 } 2458 } 2459 } 2460 //Slog.i(TAG, "Running services: " + mServices); 2461 } 2462 2463 public final ActivityClientRecord performResumeActivity(IBinder token, 2464 boolean clearHide) { 2465 ActivityClientRecord r = mActivities.get(token); 2466 if (localLOGV) Slog.v(TAG, "Performing resume of " + r 2467 + " finished=" + r.activity.mFinished); 2468 if (r != null && !r.activity.mFinished) { 2469 if (clearHide) { 2470 r.hideForNow = false; 2471 r.activity.mStartedActivity = false; 2472 } 2473 try { 2474 if (r.pendingIntents != null) { 2475 deliverNewIntents(r, r.pendingIntents); 2476 r.pendingIntents = null; 2477 } 2478 if (r.pendingResults != null) { 2479 deliverResults(r, r.pendingResults); 2480 r.pendingResults = null; 2481 } 2482 r.activity.performResume(); 2483 2484 EventLog.writeEvent(LOG_ON_RESUME_CALLED, 2485 r.activity.getComponentName().getClassName()); 2486 2487 r.paused = false; 2488 r.stopped = false; 2489 r.state = null; 2490 } catch (Exception e) { 2491 if (!mInstrumentation.onException(r.activity, e)) { 2492 throw new RuntimeException( 2493 "Unable to resume activity " 2494 + r.intent.getComponent().toShortString() 2495 + ": " + e.toString(), e); 2496 } 2497 } 2498 } 2499 return r; 2500 } 2501 2502 final void cleanUpPendingRemoveWindows(ActivityClientRecord r) { 2503 if (r.mPendingRemoveWindow != null) { 2504 r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow); 2505 IBinder wtoken = r.mPendingRemoveWindow.getWindowToken(); 2506 if (wtoken != null) { 2507 WindowManagerImpl.getDefault().closeAll(wtoken, 2508 r.activity.getClass().getName(), "Activity"); 2509 } 2510 } 2511 r.mPendingRemoveWindow = null; 2512 r.mPendingRemoveWindowManager = null; 2513 } 2514 2515 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) { 2516 // If we are getting ready to gc after going to the background, well 2517 // we are back active so skip it. 2518 unscheduleGcIdler(); 2519 2520 ActivityClientRecord r = performResumeActivity(token, clearHide); 2521 2522 if (r != null) { 2523 final Activity a = r.activity; 2524 2525 if (localLOGV) Slog.v( 2526 TAG, "Resume " + r + " started activity: " + 2527 a.mStartedActivity + ", hideForNow: " + r.hideForNow 2528 + ", finished: " + a.mFinished); 2529 2530 final int forwardBit = isForward ? 2531 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0; 2532 2533 // If the window hasn't yet been added to the window manager, 2534 // and this guy didn't finish itself or start another activity, 2535 // then go ahead and add the window. 2536 boolean willBeVisible = !a.mStartedActivity; 2537 if (!willBeVisible) { 2538 try { 2539 willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible( 2540 a.getActivityToken()); 2541 } catch (RemoteException e) { 2542 } 2543 } 2544 if (r.window == null && !a.mFinished && willBeVisible) { 2545 r.window = r.activity.getWindow(); 2546 View decor = r.window.getDecorView(); 2547 decor.setVisibility(View.INVISIBLE); 2548 ViewManager wm = a.getWindowManager(); 2549 WindowManager.LayoutParams l = r.window.getAttributes(); 2550 a.mDecor = decor; 2551 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 2552 l.softInputMode |= forwardBit; 2553 if (a.mVisibleFromClient) { 2554 a.mWindowAdded = true; 2555 wm.addView(decor, l); 2556 } 2557 2558 // If the window has already been added, but during resume 2559 // we started another activity, then don't yet make the 2560 // window visible. 2561 } else if (!willBeVisible) { 2562 if (localLOGV) Slog.v( 2563 TAG, "Launch " + r + " mStartedActivity set"); 2564 r.hideForNow = true; 2565 } 2566 2567 // Get rid of anything left hanging around. 2568 cleanUpPendingRemoveWindows(r); 2569 2570 // The window is now visible if it has been added, we are not 2571 // simply finishing, and we are not starting another activity. 2572 if (!r.activity.mFinished && willBeVisible 2573 && r.activity.mDecor != null && !r.hideForNow) { 2574 if (r.newConfig != null) { 2575 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity " 2576 + r.activityInfo.name + " with newConfig " + r.newConfig); 2577 performConfigurationChanged(r.activity, r.newConfig); 2578 r.newConfig = null; 2579 } 2580 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" 2581 + isForward); 2582 WindowManager.LayoutParams l = r.window.getAttributes(); 2583 if ((l.softInputMode 2584 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) 2585 != forwardBit) { 2586 l.softInputMode = (l.softInputMode 2587 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)) 2588 | forwardBit; 2589 if (r.activity.mVisibleFromClient) { 2590 ViewManager wm = a.getWindowManager(); 2591 View decor = r.window.getDecorView(); 2592 wm.updateViewLayout(decor, l); 2593 } 2594 } 2595 r.activity.mVisibleFromServer = true; 2596 mNumVisibleActivities++; 2597 if (r.activity.mVisibleFromClient) { 2598 r.activity.makeVisible(); 2599 } 2600 } 2601 2602 if (!r.onlyLocalRequest) { 2603 r.nextIdle = mNewActivities; 2604 mNewActivities = r; 2605 if (localLOGV) Slog.v( 2606 TAG, "Scheduling idle handler for " + r); 2607 Looper.myQueue().addIdleHandler(new Idler()); 2608 } 2609 r.onlyLocalRequest = false; 2610 2611 } else { 2612 // If an exception was thrown when trying to resume, then 2613 // just end this activity. 2614 try { 2615 ActivityManagerNative.getDefault() 2616 .finishActivity(token, Activity.RESULT_CANCELED, null); 2617 } catch (RemoteException ex) { 2618 } 2619 } 2620 } 2621 2622 private int mThumbnailWidth = -1; 2623 private int mThumbnailHeight = -1; 2624 private Bitmap mAvailThumbnailBitmap = null; 2625 private Canvas mThumbnailCanvas = null; 2626 2627 private Bitmap createThumbnailBitmap(ActivityClientRecord r) { 2628 Bitmap thumbnail = mAvailThumbnailBitmap; 2629 try { 2630 if (thumbnail == null) { 2631 int w = mThumbnailWidth; 2632 int h; 2633 if (w < 0) { 2634 Resources res = r.activity.getResources(); 2635 mThumbnailHeight = h = 2636 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); 2637 2638 mThumbnailWidth = w = 2639 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); 2640 } else { 2641 h = mThumbnailHeight; 2642 } 2643 2644 // On platforms where we don't want thumbnails, set dims to (0,0) 2645 if ((w > 0) && (h > 0)) { 2646 thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT); 2647 thumbnail.eraseColor(0); 2648 } 2649 } 2650 2651 if (thumbnail != null) { 2652 Canvas cv = mThumbnailCanvas; 2653 if (cv == null) { 2654 mThumbnailCanvas = cv = new Canvas(); 2655 } 2656 2657 cv.setBitmap(thumbnail); 2658 if (!r.activity.onCreateThumbnail(thumbnail, cv)) { 2659 mAvailThumbnailBitmap = thumbnail; 2660 thumbnail = null; 2661 } 2662 cv.setBitmap(null); 2663 } 2664 2665 } catch (Exception e) { 2666 if (!mInstrumentation.onException(r.activity, e)) { 2667 throw new RuntimeException( 2668 "Unable to create thumbnail of " 2669 + r.intent.getComponent().toShortString() 2670 + ": " + e.toString(), e); 2671 } 2672 thumbnail = null; 2673 } 2674 2675 return thumbnail; 2676 } 2677 2678 private void handlePauseActivity(IBinder token, boolean finished, 2679 boolean userLeaving, int configChanges) { 2680 ActivityClientRecord r = mActivities.get(token); 2681 if (r != null) { 2682 //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); 2683 if (userLeaving) { 2684 performUserLeavingActivity(r); 2685 } 2686 2687 r.activity.mConfigChangeFlags |= configChanges; 2688 performPauseActivity(token, finished, r.isPreHoneycomb()); 2689 2690 // Make sure any pending writes are now committed. 2691 if (r.isPreHoneycomb()) { 2692 QueuedWork.waitToFinish(); 2693 } 2694 2695 // Tell the activity manager we have paused. 2696 try { 2697 ActivityManagerNative.getDefault().activityPaused(token); 2698 } catch (RemoteException ex) { 2699 } 2700 } 2701 } 2702 2703 final void performUserLeavingActivity(ActivityClientRecord r) { 2704 mInstrumentation.callActivityOnUserLeaving(r.activity); 2705 } 2706 2707 final Bundle performPauseActivity(IBinder token, boolean finished, 2708 boolean saveState) { 2709 ActivityClientRecord r = mActivities.get(token); 2710 return r != null ? performPauseActivity(r, finished, saveState) : null; 2711 } 2712 2713 final Bundle performPauseActivity(ActivityClientRecord r, boolean finished, 2714 boolean saveState) { 2715 if (r.paused) { 2716 if (r.activity.mFinished) { 2717 // If we are finishing, we won't call onResume() in certain cases. 2718 // So here we likewise don't want to call onPause() if the activity 2719 // isn't resumed. 2720 return null; 2721 } 2722 RuntimeException e = new RuntimeException( 2723 "Performing pause of activity that is not resumed: " 2724 + r.intent.getComponent().toShortString()); 2725 Slog.e(TAG, e.getMessage(), e); 2726 } 2727 Bundle state = null; 2728 if (finished) { 2729 r.activity.mFinished = true; 2730 } 2731 try { 2732 // Next have the activity save its current state and managed dialogs... 2733 if (!r.activity.mFinished && saveState) { 2734 state = new Bundle(); 2735 state.setAllowFds(false); 2736 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); 2737 r.state = state; 2738 } 2739 // Now we are idle. 2740 r.activity.mCalled = false; 2741 mInstrumentation.callActivityOnPause(r.activity); 2742 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName()); 2743 if (!r.activity.mCalled) { 2744 throw new SuperNotCalledException( 2745 "Activity " + r.intent.getComponent().toShortString() + 2746 " did not call through to super.onPause()"); 2747 } 2748 2749 } catch (SuperNotCalledException e) { 2750 throw e; 2751 2752 } catch (Exception e) { 2753 if (!mInstrumentation.onException(r.activity, e)) { 2754 throw new RuntimeException( 2755 "Unable to pause activity " 2756 + r.intent.getComponent().toShortString() 2757 + ": " + e.toString(), e); 2758 } 2759 } 2760 r.paused = true; 2761 2762 // Notify any outstanding on paused listeners 2763 ArrayList<OnActivityPausedListener> listeners; 2764 synchronized (mOnPauseListeners) { 2765 listeners = mOnPauseListeners.remove(r.activity); 2766 } 2767 int size = (listeners != null ? listeners.size() : 0); 2768 for (int i = 0; i < size; i++) { 2769 listeners.get(i).onPaused(r.activity); 2770 } 2771 2772 return state; 2773 } 2774 2775 final void performStopActivity(IBinder token, boolean saveState) { 2776 ActivityClientRecord r = mActivities.get(token); 2777 performStopActivityInner(r, null, false, saveState); 2778 } 2779 2780 private static class StopInfo { 2781 Bitmap thumbnail; 2782 CharSequence description; 2783 } 2784 2785 private static final class ProviderRefCount { 2786 public int count; 2787 2788 ProviderRefCount(int pCount) { 2789 count = pCount; 2790 } 2791 } 2792 2793 /** 2794 * Core implementation of stopping an activity. Note this is a little 2795 * tricky because the server's meaning of stop is slightly different 2796 * than our client -- for the server, stop means to save state and give 2797 * it the result when it is done, but the window may still be visible. 2798 * For the client, we want to call onStop()/onStart() to indicate when 2799 * the activity's UI visibillity changes. 2800 */ 2801 private void performStopActivityInner(ActivityClientRecord r, 2802 StopInfo info, boolean keepShown, boolean saveState) { 2803 if (localLOGV) Slog.v(TAG, "Performing stop of " + r); 2804 Bundle state = null; 2805 if (r != null) { 2806 if (!keepShown && r.stopped) { 2807 if (r.activity.mFinished) { 2808 // If we are finishing, we won't call onResume() in certain 2809 // cases. So here we likewise don't want to call onStop() 2810 // if the activity isn't resumed. 2811 return; 2812 } 2813 RuntimeException e = new RuntimeException( 2814 "Performing stop of activity that is not resumed: " 2815 + r.intent.getComponent().toShortString()); 2816 Slog.e(TAG, e.getMessage(), e); 2817 } 2818 2819 if (info != null) { 2820 try { 2821 // First create a thumbnail for the activity... 2822 // For now, don't create the thumbnail here; we are 2823 // doing that by doing a screen snapshot. 2824 info.thumbnail = null; //createThumbnailBitmap(r); 2825 info.description = r.activity.onCreateDescription(); 2826 } catch (Exception e) { 2827 if (!mInstrumentation.onException(r.activity, e)) { 2828 throw new RuntimeException( 2829 "Unable to save state of activity " 2830 + r.intent.getComponent().toShortString() 2831 + ": " + e.toString(), e); 2832 } 2833 } 2834 } 2835 2836 // Next have the activity save its current state and managed dialogs... 2837 if (!r.activity.mFinished && saveState) { 2838 if (r.state == null) { 2839 state = new Bundle(); 2840 state.setAllowFds(false); 2841 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); 2842 r.state = state; 2843 } else { 2844 state = r.state; 2845 } 2846 } 2847 2848 if (!keepShown) { 2849 try { 2850 // Now we are idle. 2851 r.activity.performStop(); 2852 } catch (Exception e) { 2853 if (!mInstrumentation.onException(r.activity, e)) { 2854 throw new RuntimeException( 2855 "Unable to stop activity " 2856 + r.intent.getComponent().toShortString() 2857 + ": " + e.toString(), e); 2858 } 2859 } 2860 r.stopped = true; 2861 } 2862 2863 r.paused = true; 2864 } 2865 } 2866 2867 private void updateVisibility(ActivityClientRecord r, boolean show) { 2868 View v = r.activity.mDecor; 2869 if (v != null) { 2870 if (show) { 2871 if (!r.activity.mVisibleFromServer) { 2872 r.activity.mVisibleFromServer = true; 2873 mNumVisibleActivities++; 2874 if (r.activity.mVisibleFromClient) { 2875 r.activity.makeVisible(); 2876 } 2877 } 2878 if (r.newConfig != null) { 2879 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis " 2880 + r.activityInfo.name + " with new config " + r.newConfig); 2881 performConfigurationChanged(r.activity, r.newConfig); 2882 r.newConfig = null; 2883 } 2884 } else { 2885 if (r.activity.mVisibleFromServer) { 2886 r.activity.mVisibleFromServer = false; 2887 mNumVisibleActivities--; 2888 v.setVisibility(View.INVISIBLE); 2889 } 2890 } 2891 } 2892 } 2893 2894 private void handleStopActivity(IBinder token, boolean show, int configChanges) { 2895 ActivityClientRecord r = mActivities.get(token); 2896 r.activity.mConfigChangeFlags |= configChanges; 2897 2898 StopInfo info = new StopInfo(); 2899 performStopActivityInner(r, info, show, true); 2900 2901 if (localLOGV) Slog.v( 2902 TAG, "Finishing stop of " + r + ": show=" + show 2903 + " win=" + r.window); 2904 2905 updateVisibility(r, show); 2906 2907 // Make sure any pending writes are now committed. 2908 if (!r.isPreHoneycomb()) { 2909 QueuedWork.waitToFinish(); 2910 } 2911 2912 // Tell activity manager we have been stopped. 2913 try { 2914 ActivityManagerNative.getDefault().activityStopped( 2915 r.token, r.state, info.thumbnail, info.description); 2916 } catch (RemoteException ex) { 2917 } 2918 } 2919 2920 final void performRestartActivity(IBinder token) { 2921 ActivityClientRecord r = mActivities.get(token); 2922 if (r.stopped) { 2923 r.activity.performRestart(); 2924 r.stopped = false; 2925 } 2926 } 2927 2928 private void handleWindowVisibility(IBinder token, boolean show) { 2929 ActivityClientRecord r = mActivities.get(token); 2930 2931 if (r == null) { 2932 Log.w(TAG, "handleWindowVisibility: no activity for token " + token); 2933 return; 2934 } 2935 2936 if (!show && !r.stopped) { 2937 performStopActivityInner(r, null, show, false); 2938 } else if (show && r.stopped) { 2939 // If we are getting ready to gc after going to the background, well 2940 // we are back active so skip it. 2941 unscheduleGcIdler(); 2942 2943 r.activity.performRestart(); 2944 r.stopped = false; 2945 } 2946 if (r.activity.mDecor != null) { 2947 if (false) Slog.v( 2948 TAG, "Handle window " + r + " visibility: " + show); 2949 updateVisibility(r, show); 2950 } 2951 } 2952 2953 private void handleSleeping(IBinder token, boolean sleeping) { 2954 ActivityClientRecord r = mActivities.get(token); 2955 2956 if (r == null) { 2957 Log.w(TAG, "handleSleeping: no activity for token " + token); 2958 return; 2959 } 2960 2961 if (sleeping) { 2962 if (!r.stopped && !r.isPreHoneycomb()) { 2963 try { 2964 // Now we are idle. 2965 r.activity.performStop(); 2966 } catch (Exception e) { 2967 if (!mInstrumentation.onException(r.activity, e)) { 2968 throw new RuntimeException( 2969 "Unable to stop activity " 2970 + r.intent.getComponent().toShortString() 2971 + ": " + e.toString(), e); 2972 } 2973 } 2974 r.stopped = true; 2975 } 2976 2977 // Make sure any pending writes are now committed. 2978 if (!r.isPreHoneycomb()) { 2979 QueuedWork.waitToFinish(); 2980 } 2981 2982 // Tell activity manager we slept. 2983 try { 2984 ActivityManagerNative.getDefault().activitySlept(r.token); 2985 } catch (RemoteException ex) { 2986 } 2987 } else { 2988 if (r.stopped && r.activity.mVisibleFromServer) { 2989 r.activity.performRestart(); 2990 r.stopped = false; 2991 } 2992 } 2993 } 2994 2995 private void handleSetCoreSettings(Bundle coreSettings) { 2996 synchronized (mPackages) { 2997 mCoreSettings = coreSettings; 2998 } 2999 } 3000 3001 private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) { 3002 LoadedApk apk = peekPackageInfo(data.pkg, false); 3003 if (apk != null) { 3004 apk.mCompatibilityInfo.set(data.info); 3005 } 3006 apk = peekPackageInfo(data.pkg, true); 3007 if (apk != null) { 3008 apk.mCompatibilityInfo.set(data.info); 3009 } 3010 handleConfigurationChanged(mConfiguration, data.info); 3011 WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration); 3012 } 3013 3014 private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) { 3015 final int N = results.size(); 3016 for (int i=0; i<N; i++) { 3017 ResultInfo ri = results.get(i); 3018 try { 3019 if (ri.mData != null) { 3020 ri.mData.setExtrasClassLoader(r.activity.getClassLoader()); 3021 } 3022 if (DEBUG_RESULTS) Slog.v(TAG, 3023 "Delivering result to activity " + r + " : " + ri); 3024 r.activity.dispatchActivityResult(ri.mResultWho, 3025 ri.mRequestCode, ri.mResultCode, ri.mData); 3026 } catch (Exception e) { 3027 if (!mInstrumentation.onException(r.activity, e)) { 3028 throw new RuntimeException( 3029 "Failure delivering result " + ri + " to activity " 3030 + r.intent.getComponent().toShortString() 3031 + ": " + e.toString(), e); 3032 } 3033 } 3034 } 3035 } 3036 3037 private void handleSendResult(ResultData res) { 3038 ActivityClientRecord r = mActivities.get(res.token); 3039 if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r); 3040 if (r != null) { 3041 final boolean resumed = !r.paused; 3042 if (!r.activity.mFinished && r.activity.mDecor != null 3043 && r.hideForNow && resumed) { 3044 // We had hidden the activity because it started another 3045 // one... we have gotten a result back and we are not 3046 // paused, so make sure our window is visible. 3047 updateVisibility(r, true); 3048 } 3049 if (resumed) { 3050 try { 3051 // Now we are idle. 3052 r.activity.mCalled = false; 3053 r.activity.mTemporaryPause = true; 3054 mInstrumentation.callActivityOnPause(r.activity); 3055 if (!r.activity.mCalled) { 3056 throw new SuperNotCalledException( 3057 "Activity " + r.intent.getComponent().toShortString() 3058 + " did not call through to super.onPause()"); 3059 } 3060 } catch (SuperNotCalledException e) { 3061 throw e; 3062 } catch (Exception e) { 3063 if (!mInstrumentation.onException(r.activity, e)) { 3064 throw new RuntimeException( 3065 "Unable to pause activity " 3066 + r.intent.getComponent().toShortString() 3067 + ": " + e.toString(), e); 3068 } 3069 } 3070 } 3071 deliverResults(r, res.results); 3072 if (resumed) { 3073 r.activity.performResume(); 3074 r.activity.mTemporaryPause = false; 3075 } 3076 } 3077 } 3078 3079 public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) { 3080 return performDestroyActivity(token, finishing, 0, false); 3081 } 3082 3083 private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, 3084 int configChanges, boolean getNonConfigInstance) { 3085 ActivityClientRecord r = mActivities.get(token); 3086 Class activityClass = null; 3087 if (localLOGV) Slog.v(TAG, "Performing finish of " + r); 3088 if (r != null) { 3089 activityClass = r.activity.getClass(); 3090 r.activity.mConfigChangeFlags |= configChanges; 3091 if (finishing) { 3092 r.activity.mFinished = true; 3093 } 3094 if (!r.paused) { 3095 try { 3096 r.activity.mCalled = false; 3097 mInstrumentation.callActivityOnPause(r.activity); 3098 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, 3099 r.activity.getComponentName().getClassName()); 3100 if (!r.activity.mCalled) { 3101 throw new SuperNotCalledException( 3102 "Activity " + safeToComponentShortString(r.intent) 3103 + " did not call through to super.onPause()"); 3104 } 3105 } catch (SuperNotCalledException e) { 3106 throw e; 3107 } catch (Exception e) { 3108 if (!mInstrumentation.onException(r.activity, e)) { 3109 throw new RuntimeException( 3110 "Unable to pause activity " 3111 + safeToComponentShortString(r.intent) 3112 + ": " + e.toString(), e); 3113 } 3114 } 3115 r.paused = true; 3116 } 3117 if (!r.stopped) { 3118 try { 3119 r.activity.performStop(); 3120 } catch (SuperNotCalledException e) { 3121 throw e; 3122 } catch (Exception e) { 3123 if (!mInstrumentation.onException(r.activity, e)) { 3124 throw new RuntimeException( 3125 "Unable to stop activity " 3126 + safeToComponentShortString(r.intent) 3127 + ": " + e.toString(), e); 3128 } 3129 } 3130 r.stopped = true; 3131 } 3132 if (getNonConfigInstance) { 3133 try { 3134 r.lastNonConfigurationInstances 3135 = r.activity.retainNonConfigurationInstances(); 3136 } catch (Exception e) { 3137 if (!mInstrumentation.onException(r.activity, e)) { 3138 throw new RuntimeException( 3139 "Unable to retain activity " 3140 + r.intent.getComponent().toShortString() 3141 + ": " + e.toString(), e); 3142 } 3143 } 3144 } 3145 try { 3146 r.activity.mCalled = false; 3147 mInstrumentation.callActivityOnDestroy(r.activity); 3148 if (!r.activity.mCalled) { 3149 throw new SuperNotCalledException( 3150 "Activity " + safeToComponentShortString(r.intent) + 3151 " did not call through to super.onDestroy()"); 3152 } 3153 if (r.window != null) { 3154 r.window.closeAllPanels(); 3155 } 3156 } catch (SuperNotCalledException e) { 3157 throw e; 3158 } catch (Exception e) { 3159 if (!mInstrumentation.onException(r.activity, e)) { 3160 throw new RuntimeException( 3161 "Unable to destroy activity " + safeToComponentShortString(r.intent) 3162 + ": " + e.toString(), e); 3163 } 3164 } 3165 } 3166 mActivities.remove(token); 3167 StrictMode.decrementExpectedActivityCount(activityClass); 3168 return r; 3169 } 3170 3171 private static String safeToComponentShortString(Intent intent) { 3172 ComponentName component = intent.getComponent(); 3173 return component == null ? "[Unknown]" : component.toShortString(); 3174 } 3175 3176 private void handleDestroyActivity(IBinder token, boolean finishing, 3177 int configChanges, boolean getNonConfigInstance) { 3178 ActivityClientRecord r = performDestroyActivity(token, finishing, 3179 configChanges, getNonConfigInstance); 3180 if (r != null) { 3181 cleanUpPendingRemoveWindows(r); 3182 WindowManager wm = r.activity.getWindowManager(); 3183 View v = r.activity.mDecor; 3184 if (v != null) { 3185 if (r.activity.mVisibleFromServer) { 3186 mNumVisibleActivities--; 3187 } 3188 IBinder wtoken = v.getWindowToken(); 3189 if (r.activity.mWindowAdded) { 3190 if (r.onlyLocalRequest) { 3191 // Hold off on removing this until the new activity's 3192 // window is being added. 3193 r.mPendingRemoveWindow = v; 3194 r.mPendingRemoveWindowManager = wm; 3195 } else { 3196 wm.removeViewImmediate(v); 3197 } 3198 } 3199 if (wtoken != null && r.mPendingRemoveWindow == null) { 3200 WindowManagerImpl.getDefault().closeAll(wtoken, 3201 r.activity.getClass().getName(), "Activity"); 3202 } 3203 r.activity.mDecor = null; 3204 } 3205 if (r.mPendingRemoveWindow == null) { 3206 // If we are delaying the removal of the activity window, then 3207 // we can't clean up all windows here. Note that we can't do 3208 // so later either, which means any windows that aren't closed 3209 // by the app will leak. Well we try to warning them a lot 3210 // about leaking windows, because that is a bug, so if they are 3211 // using this recreate facility then they get to live with leaks. 3212 WindowManagerImpl.getDefault().closeAll(token, 3213 r.activity.getClass().getName(), "Activity"); 3214 } 3215 3216 // Mocked out contexts won't be participating in the normal 3217 // process lifecycle, but if we're running with a proper 3218 // ApplicationContext we need to have it tear down things 3219 // cleanly. 3220 Context c = r.activity.getBaseContext(); 3221 if (c instanceof ContextImpl) { 3222 ((ContextImpl) c).scheduleFinalCleanup( 3223 r.activity.getClass().getName(), "Activity"); 3224 } 3225 } 3226 if (finishing) { 3227 try { 3228 ActivityManagerNative.getDefault().activityDestroyed(token); 3229 } catch (RemoteException ex) { 3230 // If the system process has died, it's game over for everyone. 3231 } 3232 } 3233 } 3234 3235 public final void requestRelaunchActivity(IBinder token, 3236 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, 3237 int configChanges, boolean notResumed, Configuration config, 3238 boolean fromServer) { 3239 ActivityClientRecord target = null; 3240 3241 synchronized (mPackages) { 3242 for (int i=0; i<mRelaunchingActivities.size(); i++) { 3243 ActivityClientRecord r = mRelaunchingActivities.get(i); 3244 if (r.token == token) { 3245 target = r; 3246 if (pendingResults != null) { 3247 if (r.pendingResults != null) { 3248 r.pendingResults.addAll(pendingResults); 3249 } else { 3250 r.pendingResults = pendingResults; 3251 } 3252 } 3253 if (pendingNewIntents != null) { 3254 if (r.pendingIntents != null) { 3255 r.pendingIntents.addAll(pendingNewIntents); 3256 } else { 3257 r.pendingIntents = pendingNewIntents; 3258 } 3259 } 3260 break; 3261 } 3262 } 3263 3264 if (target == null) { 3265 target = new ActivityClientRecord(); 3266 target.token = token; 3267 target.pendingResults = pendingResults; 3268 target.pendingIntents = pendingNewIntents; 3269 if (!fromServer) { 3270 ActivityClientRecord existing = mActivities.get(token); 3271 if (existing != null) { 3272 target.startsNotResumed = existing.paused; 3273 } 3274 target.onlyLocalRequest = true; 3275 } 3276 mRelaunchingActivities.add(target); 3277 queueOrSendMessage(H.RELAUNCH_ACTIVITY, target); 3278 } 3279 3280 if (fromServer) { 3281 target.startsNotResumed = notResumed; 3282 target.onlyLocalRequest = false; 3283 } 3284 if (config != null) { 3285 target.createdConfig = config; 3286 } 3287 target.pendingConfigChanges |= configChanges; 3288 } 3289 } 3290 3291 private void handleRelaunchActivity(ActivityClientRecord tmp) { 3292 // If we are getting ready to gc after going to the background, well 3293 // we are back active so skip it. 3294 unscheduleGcIdler(); 3295 3296 Configuration changedConfig = null; 3297 int configChanges = 0; 3298 3299 // First: make sure we have the most recent configuration and most 3300 // recent version of the activity, or skip it if some previous call 3301 // had taken a more recent version. 3302 synchronized (mPackages) { 3303 int N = mRelaunchingActivities.size(); 3304 IBinder token = tmp.token; 3305 tmp = null; 3306 for (int i=0; i<N; i++) { 3307 ActivityClientRecord r = mRelaunchingActivities.get(i); 3308 if (r.token == token) { 3309 tmp = r; 3310 configChanges |= tmp.pendingConfigChanges; 3311 mRelaunchingActivities.remove(i); 3312 i--; 3313 N--; 3314 } 3315 } 3316 3317 if (tmp == null) { 3318 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!"); 3319 return; 3320 } 3321 3322 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity " 3323 + tmp.token + " with configChanges=0x" 3324 + Integer.toHexString(configChanges)); 3325 3326 if (mPendingConfiguration != null) { 3327 changedConfig = mPendingConfiguration; 3328 mPendingConfiguration = null; 3329 } 3330 } 3331 3332 if (tmp.createdConfig != null) { 3333 // If the activity manager is passing us its current config, 3334 // assume that is really what we want regardless of what we 3335 // may have pending. 3336 if (mConfiguration == null 3337 || (tmp.createdConfig.isOtherSeqNewer(mConfiguration) 3338 && mConfiguration.diff(tmp.createdConfig) != 0)) { 3339 if (changedConfig == null 3340 || tmp.createdConfig.isOtherSeqNewer(changedConfig)) { 3341 changedConfig = tmp.createdConfig; 3342 } 3343 } 3344 } 3345 3346 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity " 3347 + tmp.token + ": changedConfig=" + changedConfig); 3348 3349 // If there was a pending configuration change, execute it first. 3350 if (changedConfig != null) { 3351 handleConfigurationChanged(changedConfig, null); 3352 } 3353 3354 ActivityClientRecord r = mActivities.get(tmp.token); 3355 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r); 3356 if (r == null) { 3357 return; 3358 } 3359 3360 r.activity.mConfigChangeFlags |= configChanges; 3361 r.onlyLocalRequest = tmp.onlyLocalRequest; 3362 Intent currentIntent = r.activity.mIntent; 3363 3364 r.activity.mChangingConfigurations = true; 3365 3366 // Need to ensure state is saved. 3367 if (!r.paused) { 3368 performPauseActivity(r.token, false, r.isPreHoneycomb()); 3369 } 3370 if (r.state == null && !r.stopped && !r.isPreHoneycomb()) { 3371 r.state = new Bundle(); 3372 r.state.setAllowFds(false); 3373 mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state); 3374 } 3375 3376 handleDestroyActivity(r.token, false, configChanges, true); 3377 3378 r.activity = null; 3379 r.window = null; 3380 r.hideForNow = false; 3381 r.nextIdle = null; 3382 // Merge any pending results and pending intents; don't just replace them 3383 if (tmp.pendingResults != null) { 3384 if (r.pendingResults == null) { 3385 r.pendingResults = tmp.pendingResults; 3386 } else { 3387 r.pendingResults.addAll(tmp.pendingResults); 3388 } 3389 } 3390 if (tmp.pendingIntents != null) { 3391 if (r.pendingIntents == null) { 3392 r.pendingIntents = tmp.pendingIntents; 3393 } else { 3394 r.pendingIntents.addAll(tmp.pendingIntents); 3395 } 3396 } 3397 r.startsNotResumed = tmp.startsNotResumed; 3398 3399 handleLaunchActivity(r, currentIntent); 3400 } 3401 3402 private void handleRequestThumbnail(IBinder token) { 3403 ActivityClientRecord r = mActivities.get(token); 3404 Bitmap thumbnail = createThumbnailBitmap(r); 3405 CharSequence description = null; 3406 try { 3407 description = r.activity.onCreateDescription(); 3408 } catch (Exception e) { 3409 if (!mInstrumentation.onException(r.activity, e)) { 3410 throw new RuntimeException( 3411 "Unable to create description of activity " 3412 + r.intent.getComponent().toShortString() 3413 + ": " + e.toString(), e); 3414 } 3415 } 3416 //System.out.println("Reporting top thumbnail " + thumbnail); 3417 try { 3418 ActivityManagerNative.getDefault().reportThumbnail( 3419 token, thumbnail, description); 3420 } catch (RemoteException ex) { 3421 } 3422 } 3423 3424 ArrayList<ComponentCallbacks2> collectComponentCallbacksLocked( 3425 boolean allActivities, Configuration newConfig) { 3426 ArrayList<ComponentCallbacks2> callbacks 3427 = new ArrayList<ComponentCallbacks2>(); 3428 3429 if (mActivities.size() > 0) { 3430 Iterator<ActivityClientRecord> it = mActivities.values().iterator(); 3431 while (it.hasNext()) { 3432 ActivityClientRecord ar = it.next(); 3433 Activity a = ar.activity; 3434 if (a != null) { 3435 Configuration thisConfig = applyConfigCompatMainThread(newConfig, 3436 ar.packageInfo.mCompatibilityInfo.getIfNeeded()); 3437 if (!ar.activity.mFinished && (allActivities || 3438 (a != null && !ar.paused))) { 3439 // If the activity is currently resumed, its configuration 3440 // needs to change right now. 3441 callbacks.add(a); 3442 } else if (thisConfig != null) { 3443 // Otherwise, we will tell it about the change 3444 // the next time it is resumed or shown. Note that 3445 // the activity manager may, before then, decide the 3446 // activity needs to be destroyed to handle its new 3447 // configuration. 3448 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity " 3449 + ar.activityInfo.name + " newConfig=" + thisConfig); 3450 ar.newConfig = thisConfig; 3451 } 3452 } 3453 } 3454 } 3455 if (mServices.size() > 0) { 3456 Iterator<Service> it = mServices.values().iterator(); 3457 while (it.hasNext()) { 3458 callbacks.add(it.next()); 3459 } 3460 } 3461 synchronized (mProviderMap) { 3462 if (mLocalProviders.size() > 0) { 3463 Iterator<ProviderClientRecord> it = mLocalProviders.values().iterator(); 3464 while (it.hasNext()) { 3465 callbacks.add(it.next().mLocalProvider); 3466 } 3467 } 3468 } 3469 final int N = mAllApplications.size(); 3470 for (int i=0; i<N; i++) { 3471 callbacks.add(mAllApplications.get(i)); 3472 } 3473 3474 return callbacks; 3475 } 3476 3477 private final void performConfigurationChanged( 3478 ComponentCallbacks2 cb, Configuration config) { 3479 // Only for Activity objects, check that they actually call up to their 3480 // superclass implementation. ComponentCallbacks2 is an interface, so 3481 // we check the runtime type and act accordingly. 3482 Activity activity = (cb instanceof Activity) ? (Activity) cb : null; 3483 if (activity != null) { 3484 activity.mCalled = false; 3485 } 3486 3487 boolean shouldChangeConfig = false; 3488 if ((activity == null) || (activity.mCurrentConfig == null)) { 3489 shouldChangeConfig = true; 3490 } else { 3491 3492 // If the new config is the same as the config this Activity 3493 // is already running with then don't bother calling 3494 // onConfigurationChanged 3495 int diff = activity.mCurrentConfig.diff(config); 3496 if (diff != 0) { 3497 // If this activity doesn't handle any of the config changes 3498 // then don't bother calling onConfigurationChanged as we're 3499 // going to destroy it. 3500 if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) { 3501 shouldChangeConfig = true; 3502 } 3503 } 3504 } 3505 3506 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb 3507 + ": shouldChangeConfig=" + shouldChangeConfig); 3508 if (shouldChangeConfig) { 3509 cb.onConfigurationChanged(config); 3510 3511 if (activity != null) { 3512 if (!activity.mCalled) { 3513 throw new SuperNotCalledException( 3514 "Activity " + activity.getLocalClassName() + 3515 " did not call through to super.onConfigurationChanged()"); 3516 } 3517 activity.mConfigChangeFlags = 0; 3518 activity.mCurrentConfig = new Configuration(config); 3519 } 3520 } 3521 } 3522 3523 public final void applyConfigurationToResources(Configuration config) { 3524 synchronized (mPackages) { 3525 applyConfigurationToResourcesLocked(config, null); 3526 } 3527 } 3528 3529 final boolean applyConfigurationToResourcesLocked(Configuration config, 3530 CompatibilityInfo compat) { 3531 if (mResConfiguration == null) { 3532 mResConfiguration = new Configuration(); 3533 } 3534 if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) { 3535 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq=" 3536 + mResConfiguration.seq + ", newSeq=" + config.seq); 3537 return false; 3538 } 3539 int changes = mResConfiguration.updateFrom(config); 3540 DisplayMetrics dm = getDisplayMetricsLocked(null, true); 3541 3542 if (compat != null && (mResCompatibilityInfo == null || 3543 !mResCompatibilityInfo.equals(compat))) { 3544 mResCompatibilityInfo = compat; 3545 changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT 3546 | ActivityInfo.CONFIG_SCREEN_SIZE 3547 | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 3548 } 3549 3550 // set it for java, this also affects newly created Resources 3551 if (config.locale != null) { 3552 Locale.setDefault(config.locale); 3553 } 3554 3555 Resources.updateSystemConfiguration(config, dm, compat); 3556 3557 ApplicationPackageManager.configurationChanged(); 3558 //Slog.i(TAG, "Configuration changed in " + currentPackageName()); 3559 3560 Iterator<WeakReference<Resources>> it = 3561 mActiveResources.values().iterator(); 3562 //Iterator<Map.Entry<String, WeakReference<Resources>>> it = 3563 // mActiveResources.entrySet().iterator(); 3564 while (it.hasNext()) { 3565 WeakReference<Resources> v = it.next(); 3566 Resources r = v.get(); 3567 if (r != null) { 3568 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources " 3569 + r + " config to: " + config); 3570 r.updateConfiguration(config, dm, compat); 3571 //Slog.i(TAG, "Updated app resources " + v.getKey() 3572 // + " " + r + ": " + r.getConfiguration()); 3573 } else { 3574 //Slog.i(TAG, "Removing old resources " + v.getKey()); 3575 it.remove(); 3576 } 3577 } 3578 3579 return changes != 0; 3580 } 3581 3582 final Configuration applyCompatConfiguration() { 3583 Configuration config = mConfiguration; 3584 if (mCompatConfiguration == null) { 3585 mCompatConfiguration = new Configuration(); 3586 } 3587 mCompatConfiguration.setTo(mConfiguration); 3588 if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) { 3589 mResCompatibilityInfo.applyToConfiguration(mCompatConfiguration); 3590 config = mCompatConfiguration; 3591 } 3592 return config; 3593 } 3594 3595 final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) { 3596 3597 ArrayList<ComponentCallbacks2> callbacks = null; 3598 3599 synchronized (mPackages) { 3600 if (mPendingConfiguration != null) { 3601 if (!mPendingConfiguration.isOtherSeqNewer(config)) { 3602 config = mPendingConfiguration; 3603 } 3604 mPendingConfiguration = null; 3605 } 3606 3607 if (config == null) { 3608 return; 3609 } 3610 3611 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: " 3612 + config); 3613 3614 applyConfigurationToResourcesLocked(config, compat); 3615 3616 if (mConfiguration == null) { 3617 mConfiguration = new Configuration(); 3618 } 3619 if (!mConfiguration.isOtherSeqNewer(config) && compat == null) { 3620 return; 3621 } 3622 mConfiguration.updateFrom(config); 3623 config = applyCompatConfiguration(); 3624 callbacks = collectComponentCallbacksLocked(false, config); 3625 } 3626 3627 // Cleanup hardware accelerated stuff 3628 WindowManagerImpl.getDefault().trimLocalMemory(); 3629 3630 if (callbacks != null) { 3631 final int N = callbacks.size(); 3632 for (int i=0; i<N; i++) { 3633 performConfigurationChanged(callbacks.get(i), config); 3634 } 3635 } 3636 } 3637 3638 final void handleActivityConfigurationChanged(IBinder token) { 3639 ActivityClientRecord r = mActivities.get(token); 3640 if (r == null || r.activity == null) { 3641 return; 3642 } 3643 3644 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: " 3645 + r.activityInfo.name); 3646 3647 performConfigurationChanged(r.activity, mCompatConfiguration); 3648 } 3649 3650 final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) { 3651 if (start) { 3652 try { 3653 switch (profileType) { 3654 case 1: 3655 ViewDebug.startLooperProfiling(pcd.path, pcd.fd.getFileDescriptor()); 3656 break; 3657 default: 3658 mProfiler.setProfiler(pcd.path, pcd.fd); 3659 mProfiler.autoStopProfiler = false; 3660 mProfiler.startProfiling(); 3661 break; 3662 } 3663 } catch (RuntimeException e) { 3664 Slog.w(TAG, "Profiling failed on path " + pcd.path 3665 + " -- can the process access this path?"); 3666 } finally { 3667 try { 3668 pcd.fd.close(); 3669 } catch (IOException e) { 3670 Slog.w(TAG, "Failure closing profile fd", e); 3671 } 3672 } 3673 } else { 3674 switch (profileType) { 3675 case 1: 3676 ViewDebug.stopLooperProfiling(); 3677 break; 3678 default: 3679 mProfiler.stopProfiling(); 3680 break; 3681 } 3682 } 3683 } 3684 3685 final void handleDumpHeap(boolean managed, DumpHeapData dhd) { 3686 if (managed) { 3687 try { 3688 Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor()); 3689 } catch (IOException e) { 3690 Slog.w(TAG, "Managed heap dump failed on path " + dhd.path 3691 + " -- can the process access this path?"); 3692 } finally { 3693 try { 3694 dhd.fd.close(); 3695 } catch (IOException e) { 3696 Slog.w(TAG, "Failure closing profile fd", e); 3697 } 3698 } 3699 } else { 3700 Debug.dumpNativeHeap(dhd.fd.getFileDescriptor()); 3701 } 3702 } 3703 3704 final void handleDispatchPackageBroadcast(int cmd, String[] packages) { 3705 boolean hasPkgInfo = false; 3706 if (packages != null) { 3707 for (int i=packages.length-1; i>=0; i--) { 3708 //Slog.i(TAG, "Cleaning old package: " + packages[i]); 3709 if (!hasPkgInfo) { 3710 WeakReference<LoadedApk> ref; 3711 ref = mPackages.get(packages[i]); 3712 if (ref != null && ref.get() != null) { 3713 hasPkgInfo = true; 3714 } else { 3715 ref = mResourcePackages.get(packages[i]); 3716 if (ref != null && ref.get() != null) { 3717 hasPkgInfo = true; 3718 } 3719 } 3720 } 3721 mPackages.remove(packages[i]); 3722 mResourcePackages.remove(packages[i]); 3723 } 3724 } 3725 ApplicationPackageManager.handlePackageBroadcast(cmd, packages, 3726 hasPkgInfo); 3727 } 3728 3729 final void handleLowMemory() { 3730 ArrayList<ComponentCallbacks2> callbacks; 3731 3732 synchronized (mPackages) { 3733 callbacks = collectComponentCallbacksLocked(true, null); 3734 } 3735 3736 final int N = callbacks.size(); 3737 for (int i=0; i<N; i++) { 3738 callbacks.get(i).onLowMemory(); 3739 } 3740 3741 // Ask SQLite to free up as much memory as it can, mostly from its page caches. 3742 if (Process.myUid() != Process.SYSTEM_UID) { 3743 int sqliteReleased = SQLiteDatabase.releaseMemory(); 3744 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); 3745 } 3746 3747 // Ask graphics to free up as much as possible (font/image caches) 3748 Canvas.freeCaches(); 3749 3750 BinderInternal.forceGc("mem"); 3751 } 3752 3753 final void handleTrimMemory(int level) { 3754 ArrayList<ComponentCallbacks2> callbacks; 3755 3756 synchronized (mPackages) { 3757 callbacks = collectComponentCallbacksLocked(true, null); 3758 } 3759 3760 final int N = callbacks.size(); 3761 for (int i=0; i<N; i++) { 3762 callbacks.get(i).onTrimMemory(level); 3763 } 3764 WindowManagerImpl.getDefault().trimMemory(level); 3765 } 3766 3767 private void setupGraphicsSupport(LoadedApk info) { 3768 if (Process.isIsolated()) { 3769 // Isolated processes aren't going to do UI. 3770 return; 3771 } 3772 try { 3773 int uid = Process.myUid(); 3774 String[] packages = getPackageManager().getPackagesForUid(uid); 3775 3776 // If there are several packages in this application we won't 3777 // initialize the graphics disk caches 3778 if (packages != null && packages.length == 1) { 3779 ContextImpl appContext = new ContextImpl(); 3780 appContext.init(info, null, this); 3781 3782 HardwareRenderer.setupDiskCache(appContext.getCacheDir()); 3783 RenderScript.setupDiskCache(appContext.getCacheDir()); 3784 } 3785 } catch (RemoteException e) { 3786 // Ignore 3787 } 3788 } 3789 3790 private void handleBindApplication(AppBindData data) { 3791 mBoundApplication = data; 3792 mConfiguration = new Configuration(data.config); 3793 mCompatConfiguration = new Configuration(data.config); 3794 3795 mProfiler = new Profiler(); 3796 mProfiler.profileFile = data.initProfileFile; 3797 mProfiler.profileFd = data.initProfileFd; 3798 mProfiler.autoStopProfiler = data.initAutoStopProfiler; 3799 3800 // send up app name; do this *before* waiting for debugger 3801 Process.setArgV0(data.processName); 3802 android.ddm.DdmHandleAppName.setAppName(data.processName); 3803 3804 if (data.persistent) { 3805 // Persistent processes on low-memory devices do not get to 3806 // use hardware accelerated drawing, since this can add too much 3807 // overhead to the process. 3808 Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); 3809 if (!ActivityManager.isHighEndGfx(display)) { 3810 HardwareRenderer.disable(false); 3811 } 3812 } 3813 3814 if (mProfiler.profileFd != null) { 3815 mProfiler.startProfiling(); 3816 } 3817 3818 // If the app is Honeycomb MR1 or earlier, switch its AsyncTask 3819 // implementation to use the pool executor. Normally, we use the 3820 // serialized executor as the default. This has to happen in the 3821 // main thread so the main looper is set right. 3822 if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { 3823 AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 3824 } 3825 3826 /* 3827 * Before spawning a new process, reset the time zone to be the system time zone. 3828 * This needs to be done because the system time zone could have changed after the 3829 * the spawning of this process. Without doing this this process would have the incorrect 3830 * system time zone. 3831 */ 3832 TimeZone.setDefault(null); 3833 3834 /* 3835 * Initialize the default locale in this process for the reasons we set the time zone. 3836 */ 3837 Locale.setDefault(data.config.locale); 3838 3839 /* 3840 * Update the system configuration since its preloaded and might not 3841 * reflect configuration changes. The configuration object passed 3842 * in AppBindData can be safely assumed to be up to date 3843 */ 3844 applyConfigurationToResourcesLocked(data.config, data.compatInfo); 3845 applyCompatConfiguration(); 3846 3847 data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 3848 3849 setupGraphicsSupport(data.info); 3850 3851 /** 3852 * For system applications on userdebug/eng builds, log stack 3853 * traces of disk and network access to dropbox for analysis. 3854 */ 3855 if ((data.appInfo.flags & 3856 (ApplicationInfo.FLAG_SYSTEM | 3857 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) { 3858 StrictMode.conditionallyEnableDebugLogging(); 3859 } 3860 3861 /** 3862 * For apps targetting SDK Honeycomb or later, we don't allow 3863 * network usage on the main event loop / UI thread. 3864 * 3865 * Note to those grepping: this is what ultimately throws 3866 * NetworkOnMainThreadException ... 3867 */ 3868 if (data.appInfo.targetSdkVersion > 9) { 3869 StrictMode.enableDeathOnNetwork(); 3870 } 3871 3872 /** 3873 * Switch this process to density compatibility mode if needed. 3874 */ 3875 if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) 3876 == 0) { 3877 Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); 3878 } 3879 3880 if (data.debugMode != IApplicationThread.DEBUG_OFF) { 3881 // XXX should have option to change the port. 3882 Debug.changeDebugPort(8100); 3883 if (data.debugMode == IApplicationThread.DEBUG_WAIT) { 3884 Slog.w(TAG, "Application " + data.info.getPackageName() 3885 + " is waiting for the debugger on port 8100..."); 3886 3887 IActivityManager mgr = ActivityManagerNative.getDefault(); 3888 try { 3889 mgr.showWaitingForDebugger(mAppThread, true); 3890 } catch (RemoteException ex) { 3891 } 3892 3893 Debug.waitForDebugger(); 3894 3895 try { 3896 mgr.showWaitingForDebugger(mAppThread, false); 3897 } catch (RemoteException ex) { 3898 } 3899 3900 } else { 3901 Slog.w(TAG, "Application " + data.info.getPackageName() 3902 + " can be debugged on port 8100..."); 3903 } 3904 } 3905 3906 /** 3907 * Initialize the default http proxy in this process for the reasons we set the time zone. 3908 */ 3909 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); 3910 if (b != null) { 3911 // In pre-boot mode (doing initial launch to collect password), not 3912 // all system is up. This includes the connectivity service, so don't 3913 // crash if we can't get it. 3914 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); 3915 try { 3916 ProxyProperties proxyProperties = service.getProxy(); 3917 Proxy.setHttpProxySystemProperty(proxyProperties); 3918 } catch (RemoteException e) {} 3919 } 3920 3921 if (data.instrumentationName != null) { 3922 ContextImpl appContext = new ContextImpl(); 3923 appContext.init(data.info, null, this); 3924 InstrumentationInfo ii = null; 3925 try { 3926 ii = appContext.getPackageManager(). 3927 getInstrumentationInfo(data.instrumentationName, 0); 3928 } catch (PackageManager.NameNotFoundException e) { 3929 } 3930 if (ii == null) { 3931 throw new RuntimeException( 3932 "Unable to find instrumentation info for: " 3933 + data.instrumentationName); 3934 } 3935 3936 mInstrumentationAppDir = ii.sourceDir; 3937 mInstrumentationAppPackage = ii.packageName; 3938 mInstrumentedAppDir = data.info.getAppDir(); 3939 3940 ApplicationInfo instrApp = new ApplicationInfo(); 3941 instrApp.packageName = ii.packageName; 3942 instrApp.sourceDir = ii.sourceDir; 3943 instrApp.publicSourceDir = ii.publicSourceDir; 3944 instrApp.dataDir = ii.dataDir; 3945 instrApp.nativeLibraryDir = ii.nativeLibraryDir; 3946 LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, 3947 appContext.getClassLoader(), false, true); 3948 ContextImpl instrContext = new ContextImpl(); 3949 instrContext.init(pi, null, this); 3950 3951 try { 3952 java.lang.ClassLoader cl = instrContext.getClassLoader(); 3953 mInstrumentation = (Instrumentation) 3954 cl.loadClass(data.instrumentationName.getClassName()).newInstance(); 3955 } catch (Exception e) { 3956 throw new RuntimeException( 3957 "Unable to instantiate instrumentation " 3958 + data.instrumentationName + ": " + e.toString(), e); 3959 } 3960 3961 mInstrumentation.init(this, instrContext, appContext, 3962 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher); 3963 3964 if (mProfiler.profileFile != null && !ii.handleProfiling 3965 && mProfiler.profileFd == null) { 3966 mProfiler.handlingProfiling = true; 3967 File file = new File(mProfiler.profileFile); 3968 file.getParentFile().mkdirs(); 3969 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 3970 } 3971 3972 try { 3973 mInstrumentation.onCreate(data.instrumentationArgs); 3974 } 3975 catch (Exception e) { 3976 throw new RuntimeException( 3977 "Exception thrown in onCreate() of " 3978 + data.instrumentationName + ": " + e.toString(), e); 3979 } 3980 3981 } else { 3982 mInstrumentation = new Instrumentation(); 3983 } 3984 3985 if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { 3986 dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); 3987 } 3988 3989 // allow disk access during application and provider setup. this could 3990 // block processing ordered broadcasts, but later processing would 3991 // probably end up doing the same disk access. restore not guarded with 3992 // finally block, since exceptions here will take down the application. 3993 final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); 3994 3995 // If the app is being launched for full backup or restore, bring it up in 3996 // a restricted environment with the base application class. 3997 Application app = data.info.makeApplication(data.restrictedBackupMode, null); 3998 mInitialApplication = app; 3999 4000 // don't bring up providers in restricted mode; they may depend on the 4001 // app's custom Application class 4002 if (!data.restrictedBackupMode) { 4003 List<ProviderInfo> providers = data.providers; 4004 if (providers != null) { 4005 installContentProviders(app, providers); 4006 // For process that contains content providers, we want to 4007 // ensure that the JIT is enabled "at some point". 4008 mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); 4009 } 4010 } 4011 4012 try { 4013 mInstrumentation.callApplicationOnCreate(app); 4014 } catch (Exception e) { 4015 if (!mInstrumentation.onException(app, e)) { 4016 throw new RuntimeException( 4017 "Unable to create application " + app.getClass().getName() 4018 + ": " + e.toString(), e); 4019 } 4020 } 4021 4022 StrictMode.setThreadPolicy(savedPolicy); 4023 } 4024 4025 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) { 4026 IActivityManager am = ActivityManagerNative.getDefault(); 4027 if (mProfiler.profileFile != null && mProfiler.handlingProfiling 4028 && mProfiler.profileFd == null) { 4029 Debug.stopMethodTracing(); 4030 } 4031 //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault() 4032 // + ", app thr: " + mAppThread); 4033 try { 4034 am.finishInstrumentation(mAppThread, resultCode, results); 4035 } catch (RemoteException ex) { 4036 } 4037 } 4038 4039 private void installContentProviders( 4040 Context context, List<ProviderInfo> providers) { 4041 final ArrayList<IActivityManager.ContentProviderHolder> results = 4042 new ArrayList<IActivityManager.ContentProviderHolder>(); 4043 4044 Iterator<ProviderInfo> i = providers.iterator(); 4045 while (i.hasNext()) { 4046 ProviderInfo cpi = i.next(); 4047 StringBuilder buf = new StringBuilder(128); 4048 buf.append("Pub "); 4049 buf.append(cpi.authority); 4050 buf.append(": "); 4051 buf.append(cpi.name); 4052 Log.i(TAG, buf.toString()); 4053 IContentProvider cp = installProvider(context, null, cpi, 4054 false /*noisy*/, true /*noReleaseNeeded*/); 4055 if (cp != null) { 4056 IActivityManager.ContentProviderHolder cph = 4057 new IActivityManager.ContentProviderHolder(cpi); 4058 cph.provider = cp; 4059 cph.noReleaseNeeded = true; 4060 results.add(cph); 4061 } 4062 } 4063 4064 try { 4065 ActivityManagerNative.getDefault().publishContentProviders( 4066 getApplicationThread(), results); 4067 } catch (RemoteException ex) { 4068 } 4069 } 4070 4071 public final IContentProvider acquireProvider(Context c, String name) { 4072 IContentProvider provider = acquireExistingProvider(c, name); 4073 if (provider != null) { 4074 return provider; 4075 } 4076 4077 // There is a possible race here. Another thread may try to acquire 4078 // the same provider at the same time. When this happens, we want to ensure 4079 // that the first one wins. 4080 // Note that we cannot hold the lock while acquiring and installing the 4081 // provider since it might take a long time to run and it could also potentially 4082 // be re-entrant in the case where the provider is in the same process. 4083 IActivityManager.ContentProviderHolder holder = null; 4084 try { 4085 holder = ActivityManagerNative.getDefault().getContentProvider( 4086 getApplicationThread(), name); 4087 } catch (RemoteException ex) { 4088 } 4089 if (holder == null) { 4090 Slog.e(TAG, "Failed to find provider info for " + name); 4091 return null; 4092 } 4093 4094 // Install provider will increment the reference count for us, and break 4095 // any ties in the race. 4096 provider = installProvider(c, holder.provider, holder.info, 4097 true /*noisy*/, holder.noReleaseNeeded); 4098 if (holder.provider != null && provider != holder.provider) { 4099 if (localLOGV) { 4100 Slog.v(TAG, "acquireProvider: lost the race, releasing extraneous " 4101 + "reference to the content provider"); 4102 } 4103 try { 4104 ActivityManagerNative.getDefault().removeContentProvider( 4105 getApplicationThread(), name); 4106 } catch (RemoteException ex) { 4107 } 4108 } 4109 return provider; 4110 } 4111 4112 public final IContentProvider acquireExistingProvider(Context c, String name) { 4113 synchronized (mProviderMap) { 4114 ProviderClientRecord pr = mProviderMap.get(name); 4115 if (pr == null) { 4116 return null; 4117 } 4118 4119 IContentProvider provider = pr.mProvider; 4120 IBinder jBinder = provider.asBinder(); 4121 4122 // Only increment the ref count if we have one. If we don't then the 4123 // provider is not reference counted and never needs to be released. 4124 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 4125 if (prc != null) { 4126 prc.count += 1; 4127 if (prc.count == 1) { 4128 if (localLOGV) { 4129 Slog.v(TAG, "acquireExistingProvider: " 4130 + "snatched provider from the jaws of death"); 4131 } 4132 // Because the provider previously had a reference count of zero, 4133 // it was scheduled to be removed. Cancel that. 4134 mH.removeMessages(H.REMOVE_PROVIDER, provider); 4135 } 4136 } 4137 return provider; 4138 } 4139 } 4140 4141 public final boolean releaseProvider(IContentProvider provider) { 4142 if(provider == null) { 4143 return false; 4144 } 4145 4146 IBinder jBinder = provider.asBinder(); 4147 synchronized (mProviderMap) { 4148 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 4149 if (prc == null) { 4150 // The provider has no ref count, no release is needed. 4151 return false; 4152 } 4153 4154 if (prc.count == 0) { 4155 if (localLOGV) Slog.v(TAG, "releaseProvider: ref count already 0, how?"); 4156 return false; 4157 } 4158 4159 prc.count -= 1; 4160 if (prc.count == 0) { 4161 // Schedule the actual remove asynchronously, since we don't know the context 4162 // this will be called in. 4163 // TODO: it would be nice to post a delayed message, so 4164 // if we come back and need the same provider quickly 4165 // we will still have it available. 4166 Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider); 4167 mH.sendMessage(msg); 4168 } 4169 return true; 4170 } 4171 } 4172 4173 final void completeRemoveProvider(IContentProvider provider) { 4174 IBinder jBinder = provider.asBinder(); 4175 String remoteProviderName = null; 4176 synchronized(mProviderMap) { 4177 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 4178 if (prc == null) { 4179 // Either no release is needed (so we shouldn't be here) or the 4180 // provider was already released. 4181 if (localLOGV) Slog.v(TAG, "completeRemoveProvider: release not needed"); 4182 return; 4183 } 4184 4185 if (prc.count != 0) { 4186 // There was a race! Some other client managed to acquire 4187 // the provider before the removal was completed. 4188 // Abort the removal. We will do it later. 4189 if (localLOGV) Slog.v(TAG, "completeRemoveProvider: lost the race, " 4190 + "provider still in use"); 4191 return; 4192 } 4193 4194 mProviderRefCountMap.remove(jBinder); 4195 4196 Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator(); 4197 while (iter.hasNext()) { 4198 ProviderClientRecord pr = iter.next(); 4199 IBinder myBinder = pr.mProvider.asBinder(); 4200 if (myBinder == jBinder) { 4201 iter.remove(); 4202 if (pr.mLocalProvider == null) { 4203 myBinder.unlinkToDeath(pr, 0); 4204 if (remoteProviderName == null) { 4205 remoteProviderName = pr.mName; 4206 } 4207 } 4208 } 4209 } 4210 } 4211 4212 if (remoteProviderName != null) { 4213 try { 4214 if (localLOGV) { 4215 Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative." 4216 + "removeContentProvider(" + remoteProviderName + ")"); 4217 } 4218 ActivityManagerNative.getDefault().removeContentProvider( 4219 getApplicationThread(), remoteProviderName); 4220 } catch (RemoteException e) { 4221 //do nothing content provider object is dead any way 4222 } 4223 } 4224 } 4225 4226 final void removeDeadProvider(String name, IContentProvider provider) { 4227 synchronized(mProviderMap) { 4228 ProviderClientRecord pr = mProviderMap.get(name); 4229 if (pr != null && pr.mProvider.asBinder() == provider.asBinder()) { 4230 Slog.i(TAG, "Removing dead content provider: " + name); 4231 ProviderClientRecord removed = mProviderMap.remove(name); 4232 if (removed != null) { 4233 removed.mProvider.asBinder().unlinkToDeath(removed, 0); 4234 } 4235 } 4236 } 4237 } 4238 4239 /** 4240 * Installs the provider. 4241 * 4242 * Providers that are local to the process or that come from the system server 4243 * may be installed permanently which is indicated by setting noReleaseNeeded to true. 4244 * Other remote providers are reference counted. The initial reference count 4245 * for all reference counted providers is one. Providers that are not reference 4246 * counted do not have a reference count (at all). 4247 * 4248 * This method detects when a provider has already been installed. When this happens, 4249 * it increments the reference count of the existing provider (if appropriate) 4250 * and returns the existing provider. This can happen due to concurrent 4251 * attempts to acquire the same provider. 4252 */ 4253 private IContentProvider installProvider(Context context, 4254 IContentProvider provider, ProviderInfo info, 4255 boolean noisy, boolean noReleaseNeeded) { 4256 ContentProvider localProvider = null; 4257 if (provider == null) { 4258 if (noisy) { 4259 Slog.d(TAG, "Loading provider " + info.authority + ": " 4260 + info.name); 4261 } 4262 Context c = null; 4263 ApplicationInfo ai = info.applicationInfo; 4264 if (context.getPackageName().equals(ai.packageName)) { 4265 c = context; 4266 } else if (mInitialApplication != null && 4267 mInitialApplication.getPackageName().equals(ai.packageName)) { 4268 c = mInitialApplication; 4269 } else { 4270 try { 4271 c = context.createPackageContext(ai.packageName, 4272 Context.CONTEXT_INCLUDE_CODE); 4273 } catch (PackageManager.NameNotFoundException e) { 4274 // Ignore 4275 } 4276 } 4277 if (c == null) { 4278 Slog.w(TAG, "Unable to get context for package " + 4279 ai.packageName + 4280 " while loading content provider " + 4281 info.name); 4282 return null; 4283 } 4284 try { 4285 final java.lang.ClassLoader cl = c.getClassLoader(); 4286 localProvider = (ContentProvider)cl. 4287 loadClass(info.name).newInstance(); 4288 provider = localProvider.getIContentProvider(); 4289 if (provider == null) { 4290 Slog.e(TAG, "Failed to instantiate class " + 4291 info.name + " from sourceDir " + 4292 info.applicationInfo.sourceDir); 4293 return null; 4294 } 4295 if (false) Slog.v( 4296 TAG, "Instantiating local provider " + info.name); 4297 // XXX Need to create the correct context for this provider. 4298 localProvider.attachInfo(c, info); 4299 } catch (java.lang.Exception e) { 4300 if (!mInstrumentation.onException(null, e)) { 4301 throw new RuntimeException( 4302 "Unable to get provider " + info.name 4303 + ": " + e.toString(), e); 4304 } 4305 return null; 4306 } 4307 } else if (localLOGV) { 4308 Slog.v(TAG, "Installing external provider " + info.authority + ": " 4309 + info.name); 4310 } 4311 4312 synchronized (mProviderMap) { 4313 // There is a possibility that this thread raced with another thread to 4314 // add the provider. If we find another thread got there first then we 4315 // just get out of the way and return the original provider. 4316 IBinder jBinder = provider.asBinder(); 4317 String names[] = PATTERN_SEMICOLON.split(info.authority); 4318 for (int i = 0; i < names.length; i++) { 4319 ProviderClientRecord pr = mProviderMap.get(names[i]); 4320 if (pr != null) { 4321 if (localLOGV) { 4322 Slog.v(TAG, "installProvider: lost the race, " 4323 + "using existing named provider"); 4324 } 4325 provider = pr.mProvider; 4326 } else { 4327 pr = new ProviderClientRecord(names[i], provider, localProvider); 4328 if (localProvider == null) { 4329 try { 4330 jBinder.linkToDeath(pr, 0); 4331 } catch (RemoteException e) { 4332 // Provider already dead. Bail out of here without making 4333 // any changes to the provider map or other data structures. 4334 return null; 4335 } 4336 } 4337 mProviderMap.put(names[i], pr); 4338 } 4339 } 4340 4341 if (localProvider != null) { 4342 ProviderClientRecord pr = mLocalProviders.get(jBinder); 4343 if (pr != null) { 4344 if (localLOGV) { 4345 Slog.v(TAG, "installProvider: lost the race, " 4346 + "using existing local provider"); 4347 } 4348 provider = pr.mProvider; 4349 } else { 4350 pr = new ProviderClientRecord(null, provider, localProvider); 4351 mLocalProviders.put(jBinder, pr); 4352 } 4353 } 4354 4355 if (!noReleaseNeeded) { 4356 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 4357 if (prc != null) { 4358 if (localLOGV) { 4359 Slog.v(TAG, "installProvider: lost the race, incrementing ref count"); 4360 } 4361 prc.count += 1; 4362 if (prc.count == 1) { 4363 if (localLOGV) { 4364 Slog.v(TAG, "installProvider: " 4365 + "snatched provider from the jaws of death"); 4366 } 4367 // Because the provider previously had a reference count of zero, 4368 // it was scheduled to be removed. Cancel that. 4369 mH.removeMessages(H.REMOVE_PROVIDER, provider); 4370 } 4371 } else { 4372 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); 4373 } 4374 } 4375 } 4376 return provider; 4377 } 4378 4379 private void attach(boolean system) { 4380 sThreadLocal.set(this); 4381 mSystemThread = system; 4382 if (!system) { 4383 ViewRootImpl.addFirstDrawHandler(new Runnable() { 4384 public void run() { 4385 ensureJitEnabled(); 4386 } 4387 }); 4388 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>"); 4389 RuntimeInit.setApplicationObject(mAppThread.asBinder()); 4390 IActivityManager mgr = ActivityManagerNative.getDefault(); 4391 try { 4392 mgr.attachApplication(mAppThread); 4393 } catch (RemoteException ex) { 4394 // Ignore 4395 } 4396 } else { 4397 // Don't set application object here -- if the system crashes, 4398 // we can't display an alert, we just want to die die die. 4399 android.ddm.DdmHandleAppName.setAppName("system_process"); 4400 try { 4401 mInstrumentation = new Instrumentation(); 4402 ContextImpl context = new ContextImpl(); 4403 context.init(getSystemContext().mPackageInfo, null, this); 4404 Application app = Instrumentation.newApplication(Application.class, context); 4405 mAllApplications.add(app); 4406 mInitialApplication = app; 4407 app.onCreate(); 4408 } catch (Exception e) { 4409 throw new RuntimeException( 4410 "Unable to instantiate Application():" + e.toString(), e); 4411 } 4412 } 4413 4414 ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { 4415 public void onConfigurationChanged(Configuration newConfig) { 4416 synchronized (mPackages) { 4417 // We need to apply this change to the resources 4418 // immediately, because upon returning the view 4419 // hierarchy will be informed about it. 4420 if (applyConfigurationToResourcesLocked(newConfig, null)) { 4421 // This actually changed the resources! Tell 4422 // everyone about it. 4423 if (mPendingConfiguration == null || 4424 mPendingConfiguration.isOtherSeqNewer(newConfig)) { 4425 mPendingConfiguration = newConfig; 4426 4427 queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig); 4428 } 4429 } 4430 } 4431 } 4432 public void onLowMemory() { 4433 } 4434 public void onTrimMemory(int level) { 4435 } 4436 }); 4437 } 4438 4439 public static ActivityThread systemMain() { 4440 HardwareRenderer.disable(true); 4441 ActivityThread thread = new ActivityThread(); 4442 thread.attach(true); 4443 return thread; 4444 } 4445 4446 public final void installSystemProviders(List<ProviderInfo> providers) { 4447 if (providers != null) { 4448 installContentProviders(mInitialApplication, providers); 4449 } 4450 } 4451 4452 public int getIntCoreSetting(String key, int defaultValue) { 4453 synchronized (mPackages) { 4454 if (mCoreSettings != null) { 4455 return mCoreSettings.getInt(key, defaultValue); 4456 } else { 4457 return defaultValue; 4458 } 4459 } 4460 } 4461 4462 public static void main(String[] args) { 4463 SamplingProfilerIntegration.start(); 4464 4465 // CloseGuard defaults to true and can be quite spammy. We 4466 // disable it here, but selectively enable it later (via 4467 // StrictMode) on debug builds, but using DropBox, not logs. 4468 CloseGuard.setEnabled(false); 4469 4470 Process.setArgV0("<pre-initialized>"); 4471 4472 Looper.prepareMainLooper(); 4473 if (sMainThreadHandler == null) { 4474 sMainThreadHandler = new Handler(); 4475 } 4476 4477 ActivityThread thread = new ActivityThread(); 4478 thread.attach(false); 4479 4480 AsyncTask.init(); 4481 4482 if (false) { 4483 Looper.myLooper().setMessageLogging(new 4484 LogPrinter(Log.DEBUG, "ActivityThread")); 4485 } 4486 4487 Looper.loop(); 4488 4489 throw new RuntimeException("Main thread loop unexpectedly exited"); 4490 } 4491} 4492