ActivityThread.java revision a998dff5d49a423aaf7097aa8f96bf5bdc681d25
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 libcore.io.IoUtils; 106 107import dalvik.system.CloseGuard; 108 109final class SuperNotCalledException extends AndroidRuntimeException { 110 public SuperNotCalledException(String msg) { 111 super(msg); 112 } 113} 114 115final class RemoteServiceException extends AndroidRuntimeException { 116 public RemoteServiceException(String msg) { 117 super(msg); 118 } 119} 120 121/** 122 * This manages the execution of the main thread in an 123 * application process, scheduling and executing activities, 124 * broadcasts, and other operations on it as the activity 125 * manager requests. 126 * 127 * {@hide} 128 */ 129public final class ActivityThread { 130 /** @hide */ 131 public static final String TAG = "ActivityThread"; 132 private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565; 133 static final boolean localLOGV = false; 134 static final boolean DEBUG_MESSAGES = false; 135 /** @hide */ 136 public static final boolean DEBUG_BROADCAST = false; 137 private static final boolean DEBUG_RESULTS = false; 138 private static final boolean DEBUG_BACKUP = true; 139 private static final boolean DEBUG_CONFIGURATION = false; 140 private static final boolean DEBUG_SERVICE = false; 141 private static final long MIN_TIME_BETWEEN_GCS = 5*1000; 142 private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); 143 private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; 144 private static final int LOG_ON_PAUSE_CALLED = 30021; 145 private static final int LOG_ON_RESUME_CALLED = 30022; 146 147 static ContextImpl mSystemContext = null; 148 149 static IPackageManager sPackageManager; 150 151 final ApplicationThread mAppThread = new ApplicationThread(); 152 final Looper mLooper = Looper.myLooper(); 153 final H mH = new H(); 154 final HashMap<IBinder, ActivityClientRecord> mActivities 155 = new HashMap<IBinder, ActivityClientRecord>(); 156 // List of new activities (via ActivityRecord.nextIdle) that should 157 // be reported when next we idle. 158 ActivityClientRecord mNewActivities = null; 159 // Number of activities that are currently visible on-screen. 160 int mNumVisibleActivities = 0; 161 final HashMap<IBinder, Service> mServices 162 = new HashMap<IBinder, Service>(); 163 AppBindData mBoundApplication; 164 Profiler mProfiler; 165 Configuration mConfiguration; 166 Configuration mCompatConfiguration; 167 Configuration mResConfiguration; 168 CompatibilityInfo mResCompatibilityInfo; 169 Application mInitialApplication; 170 final ArrayList<Application> mAllApplications 171 = new ArrayList<Application>(); 172 // set of instantiated backup agents, keyed by package name 173 final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>(); 174 static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>(); 175 Instrumentation mInstrumentation; 176 String mInstrumentationAppDir = null; 177 String mInstrumentationAppPackage = null; 178 String mInstrumentedAppDir = null; 179 boolean mSystemThread = false; 180 boolean mJitEnabled = false; 181 182 // These can be accessed by multiple threads; mPackages is the lock. 183 // XXX For now we keep around information about all packages we have 184 // seen, not removing entries from this map. 185 // NOTE: The activity and window managers need to call in to 186 // ActivityThread to do things like update resource configurations, 187 // which means this lock gets held while the activity and window managers 188 // holds their own lock. Thus you MUST NEVER call back into the activity manager 189 // or window manager or anything that depends on them while holding this lock. 190 final HashMap<String, WeakReference<LoadedApk>> mPackages 191 = new HashMap<String, WeakReference<LoadedApk>>(); 192 final HashMap<String, WeakReference<LoadedApk>> mResourcePackages 193 = new HashMap<String, WeakReference<LoadedApk>>(); 194 final HashMap<CompatibilityInfo, DisplayMetrics> mDisplayMetrics 195 = new HashMap<CompatibilityInfo, DisplayMetrics>(); 196 final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources 197 = new HashMap<ResourcesKey, WeakReference<Resources> >(); 198 final ArrayList<ActivityClientRecord> mRelaunchingActivities 199 = new ArrayList<ActivityClientRecord>(); 200 Configuration mPendingConfiguration = null; 201 202 // The lock of mProviderMap protects the following variables. 203 final HashMap<String, ProviderClientRecord> mProviderMap 204 = new HashMap<String, ProviderClientRecord>(); 205 final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap 206 = new HashMap<IBinder, ProviderRefCount>(); 207 final HashMap<IBinder, ProviderClientRecord> mLocalProviders 208 = new HashMap<IBinder, ProviderClientRecord>(); 209 210 final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners 211 = new HashMap<Activity, ArrayList<OnActivityPausedListener>>(); 212 213 final GcIdler mGcIdler = new GcIdler(); 214 boolean mGcIdlerScheduled = false; 215 216 static Handler sMainThreadHandler; // set once in main() 217 218 Bundle mCoreSettings = null; 219 220 static final class ActivityClientRecord { 221 IBinder token; 222 int ident; 223 Intent intent; 224 Bundle state; 225 Activity activity; 226 Window window; 227 Activity parent; 228 String embeddedID; 229 Activity.NonConfigurationInstances lastNonConfigurationInstances; 230 boolean paused; 231 boolean stopped; 232 boolean hideForNow; 233 Configuration newConfig; 234 Configuration createdConfig; 235 ActivityClientRecord nextIdle; 236 237 String profileFile; 238 ParcelFileDescriptor profileFd; 239 boolean autoStopProfiler; 240 241 ActivityInfo activityInfo; 242 CompatibilityInfo compatInfo; 243 LoadedApk packageInfo; 244 245 List<ResultInfo> pendingResults; 246 List<Intent> pendingIntents; 247 248 boolean startsNotResumed; 249 boolean isForward; 250 int pendingConfigChanges; 251 boolean onlyLocalRequest; 252 253 View mPendingRemoveWindow; 254 WindowManager mPendingRemoveWindowManager; 255 256 ActivityClientRecord() { 257 parent = null; 258 embeddedID = null; 259 paused = false; 260 stopped = false; 261 hideForNow = false; 262 nextIdle = null; 263 } 264 265 public boolean isPreHoneycomb() { 266 if (activity != null) { 267 return activity.getApplicationInfo().targetSdkVersion 268 < android.os.Build.VERSION_CODES.HONEYCOMB; 269 } 270 return false; 271 } 272 273 public String toString() { 274 ComponentName componentName = intent.getComponent(); 275 return "ActivityRecord{" 276 + Integer.toHexString(System.identityHashCode(this)) 277 + " token=" + token + " " + (componentName == null 278 ? "no component name" : componentName.toShortString()) 279 + "}"; 280 } 281 } 282 283 final class ProviderClientRecord implements IBinder.DeathRecipient { 284 final String mName; 285 final IContentProvider mProvider; 286 final ContentProvider mLocalProvider; 287 288 ProviderClientRecord(String name, IContentProvider provider, 289 ContentProvider localProvider) { 290 mName = name; 291 mProvider = provider; 292 mLocalProvider = localProvider; 293 } 294 295 public void binderDied() { 296 removeDeadProvider(mName, mProvider); 297 } 298 } 299 300 static final class NewIntentData { 301 List<Intent> intents; 302 IBinder token; 303 public String toString() { 304 return "NewIntentData{intents=" + intents + " token=" + token + "}"; 305 } 306 } 307 308 static final class ReceiverData extends BroadcastReceiver.PendingResult { 309 public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras, 310 boolean ordered, boolean sticky, IBinder token) { 311 super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token); 312 this.intent = intent; 313 } 314 315 Intent intent; 316 ActivityInfo info; 317 CompatibilityInfo compatInfo; 318 public String toString() { 319 return "ReceiverData{intent=" + intent + " packageName=" + 320 info.packageName + " resultCode=" + getResultCode() 321 + " resultData=" + getResultData() + " resultExtras=" 322 + getResultExtras(false) + "}"; 323 } 324 } 325 326 static final class CreateBackupAgentData { 327 ApplicationInfo appInfo; 328 CompatibilityInfo compatInfo; 329 int backupMode; 330 public String toString() { 331 return "CreateBackupAgentData{appInfo=" + appInfo 332 + " backupAgent=" + appInfo.backupAgentName 333 + " mode=" + backupMode + "}"; 334 } 335 } 336 337 static final class CreateServiceData { 338 IBinder token; 339 ServiceInfo info; 340 CompatibilityInfo compatInfo; 341 Intent intent; 342 public String toString() { 343 return "CreateServiceData{token=" + token + " className=" 344 + info.name + " packageName=" + info.packageName 345 + " intent=" + intent + "}"; 346 } 347 } 348 349 static final class BindServiceData { 350 IBinder token; 351 Intent intent; 352 boolean rebind; 353 public String toString() { 354 return "BindServiceData{token=" + token + " intent=" + intent + "}"; 355 } 356 } 357 358 static final class ServiceArgsData { 359 IBinder token; 360 boolean taskRemoved; 361 int startId; 362 int flags; 363 Intent args; 364 public String toString() { 365 return "ServiceArgsData{token=" + token + " startId=" + startId 366 + " args=" + args + "}"; 367 } 368 } 369 370 static final class AppBindData { 371 LoadedApk info; 372 String processName; 373 ApplicationInfo appInfo; 374 List<ProviderInfo> providers; 375 ComponentName instrumentationName; 376 Bundle instrumentationArgs; 377 IInstrumentationWatcher instrumentationWatcher; 378 int debugMode; 379 boolean enableOpenGlTrace; 380 boolean restrictedBackupMode; 381 boolean persistent; 382 Configuration config; 383 CompatibilityInfo compatInfo; 384 385 /** Initial values for {@link Profiler}. */ 386 String initProfileFile; 387 ParcelFileDescriptor initProfileFd; 388 boolean initAutoStopProfiler; 389 390 public String toString() { 391 return "AppBindData{appInfo=" + appInfo + "}"; 392 } 393 } 394 395 static final class Profiler { 396 String profileFile; 397 ParcelFileDescriptor profileFd; 398 boolean autoStopProfiler; 399 boolean profiling; 400 boolean handlingProfiling; 401 public void setProfiler(String file, ParcelFileDescriptor fd) { 402 if (profiling) { 403 if (fd != null) { 404 try { 405 fd.close(); 406 } catch (IOException e) { 407 // Ignore 408 } 409 } 410 return; 411 } 412 if (profileFd != null) { 413 try { 414 profileFd.close(); 415 } catch (IOException e) { 416 // Ignore 417 } 418 } 419 profileFile = file; 420 profileFd = fd; 421 } 422 public void startProfiling() { 423 if (profileFd == null || profiling) { 424 return; 425 } 426 try { 427 Debug.startMethodTracing(profileFile, profileFd.getFileDescriptor(), 428 8 * 1024 * 1024, 0); 429 profiling = true; 430 } catch (RuntimeException e) { 431 Slog.w(TAG, "Profiling failed on path " + profileFile); 432 try { 433 profileFd.close(); 434 profileFd = null; 435 } catch (IOException e2) { 436 Slog.w(TAG, "Failure closing profile fd", e2); 437 } 438 } 439 } 440 public void stopProfiling() { 441 if (profiling) { 442 profiling = false; 443 Debug.stopMethodTracing(); 444 if (profileFd != null) { 445 try { 446 profileFd.close(); 447 } catch (IOException e) { 448 } 449 } 450 profileFd = null; 451 profileFile = null; 452 } 453 } 454 } 455 456 static final class DumpComponentInfo { 457 ParcelFileDescriptor fd; 458 IBinder token; 459 String prefix; 460 String[] args; 461 } 462 463 static final class ResultData { 464 IBinder token; 465 List<ResultInfo> results; 466 public String toString() { 467 return "ResultData{token=" + token + " results" + results + "}"; 468 } 469 } 470 471 static final class ContextCleanupInfo { 472 ContextImpl context; 473 String what; 474 String who; 475 } 476 477 static final class ProfilerControlData { 478 String path; 479 ParcelFileDescriptor fd; 480 } 481 482 static final class DumpHeapData { 483 String path; 484 ParcelFileDescriptor fd; 485 } 486 487 static final class UpdateCompatibilityData { 488 String pkg; 489 CompatibilityInfo info; 490 } 491 492 private native void dumpGraphicsInfo(FileDescriptor fd); 493 494 private class ApplicationThread extends ApplicationThreadNative { 495 private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s"; 496 private static final String ONE_COUNT_COLUMN = "%21s %8d"; 497 private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d"; 498 private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s"; 499 500 // Formatting for checkin service - update version if row format changes 501 private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1; 502 503 private void updatePendingConfiguration(Configuration config) { 504 synchronized (mPackages) { 505 if (mPendingConfiguration == null || 506 mPendingConfiguration.isOtherSeqNewer(config)) { 507 mPendingConfiguration = config; 508 } 509 } 510 } 511 512 public final void schedulePauseActivity(IBinder token, boolean finished, 513 boolean userLeaving, int configChanges) { 514 queueOrSendMessage( 515 finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, 516 token, 517 (userLeaving ? 1 : 0), 518 configChanges); 519 } 520 521 public final void scheduleStopActivity(IBinder token, boolean showWindow, 522 int configChanges) { 523 queueOrSendMessage( 524 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE, 525 token, 0, configChanges); 526 } 527 528 public final void scheduleWindowVisibility(IBinder token, boolean showWindow) { 529 queueOrSendMessage( 530 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW, 531 token); 532 } 533 534 public final void scheduleSleeping(IBinder token, boolean sleeping) { 535 queueOrSendMessage(H.SLEEPING, token, sleeping ? 1 : 0); 536 } 537 538 public final void scheduleResumeActivity(IBinder token, boolean isForward) { 539 queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0); 540 } 541 542 public final void scheduleSendResult(IBinder token, List<ResultInfo> results) { 543 ResultData res = new ResultData(); 544 res.token = token; 545 res.results = results; 546 queueOrSendMessage(H.SEND_RESULT, res); 547 } 548 549 // we use token to identify this activity without having to send the 550 // activity itself back to the activity manager. (matters more with ipc) 551 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, 552 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, 553 Bundle state, List<ResultInfo> pendingResults, 554 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, 555 String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { 556 ActivityClientRecord r = new ActivityClientRecord(); 557 558 r.token = token; 559 r.ident = ident; 560 r.intent = intent; 561 r.activityInfo = info; 562 r.compatInfo = compatInfo; 563 r.state = state; 564 565 r.pendingResults = pendingResults; 566 r.pendingIntents = pendingNewIntents; 567 568 r.startsNotResumed = notResumed; 569 r.isForward = isForward; 570 571 r.profileFile = profileName; 572 r.profileFd = profileFd; 573 r.autoStopProfiler = autoStopProfiler; 574 575 updatePendingConfiguration(curConfig); 576 577 queueOrSendMessage(H.LAUNCH_ACTIVITY, r); 578 } 579 580 public final void scheduleRelaunchActivity(IBinder token, 581 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, 582 int configChanges, boolean notResumed, Configuration config) { 583 requestRelaunchActivity(token, pendingResults, pendingNewIntents, 584 configChanges, notResumed, config, true); 585 } 586 587 public final void scheduleNewIntent(List<Intent> intents, IBinder token) { 588 NewIntentData data = new NewIntentData(); 589 data.intents = intents; 590 data.token = token; 591 592 queueOrSendMessage(H.NEW_INTENT, data); 593 } 594 595 public final void scheduleDestroyActivity(IBinder token, boolean finishing, 596 int configChanges) { 597 queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0, 598 configChanges); 599 } 600 601 public final void scheduleReceiver(Intent intent, ActivityInfo info, 602 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, 603 boolean sync) { 604 ReceiverData r = new ReceiverData(intent, resultCode, data, extras, 605 sync, false, mAppThread.asBinder()); 606 r.info = info; 607 r.compatInfo = compatInfo; 608 queueOrSendMessage(H.RECEIVER, r); 609 } 610 611 public final void scheduleCreateBackupAgent(ApplicationInfo app, 612 CompatibilityInfo compatInfo, int backupMode) { 613 CreateBackupAgentData d = new CreateBackupAgentData(); 614 d.appInfo = app; 615 d.compatInfo = compatInfo; 616 d.backupMode = backupMode; 617 618 queueOrSendMessage(H.CREATE_BACKUP_AGENT, d); 619 } 620 621 public final void scheduleDestroyBackupAgent(ApplicationInfo app, 622 CompatibilityInfo compatInfo) { 623 CreateBackupAgentData d = new CreateBackupAgentData(); 624 d.appInfo = app; 625 d.compatInfo = compatInfo; 626 627 queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d); 628 } 629 630 public final void scheduleCreateService(IBinder token, 631 ServiceInfo info, CompatibilityInfo compatInfo) { 632 CreateServiceData s = new CreateServiceData(); 633 s.token = token; 634 s.info = info; 635 s.compatInfo = compatInfo; 636 637 queueOrSendMessage(H.CREATE_SERVICE, s); 638 } 639 640 public final void scheduleBindService(IBinder token, Intent intent, 641 boolean rebind) { 642 BindServiceData s = new BindServiceData(); 643 s.token = token; 644 s.intent = intent; 645 s.rebind = rebind; 646 647 if (DEBUG_SERVICE) 648 Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid=" 649 + Binder.getCallingUid() + " pid=" + Binder.getCallingPid()); 650 queueOrSendMessage(H.BIND_SERVICE, s); 651 } 652 653 public final void scheduleUnbindService(IBinder token, Intent intent) { 654 BindServiceData s = new BindServiceData(); 655 s.token = token; 656 s.intent = intent; 657 658 queueOrSendMessage(H.UNBIND_SERVICE, s); 659 } 660 661 public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId, 662 int flags ,Intent args) { 663 ServiceArgsData s = new ServiceArgsData(); 664 s.token = token; 665 s.taskRemoved = taskRemoved; 666 s.startId = startId; 667 s.flags = flags; 668 s.args = args; 669 670 queueOrSendMessage(H.SERVICE_ARGS, s); 671 } 672 673 public final void scheduleStopService(IBinder token) { 674 queueOrSendMessage(H.STOP_SERVICE, token); 675 } 676 677 public final void bindApplication(String processName, 678 ApplicationInfo appInfo, List<ProviderInfo> providers, 679 ComponentName instrumentationName, String profileFile, 680 ParcelFileDescriptor profileFd, boolean autoStopProfiler, 681 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, 682 int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode, 683 boolean persistent, Configuration config, CompatibilityInfo compatInfo, 684 Map<String, IBinder> services, Bundle coreSettings) { 685 686 if (services != null) { 687 // Setup the service cache in the ServiceManager 688 ServiceManager.initServiceCache(services); 689 } 690 691 setCoreSettings(coreSettings); 692 693 AppBindData data = new AppBindData(); 694 data.processName = processName; 695 data.appInfo = appInfo; 696 data.providers = providers; 697 data.instrumentationName = instrumentationName; 698 data.instrumentationArgs = instrumentationArgs; 699 data.instrumentationWatcher = instrumentationWatcher; 700 data.debugMode = debugMode; 701 data.enableOpenGlTrace = enableOpenGlTrace; 702 data.restrictedBackupMode = isRestrictedBackupMode; 703 data.persistent = persistent; 704 data.config = config; 705 data.compatInfo = compatInfo; 706 data.initProfileFile = profileFile; 707 data.initProfileFd = profileFd; 708 data.initAutoStopProfiler = false; 709 queueOrSendMessage(H.BIND_APPLICATION, data); 710 } 711 712 public final void scheduleExit() { 713 queueOrSendMessage(H.EXIT_APPLICATION, null); 714 } 715 716 public final void scheduleSuicide() { 717 queueOrSendMessage(H.SUICIDE, null); 718 } 719 720 public void requestThumbnail(IBinder token) { 721 queueOrSendMessage(H.REQUEST_THUMBNAIL, token); 722 } 723 724 public void scheduleConfigurationChanged(Configuration config) { 725 updatePendingConfiguration(config); 726 queueOrSendMessage(H.CONFIGURATION_CHANGED, config); 727 } 728 729 public void updateTimeZone() { 730 TimeZone.setDefault(null); 731 } 732 733 public void clearDnsCache() { 734 // a non-standard API to get this to libcore 735 InetAddress.clearDnsCache(); 736 } 737 738 public void setHttpProxy(String host, String port, String exclList) { 739 Proxy.setHttpProxySystemProperty(host, port, exclList); 740 } 741 742 public void processInBackground() { 743 mH.removeMessages(H.GC_WHEN_IDLE); 744 mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE)); 745 } 746 747 public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) { 748 DumpComponentInfo data = new DumpComponentInfo(); 749 try { 750 data.fd = ParcelFileDescriptor.dup(fd); 751 data.token = servicetoken; 752 data.args = args; 753 queueOrSendMessage(H.DUMP_SERVICE, data); 754 } catch (IOException e) { 755 Slog.w(TAG, "dumpService failed", e); 756 } 757 } 758 759 // This function exists to make sure all receiver dispatching is 760 // correctly ordered, since these are one-way calls and the binder driver 761 // applies transaction ordering per object for such calls. 762 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, 763 int resultCode, String dataStr, Bundle extras, boolean ordered, 764 boolean sticky) throws RemoteException { 765 receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky); 766 } 767 768 public void scheduleLowMemory() { 769 queueOrSendMessage(H.LOW_MEMORY, null); 770 } 771 772 public void scheduleActivityConfigurationChanged(IBinder token) { 773 queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token); 774 } 775 776 public void profilerControl(boolean start, String path, ParcelFileDescriptor fd, 777 int profileType) { 778 ProfilerControlData pcd = new ProfilerControlData(); 779 pcd.path = path; 780 pcd.fd = fd; 781 queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType); 782 } 783 784 public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) { 785 DumpHeapData dhd = new DumpHeapData(); 786 dhd.path = path; 787 dhd.fd = fd; 788 queueOrSendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0); 789 } 790 791 public void setSchedulingGroup(int group) { 792 // Note: do this immediately, since going into the foreground 793 // should happen regardless of what pending work we have to do 794 // and the activity manager will wait for us to report back that 795 // we are done before sending us to the background. 796 try { 797 Process.setProcessGroup(Process.myPid(), group); 798 } catch (Exception e) { 799 Slog.w(TAG, "Failed setting process group to " + group, e); 800 } 801 } 802 803 public void getMemoryInfo(Debug.MemoryInfo outInfo) { 804 Debug.getMemoryInfo(outInfo); 805 } 806 807 public void dispatchPackageBroadcast(int cmd, String[] packages) { 808 queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd); 809 } 810 811 public void scheduleCrash(String msg) { 812 queueOrSendMessage(H.SCHEDULE_CRASH, msg); 813 } 814 815 public void dumpActivity(FileDescriptor fd, IBinder activitytoken, 816 String prefix, String[] args) { 817 DumpComponentInfo data = new DumpComponentInfo(); 818 try { 819 data.fd = ParcelFileDescriptor.dup(fd); 820 data.token = activitytoken; 821 data.prefix = prefix; 822 data.args = args; 823 queueOrSendMessage(H.DUMP_ACTIVITY, data); 824 } catch (IOException e) { 825 Slog.w(TAG, "dumpActivity failed", e); 826 } 827 } 828 829 public void dumpProvider(FileDescriptor fd, IBinder providertoken, 830 String[] args) { 831 DumpComponentInfo data = new DumpComponentInfo(); 832 try { 833 data.fd = ParcelFileDescriptor.dup(fd); 834 data.token = providertoken; 835 data.args = args; 836 queueOrSendMessage(H.DUMP_PROVIDER, data); 837 } catch (IOException e) { 838 Slog.w(TAG, "dumpProvider failed", e); 839 } 840 } 841 842 @Override 843 public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin, 844 boolean all, String[] args) { 845 FileOutputStream fout = new FileOutputStream(fd); 846 PrintWriter pw = new PrintWriter(fout); 847 try { 848 return dumpMemInfo(pw, checkin, all); 849 } finally { 850 pw.flush(); 851 } 852 } 853 854 private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, boolean checkin, boolean all) { 855 long nativeMax = Debug.getNativeHeapSize() / 1024; 856 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; 857 long nativeFree = Debug.getNativeHeapFreeSize() / 1024; 858 859 Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); 860 Debug.getMemoryInfo(memInfo); 861 862 if (!all) { 863 return memInfo; 864 } 865 866 Runtime runtime = Runtime.getRuntime(); 867 868 long dalvikMax = runtime.totalMemory() / 1024; 869 long dalvikFree = runtime.freeMemory() / 1024; 870 long dalvikAllocated = dalvikMax - dalvikFree; 871 long viewInstanceCount = ViewDebug.getViewInstanceCount(); 872 long viewRootInstanceCount = ViewDebug.getViewRootImplCount(); 873 long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class); 874 long activityInstanceCount = Debug.countInstancesOfClass(Activity.class); 875 int globalAssetCount = AssetManager.getGlobalAssetCount(); 876 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount(); 877 int binderLocalObjectCount = Debug.getBinderLocalObjectCount(); 878 int binderProxyObjectCount = Debug.getBinderProxyObjectCount(); 879 int binderDeathObjectCount = Debug.getBinderDeathObjectCount(); 880 long openSslSocketCount = Debug.countInstancesOfClass(OpenSSLSocketImpl.class); 881 SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo(); 882 883 // For checkin, we print one long comma-separated list of values 884 if (checkin) { 885 // NOTE: if you change anything significant below, also consider changing 886 // ACTIVITY_THREAD_CHECKIN_VERSION. 887 String processName = (mBoundApplication != null) 888 ? mBoundApplication.processName : "unknown"; 889 890 // Header 891 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(','); 892 pw.print(Process.myPid()); pw.print(','); 893 pw.print(processName); pw.print(','); 894 895 // Heap info - max 896 pw.print(nativeMax); pw.print(','); 897 pw.print(dalvikMax); pw.print(','); 898 pw.print("N/A,"); 899 pw.print(nativeMax + dalvikMax); pw.print(','); 900 901 // Heap info - allocated 902 pw.print(nativeAllocated); pw.print(','); 903 pw.print(dalvikAllocated); pw.print(','); 904 pw.print("N/A,"); 905 pw.print(nativeAllocated + dalvikAllocated); pw.print(','); 906 907 // Heap info - free 908 pw.print(nativeFree); pw.print(','); 909 pw.print(dalvikFree); pw.print(','); 910 pw.print("N/A,"); 911 pw.print(nativeFree + dalvikFree); pw.print(','); 912 913 // Heap info - proportional set size 914 pw.print(memInfo.nativePss); pw.print(','); 915 pw.print(memInfo.dalvikPss); pw.print(','); 916 pw.print(memInfo.otherPss); pw.print(','); 917 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(','); 918 919 // Heap info - shared 920 pw.print(memInfo.nativeSharedDirty); pw.print(','); 921 pw.print(memInfo.dalvikSharedDirty); pw.print(','); 922 pw.print(memInfo.otherSharedDirty); pw.print(','); 923 pw.print(memInfo.nativeSharedDirty + memInfo.dalvikSharedDirty 924 + memInfo.otherSharedDirty); pw.print(','); 925 926 // Heap info - private 927 pw.print(memInfo.nativePrivateDirty); pw.print(','); 928 pw.print(memInfo.dalvikPrivateDirty); pw.print(','); 929 pw.print(memInfo.otherPrivateDirty); pw.print(','); 930 pw.print(memInfo.nativePrivateDirty + memInfo.dalvikPrivateDirty 931 + memInfo.otherPrivateDirty); pw.print(','); 932 933 // Object counts 934 pw.print(viewInstanceCount); pw.print(','); 935 pw.print(viewRootInstanceCount); pw.print(','); 936 pw.print(appContextInstanceCount); pw.print(','); 937 pw.print(activityInstanceCount); pw.print(','); 938 939 pw.print(globalAssetCount); pw.print(','); 940 pw.print(globalAssetManagerCount); pw.print(','); 941 pw.print(binderLocalObjectCount); pw.print(','); 942 pw.print(binderProxyObjectCount); pw.print(','); 943 944 pw.print(binderDeathObjectCount); pw.print(','); 945 pw.print(openSslSocketCount); pw.print(','); 946 947 // SQL 948 pw.print(stats.memoryUsed / 1024); pw.print(','); 949 pw.print(stats.memoryUsed / 1024); pw.print(','); 950 pw.print(stats.pageCacheOverflow / 1024); pw.print(','); 951 pw.print(stats.largestMemAlloc / 1024); 952 for (int i = 0; i < stats.dbStats.size(); i++) { 953 DbStats dbStats = stats.dbStats.get(i); 954 pw.print(','); pw.print(dbStats.dbName); 955 pw.print(','); pw.print(dbStats.pageSize); 956 pw.print(','); pw.print(dbStats.dbSize); 957 pw.print(','); pw.print(dbStats.lookaside); 958 pw.print(','); pw.print(dbStats.cache); 959 pw.print(','); pw.print(dbStats.cache); 960 } 961 pw.println(); 962 963 return memInfo; 964 } 965 966 // otherwise, show human-readable format 967 printRow(pw, HEAP_COLUMN, "", "", "Shared", "Private", "Heap", "Heap", "Heap"); 968 printRow(pw, HEAP_COLUMN, "", "Pss", "Dirty", "Dirty", "Size", "Alloc", "Free"); 969 printRow(pw, HEAP_COLUMN, "", "------", "------", "------", "------", "------", 970 "------"); 971 printRow(pw, HEAP_COLUMN, "Native", memInfo.nativePss, memInfo.nativeSharedDirty, 972 memInfo.nativePrivateDirty, nativeMax, nativeAllocated, nativeFree); 973 printRow(pw, HEAP_COLUMN, "Dalvik", memInfo.dalvikPss, memInfo.dalvikSharedDirty, 974 memInfo.dalvikPrivateDirty, dalvikMax, dalvikAllocated, dalvikFree); 975 976 int otherPss = memInfo.otherPss; 977 int otherSharedDirty = memInfo.otherSharedDirty; 978 int otherPrivateDirty = memInfo.otherPrivateDirty; 979 980 for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) { 981 printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i), 982 memInfo.getOtherPss(i), memInfo.getOtherSharedDirty(i), 983 memInfo.getOtherPrivateDirty(i), "", "", ""); 984 otherPss -= memInfo.getOtherPss(i); 985 otherSharedDirty -= memInfo.getOtherSharedDirty(i); 986 otherPrivateDirty -= memInfo.getOtherPrivateDirty(i); 987 } 988 989 printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSharedDirty, 990 otherPrivateDirty, "", "", ""); 991 printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(), 992 memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(), 993 nativeMax+dalvikMax, nativeAllocated+dalvikAllocated, 994 nativeFree+dalvikFree); 995 996 pw.println(" "); 997 pw.println(" Objects"); 998 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:", 999 viewRootInstanceCount); 1000 1001 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount, 1002 "Activities:", activityInstanceCount); 1003 1004 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount, 1005 "AssetManagers:", globalAssetManagerCount); 1006 1007 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount, 1008 "Proxy Binders:", binderProxyObjectCount); 1009 printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount); 1010 1011 printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount); 1012 1013 // SQLite mem info 1014 pw.println(" "); 1015 pw.println(" SQL"); 1016 printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024); 1017 printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:", 1018 stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024); 1019 pw.println(" "); 1020 int N = stats.dbStats.size(); 1021 if (N > 0) { 1022 pw.println(" DATABASES"); 1023 printRow(pw, " %8s %8s %14s %14s %s", "pgsz", "dbsz", "Lookaside(b)", "cache", 1024 "Dbname"); 1025 for (int i = 0; i < N; i++) { 1026 DbStats dbStats = stats.dbStats.get(i); 1027 printRow(pw, DB_INFO_FORMAT, 1028 (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ", 1029 (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ", 1030 (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ", 1031 dbStats.cache, dbStats.dbName); 1032 } 1033 } 1034 1035 // Asset details. 1036 String assetAlloc = AssetManager.getAssetAllocations(); 1037 if (assetAlloc != null) { 1038 pw.println(" "); 1039 pw.println(" Asset Allocations"); 1040 pw.print(assetAlloc); 1041 } 1042 1043 return memInfo; 1044 } 1045 1046 @Override 1047 public void dumpGfxInfo(FileDescriptor fd, String[] args) { 1048 dumpGraphicsInfo(fd); 1049 WindowManagerImpl.getDefault().dumpGfxInfo(fd); 1050 } 1051 1052 @Override 1053 public void dumpDbInfo(FileDescriptor fd, String[] args) { 1054 PrintWriter pw = new PrintWriter(new FileOutputStream(fd)); 1055 PrintWriterPrinter printer = new PrintWriterPrinter(pw); 1056 SQLiteDebug.dump(printer, args); 1057 pw.flush(); 1058 } 1059 1060 private void printRow(PrintWriter pw, String format, Object...objs) { 1061 pw.println(String.format(format, objs)); 1062 } 1063 1064 public void setCoreSettings(Bundle coreSettings) { 1065 queueOrSendMessage(H.SET_CORE_SETTINGS, coreSettings); 1066 } 1067 1068 public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) { 1069 UpdateCompatibilityData ucd = new UpdateCompatibilityData(); 1070 ucd.pkg = pkg; 1071 ucd.info = info; 1072 queueOrSendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd); 1073 } 1074 1075 public void scheduleTrimMemory(int level) { 1076 queueOrSendMessage(H.TRIM_MEMORY, null, level); 1077 } 1078 1079 } 1080 1081 private class H extends Handler { 1082 public static final int LAUNCH_ACTIVITY = 100; 1083 public static final int PAUSE_ACTIVITY = 101; 1084 public static final int PAUSE_ACTIVITY_FINISHING= 102; 1085 public static final int STOP_ACTIVITY_SHOW = 103; 1086 public static final int STOP_ACTIVITY_HIDE = 104; 1087 public static final int SHOW_WINDOW = 105; 1088 public static final int HIDE_WINDOW = 106; 1089 public static final int RESUME_ACTIVITY = 107; 1090 public static final int SEND_RESULT = 108; 1091 public static final int DESTROY_ACTIVITY = 109; 1092 public static final int BIND_APPLICATION = 110; 1093 public static final int EXIT_APPLICATION = 111; 1094 public static final int NEW_INTENT = 112; 1095 public static final int RECEIVER = 113; 1096 public static final int CREATE_SERVICE = 114; 1097 public static final int SERVICE_ARGS = 115; 1098 public static final int STOP_SERVICE = 116; 1099 public static final int REQUEST_THUMBNAIL = 117; 1100 public static final int CONFIGURATION_CHANGED = 118; 1101 public static final int CLEAN_UP_CONTEXT = 119; 1102 public static final int GC_WHEN_IDLE = 120; 1103 public static final int BIND_SERVICE = 121; 1104 public static final int UNBIND_SERVICE = 122; 1105 public static final int DUMP_SERVICE = 123; 1106 public static final int LOW_MEMORY = 124; 1107 public static final int ACTIVITY_CONFIGURATION_CHANGED = 125; 1108 public static final int RELAUNCH_ACTIVITY = 126; 1109 public static final int PROFILER_CONTROL = 127; 1110 public static final int CREATE_BACKUP_AGENT = 128; 1111 public static final int DESTROY_BACKUP_AGENT = 129; 1112 public static final int SUICIDE = 130; 1113 public static final int REMOVE_PROVIDER = 131; 1114 public static final int ENABLE_JIT = 132; 1115 public static final int DISPATCH_PACKAGE_BROADCAST = 133; 1116 public static final int SCHEDULE_CRASH = 134; 1117 public static final int DUMP_HEAP = 135; 1118 public static final int DUMP_ACTIVITY = 136; 1119 public static final int SLEEPING = 137; 1120 public static final int SET_CORE_SETTINGS = 138; 1121 public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139; 1122 public static final int TRIM_MEMORY = 140; 1123 public static final int DUMP_PROVIDER = 141; 1124 String codeToString(int code) { 1125 if (DEBUG_MESSAGES) { 1126 switch (code) { 1127 case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY"; 1128 case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY"; 1129 case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING"; 1130 case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW"; 1131 case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE"; 1132 case SHOW_WINDOW: return "SHOW_WINDOW"; 1133 case HIDE_WINDOW: return "HIDE_WINDOW"; 1134 case RESUME_ACTIVITY: return "RESUME_ACTIVITY"; 1135 case SEND_RESULT: return "SEND_RESULT"; 1136 case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY"; 1137 case BIND_APPLICATION: return "BIND_APPLICATION"; 1138 case EXIT_APPLICATION: return "EXIT_APPLICATION"; 1139 case NEW_INTENT: return "NEW_INTENT"; 1140 case RECEIVER: return "RECEIVER"; 1141 case CREATE_SERVICE: return "CREATE_SERVICE"; 1142 case SERVICE_ARGS: return "SERVICE_ARGS"; 1143 case STOP_SERVICE: return "STOP_SERVICE"; 1144 case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL"; 1145 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED"; 1146 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT"; 1147 case GC_WHEN_IDLE: return "GC_WHEN_IDLE"; 1148 case BIND_SERVICE: return "BIND_SERVICE"; 1149 case UNBIND_SERVICE: return "UNBIND_SERVICE"; 1150 case DUMP_SERVICE: return "DUMP_SERVICE"; 1151 case LOW_MEMORY: return "LOW_MEMORY"; 1152 case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED"; 1153 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; 1154 case PROFILER_CONTROL: return "PROFILER_CONTROL"; 1155 case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT"; 1156 case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT"; 1157 case SUICIDE: return "SUICIDE"; 1158 case REMOVE_PROVIDER: return "REMOVE_PROVIDER"; 1159 case ENABLE_JIT: return "ENABLE_JIT"; 1160 case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST"; 1161 case SCHEDULE_CRASH: return "SCHEDULE_CRASH"; 1162 case DUMP_HEAP: return "DUMP_HEAP"; 1163 case DUMP_ACTIVITY: return "DUMP_ACTIVITY"; 1164 case SLEEPING: return "SLEEPING"; 1165 case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS"; 1166 case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO"; 1167 case TRIM_MEMORY: return "TRIM_MEMORY"; 1168 case DUMP_PROVIDER: return "DUMP_PROVIDER"; 1169 } 1170 } 1171 return "(unknown)"; 1172 } 1173 public void handleMessage(Message msg) { 1174 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what); 1175 switch (msg.what) { 1176 case LAUNCH_ACTIVITY: { 1177 ActivityClientRecord r = (ActivityClientRecord)msg.obj; 1178 1179 r.packageInfo = getPackageInfoNoCheck( 1180 r.activityInfo.applicationInfo, r.compatInfo); 1181 handleLaunchActivity(r, null); 1182 } break; 1183 case RELAUNCH_ACTIVITY: { 1184 ActivityClientRecord r = (ActivityClientRecord)msg.obj; 1185 handleRelaunchActivity(r); 1186 } break; 1187 case PAUSE_ACTIVITY: 1188 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2); 1189 maybeSnapshot(); 1190 break; 1191 case PAUSE_ACTIVITY_FINISHING: 1192 handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2); 1193 break; 1194 case STOP_ACTIVITY_SHOW: 1195 handleStopActivity((IBinder)msg.obj, true, msg.arg2); 1196 break; 1197 case STOP_ACTIVITY_HIDE: 1198 handleStopActivity((IBinder)msg.obj, false, msg.arg2); 1199 break; 1200 case SHOW_WINDOW: 1201 handleWindowVisibility((IBinder)msg.obj, true); 1202 break; 1203 case HIDE_WINDOW: 1204 handleWindowVisibility((IBinder)msg.obj, false); 1205 break; 1206 case RESUME_ACTIVITY: 1207 handleResumeActivity((IBinder)msg.obj, true, 1208 msg.arg1 != 0); 1209 break; 1210 case SEND_RESULT: 1211 handleSendResult((ResultData)msg.obj); 1212 break; 1213 case DESTROY_ACTIVITY: 1214 handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0, 1215 msg.arg2, false); 1216 break; 1217 case BIND_APPLICATION: 1218 AppBindData data = (AppBindData)msg.obj; 1219 handleBindApplication(data); 1220 break; 1221 case EXIT_APPLICATION: 1222 if (mInitialApplication != null) { 1223 mInitialApplication.onTerminate(); 1224 } 1225 Looper.myLooper().quit(); 1226 break; 1227 case NEW_INTENT: 1228 handleNewIntent((NewIntentData)msg.obj); 1229 break; 1230 case RECEIVER: 1231 handleReceiver((ReceiverData)msg.obj); 1232 maybeSnapshot(); 1233 break; 1234 case CREATE_SERVICE: 1235 handleCreateService((CreateServiceData)msg.obj); 1236 break; 1237 case BIND_SERVICE: 1238 handleBindService((BindServiceData)msg.obj); 1239 break; 1240 case UNBIND_SERVICE: 1241 handleUnbindService((BindServiceData)msg.obj); 1242 break; 1243 case SERVICE_ARGS: 1244 handleServiceArgs((ServiceArgsData)msg.obj); 1245 break; 1246 case STOP_SERVICE: 1247 handleStopService((IBinder)msg.obj); 1248 maybeSnapshot(); 1249 break; 1250 case REQUEST_THUMBNAIL: 1251 handleRequestThumbnail((IBinder)msg.obj); 1252 break; 1253 case CONFIGURATION_CHANGED: 1254 handleConfigurationChanged((Configuration)msg.obj, null); 1255 break; 1256 case CLEAN_UP_CONTEXT: 1257 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj; 1258 cci.context.performFinalCleanup(cci.who, cci.what); 1259 break; 1260 case GC_WHEN_IDLE: 1261 scheduleGcIdler(); 1262 break; 1263 case DUMP_SERVICE: 1264 handleDumpService((DumpComponentInfo)msg.obj); 1265 break; 1266 case LOW_MEMORY: 1267 handleLowMemory(); 1268 break; 1269 case ACTIVITY_CONFIGURATION_CHANGED: 1270 handleActivityConfigurationChanged((IBinder)msg.obj); 1271 break; 1272 case PROFILER_CONTROL: 1273 handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2); 1274 break; 1275 case CREATE_BACKUP_AGENT: 1276 handleCreateBackupAgent((CreateBackupAgentData)msg.obj); 1277 break; 1278 case DESTROY_BACKUP_AGENT: 1279 handleDestroyBackupAgent((CreateBackupAgentData)msg.obj); 1280 break; 1281 case SUICIDE: 1282 Process.killProcess(Process.myPid()); 1283 break; 1284 case REMOVE_PROVIDER: 1285 completeRemoveProvider((IContentProvider)msg.obj); 1286 break; 1287 case ENABLE_JIT: 1288 ensureJitEnabled(); 1289 break; 1290 case DISPATCH_PACKAGE_BROADCAST: 1291 handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj); 1292 break; 1293 case SCHEDULE_CRASH: 1294 throw new RemoteServiceException((String)msg.obj); 1295 case DUMP_HEAP: 1296 handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj); 1297 break; 1298 case DUMP_ACTIVITY: 1299 handleDumpActivity((DumpComponentInfo)msg.obj); 1300 break; 1301 case DUMP_PROVIDER: 1302 handleDumpProvider((DumpComponentInfo)msg.obj); 1303 break; 1304 case SLEEPING: 1305 handleSleeping((IBinder)msg.obj, msg.arg1 != 0); 1306 break; 1307 case SET_CORE_SETTINGS: 1308 handleSetCoreSettings((Bundle) msg.obj); 1309 break; 1310 case UPDATE_PACKAGE_COMPATIBILITY_INFO: 1311 handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj); 1312 break; 1313 case TRIM_MEMORY: 1314 handleTrimMemory(msg.arg1); 1315 break; 1316 } 1317 if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what); 1318 } 1319 1320 private void maybeSnapshot() { 1321 if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) { 1322 // convert the *private* ActivityThread.PackageInfo to *public* known 1323 // android.content.pm.PackageInfo 1324 String packageName = mBoundApplication.info.mPackageName; 1325 android.content.pm.PackageInfo packageInfo = null; 1326 try { 1327 Context context = getSystemContext(); 1328 if(context == null) { 1329 Log.e(TAG, "cannot get a valid context"); 1330 return; 1331 } 1332 PackageManager pm = context.getPackageManager(); 1333 if(pm == null) { 1334 Log.e(TAG, "cannot get a valid PackageManager"); 1335 return; 1336 } 1337 packageInfo = pm.getPackageInfo( 1338 packageName, PackageManager.GET_ACTIVITIES); 1339 } catch (NameNotFoundException e) { 1340 Log.e(TAG, "cannot get package info for " + packageName, e); 1341 } 1342 SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo); 1343 } 1344 } 1345 } 1346 1347 private class Idler implements MessageQueue.IdleHandler { 1348 public final boolean queueIdle() { 1349 ActivityClientRecord a = mNewActivities; 1350 boolean stopProfiling = false; 1351 if (mBoundApplication != null && mProfiler.profileFd != null 1352 && mProfiler.autoStopProfiler) { 1353 stopProfiling = true; 1354 } 1355 if (a != null) { 1356 mNewActivities = null; 1357 IActivityManager am = ActivityManagerNative.getDefault(); 1358 ActivityClientRecord prev; 1359 do { 1360 if (localLOGV) Slog.v( 1361 TAG, "Reporting idle of " + a + 1362 " finished=" + 1363 (a.activity != null && a.activity.mFinished)); 1364 if (a.activity != null && !a.activity.mFinished) { 1365 try { 1366 am.activityIdle(a.token, a.createdConfig, stopProfiling); 1367 a.createdConfig = null; 1368 } catch (RemoteException ex) { 1369 // Ignore 1370 } 1371 } 1372 prev = a; 1373 a = a.nextIdle; 1374 prev.nextIdle = null; 1375 } while (a != null); 1376 } 1377 if (stopProfiling) { 1378 mProfiler.stopProfiling(); 1379 } 1380 ensureJitEnabled(); 1381 return false; 1382 } 1383 } 1384 1385 final class GcIdler implements MessageQueue.IdleHandler { 1386 public final boolean queueIdle() { 1387 doGcIfNeeded(); 1388 return false; 1389 } 1390 } 1391 1392 private static class ResourcesKey { 1393 final private String mResDir; 1394 final private float mScale; 1395 final private int mHash; 1396 1397 ResourcesKey(String resDir, float scale) { 1398 mResDir = resDir; 1399 mScale = scale; 1400 mHash = mResDir.hashCode() << 2 + (int) (mScale * 2); 1401 } 1402 1403 @Override 1404 public int hashCode() { 1405 return mHash; 1406 } 1407 1408 @Override 1409 public boolean equals(Object obj) { 1410 if (!(obj instanceof ResourcesKey)) { 1411 return false; 1412 } 1413 ResourcesKey peer = (ResourcesKey) obj; 1414 return mResDir.equals(peer.mResDir) && mScale == peer.mScale; 1415 } 1416 } 1417 1418 public static ActivityThread currentActivityThread() { 1419 return sThreadLocal.get(); 1420 } 1421 1422 public static String currentPackageName() { 1423 ActivityThread am = currentActivityThread(); 1424 return (am != null && am.mBoundApplication != null) 1425 ? am.mBoundApplication.processName : null; 1426 } 1427 1428 public static Application currentApplication() { 1429 ActivityThread am = currentActivityThread(); 1430 return am != null ? am.mInitialApplication : null; 1431 } 1432 1433 public static IPackageManager getPackageManager() { 1434 if (sPackageManager != null) { 1435 //Slog.v("PackageManager", "returning cur default = " + sPackageManager); 1436 return sPackageManager; 1437 } 1438 IBinder b = ServiceManager.getService("package"); 1439 //Slog.v("PackageManager", "default service binder = " + b); 1440 sPackageManager = IPackageManager.Stub.asInterface(b); 1441 //Slog.v("PackageManager", "default service = " + sPackageManager); 1442 return sPackageManager; 1443 } 1444 1445 DisplayMetrics getDisplayMetricsLocked(CompatibilityInfo ci, boolean forceUpdate) { 1446 DisplayMetrics dm = mDisplayMetrics.get(ci); 1447 if (dm != null && !forceUpdate) { 1448 return dm; 1449 } 1450 if (dm == null) { 1451 dm = new DisplayMetrics(); 1452 mDisplayMetrics.put(ci, dm); 1453 } 1454 Display d = WindowManagerImpl.getDefault(ci).getDefaultDisplay(); 1455 d.getMetrics(dm); 1456 //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h=" 1457 // + metrics.heightPixels + " den=" + metrics.density 1458 // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi); 1459 return dm; 1460 } 1461 1462 private Configuration mMainThreadConfig = new Configuration(); 1463 Configuration applyConfigCompatMainThread(Configuration config, CompatibilityInfo compat) { 1464 if (config == null) { 1465 return null; 1466 } 1467 if (compat != null && !compat.supportsScreen()) { 1468 mMainThreadConfig.setTo(config); 1469 config = mMainThreadConfig; 1470 compat.applyToConfiguration(config); 1471 } 1472 return config; 1473 } 1474 1475 /** 1476 * Creates the top level Resources for applications with the given compatibility info. 1477 * 1478 * @param resDir the resource directory. 1479 * @param compInfo the compability info. It will use the default compatibility info when it's 1480 * null. 1481 */ 1482 Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) { 1483 ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale); 1484 Resources r; 1485 synchronized (mPackages) { 1486 // Resources is app scale dependent. 1487 if (false) { 1488 Slog.w(TAG, "getTopLevelResources: " + resDir + " / " 1489 + compInfo.applicationScale); 1490 } 1491 WeakReference<Resources> wr = mActiveResources.get(key); 1492 r = wr != null ? wr.get() : null; 1493 //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate()); 1494 if (r != null && r.getAssets().isUpToDate()) { 1495 if (false) { 1496 Slog.w(TAG, "Returning cached resources " + r + " " + resDir 1497 + ": appScale=" + r.getCompatibilityInfo().applicationScale); 1498 } 1499 return r; 1500 } 1501 } 1502 1503 //if (r != null) { 1504 // Slog.w(TAG, "Throwing away out-of-date resources!!!! " 1505 // + r + " " + resDir); 1506 //} 1507 1508 AssetManager assets = new AssetManager(); 1509 if (assets.addAssetPath(resDir) == 0) { 1510 return null; 1511 } 1512 1513 //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics); 1514 DisplayMetrics metrics = getDisplayMetricsLocked(null, false); 1515 r = new Resources(assets, metrics, getConfiguration(), compInfo); 1516 if (false) { 1517 Slog.i(TAG, "Created app resources " + resDir + " " + r + ": " 1518 + r.getConfiguration() + " appScale=" 1519 + r.getCompatibilityInfo().applicationScale); 1520 } 1521 1522 synchronized (mPackages) { 1523 WeakReference<Resources> wr = mActiveResources.get(key); 1524 Resources existing = wr != null ? wr.get() : null; 1525 if (existing != null && existing.getAssets().isUpToDate()) { 1526 // Someone else already created the resources while we were 1527 // unlocked; go ahead and use theirs. 1528 r.getAssets().close(); 1529 return existing; 1530 } 1531 1532 // XXX need to remove entries when weak references go away 1533 mActiveResources.put(key, new WeakReference<Resources>(r)); 1534 return r; 1535 } 1536 } 1537 1538 /** 1539 * Creates the top level resources for the given package. 1540 */ 1541 Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) { 1542 return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo.get()); 1543 } 1544 1545 final Handler getHandler() { 1546 return mH; 1547 } 1548 1549 public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, 1550 int flags) { 1551 synchronized (mPackages) { 1552 WeakReference<LoadedApk> ref; 1553 if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) { 1554 ref = mPackages.get(packageName); 1555 } else { 1556 ref = mResourcePackages.get(packageName); 1557 } 1558 LoadedApk packageInfo = ref != null ? ref.get() : null; 1559 //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo); 1560 //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir 1561 // + ": " + packageInfo.mResources.getAssets().isUpToDate()); 1562 if (packageInfo != null && (packageInfo.mResources == null 1563 || packageInfo.mResources.getAssets().isUpToDate())) { 1564 if (packageInfo.isSecurityViolation() 1565 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) { 1566 throw new SecurityException( 1567 "Requesting code from " + packageName 1568 + " to be run in process " 1569 + mBoundApplication.processName 1570 + "/" + mBoundApplication.appInfo.uid); 1571 } 1572 return packageInfo; 1573 } 1574 } 1575 1576 ApplicationInfo ai = null; 1577 try { 1578 ai = getPackageManager().getApplicationInfo(packageName, 1579 PackageManager.GET_SHARED_LIBRARY_FILES); 1580 } catch (RemoteException e) { 1581 // Ignore 1582 } 1583 1584 if (ai != null) { 1585 return getPackageInfo(ai, compatInfo, flags); 1586 } 1587 1588 return null; 1589 } 1590 1591 public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo, 1592 int flags) { 1593 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0; 1594 boolean securityViolation = includeCode && ai.uid != 0 1595 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null 1596 ? !UserId.isSameApp(ai.uid, mBoundApplication.appInfo.uid) 1597 : true); 1598 if ((flags&(Context.CONTEXT_INCLUDE_CODE 1599 |Context.CONTEXT_IGNORE_SECURITY)) 1600 == Context.CONTEXT_INCLUDE_CODE) { 1601 if (securityViolation) { 1602 String msg = "Requesting code from " + ai.packageName 1603 + " (with uid " + ai.uid + ")"; 1604 if (mBoundApplication != null) { 1605 msg = msg + " to be run in process " 1606 + mBoundApplication.processName + " (with uid " 1607 + mBoundApplication.appInfo.uid + ")"; 1608 } 1609 throw new SecurityException(msg); 1610 } 1611 } 1612 return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode); 1613 } 1614 1615 public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, 1616 CompatibilityInfo compatInfo) { 1617 return getPackageInfo(ai, compatInfo, null, false, true); 1618 } 1619 1620 public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) { 1621 synchronized (mPackages) { 1622 WeakReference<LoadedApk> ref; 1623 if (includeCode) { 1624 ref = mPackages.get(packageName); 1625 } else { 1626 ref = mResourcePackages.get(packageName); 1627 } 1628 return ref != null ? ref.get() : null; 1629 } 1630 } 1631 1632 private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, 1633 ClassLoader baseLoader, boolean securityViolation, boolean includeCode) { 1634 synchronized (mPackages) { 1635 WeakReference<LoadedApk> ref; 1636 if (includeCode) { 1637 ref = mPackages.get(aInfo.packageName); 1638 } else { 1639 ref = mResourcePackages.get(aInfo.packageName); 1640 } 1641 LoadedApk packageInfo = ref != null ? ref.get() : null; 1642 if (packageInfo == null || (packageInfo.mResources != null 1643 && !packageInfo.mResources.getAssets().isUpToDate())) { 1644 if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package " 1645 : "Loading resource-only package ") + aInfo.packageName 1646 + " (in " + (mBoundApplication != null 1647 ? mBoundApplication.processName : null) 1648 + ")"); 1649 packageInfo = 1650 new LoadedApk(this, aInfo, compatInfo, this, baseLoader, 1651 securityViolation, includeCode && 1652 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0); 1653 if (includeCode) { 1654 mPackages.put(aInfo.packageName, 1655 new WeakReference<LoadedApk>(packageInfo)); 1656 } else { 1657 mResourcePackages.put(aInfo.packageName, 1658 new WeakReference<LoadedApk>(packageInfo)); 1659 } 1660 } 1661 return packageInfo; 1662 } 1663 } 1664 1665 ActivityThread() { 1666 } 1667 1668 public ApplicationThread getApplicationThread() 1669 { 1670 return mAppThread; 1671 } 1672 1673 public Instrumentation getInstrumentation() 1674 { 1675 return mInstrumentation; 1676 } 1677 1678 public Configuration getConfiguration() { 1679 return mResConfiguration; 1680 } 1681 1682 public boolean isProfiling() { 1683 return mProfiler != null && mProfiler.profileFile != null 1684 && mProfiler.profileFd == null; 1685 } 1686 1687 public String getProfileFilePath() { 1688 return mProfiler.profileFile; 1689 } 1690 1691 public Looper getLooper() { 1692 return mLooper; 1693 } 1694 1695 public Application getApplication() { 1696 return mInitialApplication; 1697 } 1698 1699 public String getProcessName() { 1700 return mBoundApplication.processName; 1701 } 1702 1703 public ContextImpl getSystemContext() { 1704 synchronized (this) { 1705 if (mSystemContext == null) { 1706 ContextImpl context = 1707 ContextImpl.createSystemContext(this); 1708 LoadedApk info = new LoadedApk(this, "android", context, null, 1709 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO); 1710 context.init(info, null, this); 1711 context.getResources().updateConfiguration( 1712 getConfiguration(), getDisplayMetricsLocked( 1713 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false)); 1714 mSystemContext = context; 1715 //Slog.i(TAG, "Created system resources " + context.getResources() 1716 // + ": " + context.getResources().getConfiguration()); 1717 } 1718 } 1719 return mSystemContext; 1720 } 1721 1722 public void installSystemApplicationInfo(ApplicationInfo info) { 1723 synchronized (this) { 1724 ContextImpl context = getSystemContext(); 1725 context.init(new LoadedApk(this, "android", context, info, 1726 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this); 1727 1728 // give ourselves a default profiler 1729 mProfiler = new Profiler(); 1730 } 1731 } 1732 1733 void ensureJitEnabled() { 1734 if (!mJitEnabled) { 1735 mJitEnabled = true; 1736 dalvik.system.VMRuntime.getRuntime().startJitCompilation(); 1737 } 1738 } 1739 1740 void scheduleGcIdler() { 1741 if (!mGcIdlerScheduled) { 1742 mGcIdlerScheduled = true; 1743 Looper.myQueue().addIdleHandler(mGcIdler); 1744 } 1745 mH.removeMessages(H.GC_WHEN_IDLE); 1746 } 1747 1748 void unscheduleGcIdler() { 1749 if (mGcIdlerScheduled) { 1750 mGcIdlerScheduled = false; 1751 Looper.myQueue().removeIdleHandler(mGcIdler); 1752 } 1753 mH.removeMessages(H.GC_WHEN_IDLE); 1754 } 1755 1756 void doGcIfNeeded() { 1757 mGcIdlerScheduled = false; 1758 final long now = SystemClock.uptimeMillis(); 1759 //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime() 1760 // + "m now=" + now); 1761 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) { 1762 //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!"); 1763 BinderInternal.forceGc("bg"); 1764 } 1765 } 1766 1767 public void registerOnActivityPausedListener(Activity activity, 1768 OnActivityPausedListener listener) { 1769 synchronized (mOnPauseListeners) { 1770 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); 1771 if (list == null) { 1772 list = new ArrayList<OnActivityPausedListener>(); 1773 mOnPauseListeners.put(activity, list); 1774 } 1775 list.add(listener); 1776 } 1777 } 1778 1779 public void unregisterOnActivityPausedListener(Activity activity, 1780 OnActivityPausedListener listener) { 1781 synchronized (mOnPauseListeners) { 1782 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); 1783 if (list != null) { 1784 list.remove(listener); 1785 } 1786 } 1787 } 1788 1789 public final ActivityInfo resolveActivityInfo(Intent intent) { 1790 ActivityInfo aInfo = intent.resolveActivityInfo( 1791 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES); 1792 if (aInfo == null) { 1793 // Throw an exception. 1794 Instrumentation.checkStartActivityResult( 1795 ActivityManager.START_CLASS_NOT_FOUND, intent); 1796 } 1797 return aInfo; 1798 } 1799 1800 public final Activity startActivityNow(Activity parent, String id, 1801 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state, 1802 Activity.NonConfigurationInstances lastNonConfigurationInstances) { 1803 ActivityClientRecord r = new ActivityClientRecord(); 1804 r.token = token; 1805 r.ident = 0; 1806 r.intent = intent; 1807 r.state = state; 1808 r.parent = parent; 1809 r.embeddedID = id; 1810 r.activityInfo = activityInfo; 1811 r.lastNonConfigurationInstances = lastNonConfigurationInstances; 1812 if (localLOGV) { 1813 ComponentName compname = intent.getComponent(); 1814 String name; 1815 if (compname != null) { 1816 name = compname.toShortString(); 1817 } else { 1818 name = "(Intent " + intent + ").getComponent() returned null"; 1819 } 1820 Slog.v(TAG, "Performing launch: action=" + intent.getAction() 1821 + ", comp=" + name 1822 + ", token=" + token); 1823 } 1824 return performLaunchActivity(r, null); 1825 } 1826 1827 public final Activity getActivity(IBinder token) { 1828 return mActivities.get(token).activity; 1829 } 1830 1831 public final void sendActivityResult( 1832 IBinder token, String id, int requestCode, 1833 int resultCode, Intent data) { 1834 if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id 1835 + " req=" + requestCode + " res=" + resultCode + " data=" + data); 1836 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 1837 list.add(new ResultInfo(id, requestCode, resultCode, data)); 1838 mAppThread.scheduleSendResult(token, list); 1839 } 1840 1841 // if the thread hasn't started yet, we don't have the handler, so just 1842 // save the messages until we're ready. 1843 private void queueOrSendMessage(int what, Object obj) { 1844 queueOrSendMessage(what, obj, 0, 0); 1845 } 1846 1847 private void queueOrSendMessage(int what, Object obj, int arg1) { 1848 queueOrSendMessage(what, obj, arg1, 0); 1849 } 1850 1851 private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { 1852 synchronized (this) { 1853 if (DEBUG_MESSAGES) Slog.v( 1854 TAG, "SCHEDULE " + what + " " + mH.codeToString(what) 1855 + ": " + arg1 + " / " + obj); 1856 Message msg = Message.obtain(); 1857 msg.what = what; 1858 msg.obj = obj; 1859 msg.arg1 = arg1; 1860 msg.arg2 = arg2; 1861 mH.sendMessage(msg); 1862 } 1863 } 1864 1865 final void scheduleContextCleanup(ContextImpl context, String who, 1866 String what) { 1867 ContextCleanupInfo cci = new ContextCleanupInfo(); 1868 cci.context = context; 1869 cci.who = who; 1870 cci.what = what; 1871 queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci); 1872 } 1873 1874 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { 1875 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); 1876 1877 ActivityInfo aInfo = r.activityInfo; 1878 if (r.packageInfo == null) { 1879 r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, 1880 Context.CONTEXT_INCLUDE_CODE); 1881 } 1882 1883 ComponentName component = r.intent.getComponent(); 1884 if (component == null) { 1885 component = r.intent.resolveActivity( 1886 mInitialApplication.getPackageManager()); 1887 r.intent.setComponent(component); 1888 } 1889 1890 if (r.activityInfo.targetActivity != null) { 1891 component = new ComponentName(r.activityInfo.packageName, 1892 r.activityInfo.targetActivity); 1893 } 1894 1895 Activity activity = null; 1896 try { 1897 java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); 1898 activity = mInstrumentation.newActivity( 1899 cl, component.getClassName(), r.intent); 1900 StrictMode.incrementExpectedActivityCount(activity.getClass()); 1901 r.intent.setExtrasClassLoader(cl); 1902 if (r.state != null) { 1903 r.state.setClassLoader(cl); 1904 } 1905 } catch (Exception e) { 1906 if (!mInstrumentation.onException(activity, e)) { 1907 throw new RuntimeException( 1908 "Unable to instantiate activity " + component 1909 + ": " + e.toString(), e); 1910 } 1911 } 1912 1913 try { 1914 Application app = r.packageInfo.makeApplication(false, mInstrumentation); 1915 1916 if (localLOGV) Slog.v(TAG, "Performing launch of " + r); 1917 if (localLOGV) Slog.v( 1918 TAG, r + ": app=" + app 1919 + ", appName=" + app.getPackageName() 1920 + ", pkg=" + r.packageInfo.getPackageName() 1921 + ", comp=" + r.intent.getComponent().toShortString() 1922 + ", dir=" + r.packageInfo.getAppDir()); 1923 1924 if (activity != null) { 1925 ContextImpl appContext = new ContextImpl(); 1926 appContext.init(r.packageInfo, r.token, this); 1927 appContext.setOuterContext(activity); 1928 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); 1929 Configuration config = new Configuration(mCompatConfiguration); 1930 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " 1931 + r.activityInfo.name + " with config " + config); 1932 activity.attach(appContext, this, getInstrumentation(), r.token, 1933 r.ident, app, r.intent, r.activityInfo, title, r.parent, 1934 r.embeddedID, r.lastNonConfigurationInstances, config); 1935 1936 if (customIntent != null) { 1937 activity.mIntent = customIntent; 1938 } 1939 r.lastNonConfigurationInstances = null; 1940 activity.mStartedActivity = false; 1941 int theme = r.activityInfo.getThemeResource(); 1942 if (theme != 0) { 1943 activity.setTheme(theme); 1944 } 1945 1946 activity.mCalled = false; 1947 mInstrumentation.callActivityOnCreate(activity, r.state); 1948 if (!activity.mCalled) { 1949 throw new SuperNotCalledException( 1950 "Activity " + r.intent.getComponent().toShortString() + 1951 " did not call through to super.onCreate()"); 1952 } 1953 r.activity = activity; 1954 r.stopped = true; 1955 if (!r.activity.mFinished) { 1956 activity.performStart(); 1957 r.stopped = false; 1958 } 1959 if (!r.activity.mFinished) { 1960 if (r.state != null) { 1961 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); 1962 } 1963 } 1964 if (!r.activity.mFinished) { 1965 activity.mCalled = false; 1966 mInstrumentation.callActivityOnPostCreate(activity, r.state); 1967 if (!activity.mCalled) { 1968 throw new SuperNotCalledException( 1969 "Activity " + r.intent.getComponent().toShortString() + 1970 " did not call through to super.onPostCreate()"); 1971 } 1972 } 1973 } 1974 r.paused = true; 1975 1976 mActivities.put(r.token, r); 1977 1978 } catch (SuperNotCalledException e) { 1979 throw e; 1980 1981 } catch (Exception e) { 1982 if (!mInstrumentation.onException(activity, e)) { 1983 throw new RuntimeException( 1984 "Unable to start activity " + component 1985 + ": " + e.toString(), e); 1986 } 1987 } 1988 1989 return activity; 1990 } 1991 1992 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { 1993 // If we are getting ready to gc after going to the background, well 1994 // we are back active so skip it. 1995 unscheduleGcIdler(); 1996 1997 if (r.profileFd != null) { 1998 mProfiler.setProfiler(r.profileFile, r.profileFd); 1999 mProfiler.startProfiling(); 2000 mProfiler.autoStopProfiler = r.autoStopProfiler; 2001 } 2002 2003 // Make sure we are running with the most recent config. 2004 handleConfigurationChanged(null, null); 2005 2006 if (localLOGV) Slog.v( 2007 TAG, "Handling launch of " + r); 2008 Activity a = performLaunchActivity(r, customIntent); 2009 2010 if (a != null) { 2011 r.createdConfig = new Configuration(mConfiguration); 2012 Bundle oldState = r.state; 2013 handleResumeActivity(r.token, false, r.isForward); 2014 2015 if (!r.activity.mFinished && r.startsNotResumed) { 2016 // The activity manager actually wants this one to start out 2017 // paused, because it needs to be visible but isn't in the 2018 // foreground. We accomplish this by going through the 2019 // normal startup (because activities expect to go through 2020 // onResume() the first time they run, before their window 2021 // is displayed), and then pausing it. However, in this case 2022 // we do -not- need to do the full pause cycle (of freezing 2023 // and such) because the activity manager assumes it can just 2024 // retain the current state it has. 2025 try { 2026 r.activity.mCalled = false; 2027 mInstrumentation.callActivityOnPause(r.activity); 2028 // We need to keep around the original state, in case 2029 // we need to be created again. 2030 r.state = oldState; 2031 if (!r.activity.mCalled) { 2032 throw new SuperNotCalledException( 2033 "Activity " + r.intent.getComponent().toShortString() + 2034 " did not call through to super.onPause()"); 2035 } 2036 2037 } catch (SuperNotCalledException e) { 2038 throw e; 2039 2040 } catch (Exception e) { 2041 if (!mInstrumentation.onException(r.activity, e)) { 2042 throw new RuntimeException( 2043 "Unable to pause activity " 2044 + r.intent.getComponent().toShortString() 2045 + ": " + e.toString(), e); 2046 } 2047 } 2048 r.paused = true; 2049 } 2050 } else { 2051 // If there was an error, for any reason, tell the activity 2052 // manager to stop us. 2053 try { 2054 ActivityManagerNative.getDefault() 2055 .finishActivity(r.token, Activity.RESULT_CANCELED, null); 2056 } catch (RemoteException ex) { 2057 // Ignore 2058 } 2059 } 2060 } 2061 2062 private void deliverNewIntents(ActivityClientRecord r, 2063 List<Intent> intents) { 2064 final int N = intents.size(); 2065 for (int i=0; i<N; i++) { 2066 Intent intent = intents.get(i); 2067 intent.setExtrasClassLoader(r.activity.getClassLoader()); 2068 r.activity.mFragments.noteStateNotSaved(); 2069 mInstrumentation.callActivityOnNewIntent(r.activity, intent); 2070 } 2071 } 2072 2073 public final void performNewIntents(IBinder token, 2074 List<Intent> intents) { 2075 ActivityClientRecord r = mActivities.get(token); 2076 if (r != null) { 2077 final boolean resumed = !r.paused; 2078 if (resumed) { 2079 r.activity.mTemporaryPause = true; 2080 mInstrumentation.callActivityOnPause(r.activity); 2081 } 2082 deliverNewIntents(r, intents); 2083 if (resumed) { 2084 r.activity.performResume(); 2085 r.activity.mTemporaryPause = false; 2086 } 2087 } 2088 } 2089 2090 private void handleNewIntent(NewIntentData data) { 2091 performNewIntents(data.token, data.intents); 2092 } 2093 2094 private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>(); 2095 2096 /** 2097 * Return the Intent that's currently being handled by a 2098 * BroadcastReceiver on this thread, or null if none. 2099 * @hide 2100 */ 2101 public static Intent getIntentBeingBroadcast() { 2102 return sCurrentBroadcastIntent.get(); 2103 } 2104 2105 private void handleReceiver(ReceiverData data) { 2106 // If we are getting ready to gc after going to the background, well 2107 // we are back active so skip it. 2108 unscheduleGcIdler(); 2109 2110 String component = data.intent.getComponent().getClassName(); 2111 2112 LoadedApk packageInfo = getPackageInfoNoCheck( 2113 data.info.applicationInfo, data.compatInfo); 2114 2115 IActivityManager mgr = ActivityManagerNative.getDefault(); 2116 2117 BroadcastReceiver receiver; 2118 try { 2119 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2120 data.intent.setExtrasClassLoader(cl); 2121 data.setExtrasClassLoader(cl); 2122 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); 2123 } catch (Exception e) { 2124 if (DEBUG_BROADCAST) Slog.i(TAG, 2125 "Finishing failed broadcast to " + data.intent.getComponent()); 2126 data.sendFinished(mgr); 2127 throw new RuntimeException( 2128 "Unable to instantiate receiver " + component 2129 + ": " + e.toString(), e); 2130 } 2131 2132 try { 2133 Application app = packageInfo.makeApplication(false, mInstrumentation); 2134 2135 if (localLOGV) Slog.v( 2136 TAG, "Performing receive of " + data.intent 2137 + ": app=" + app 2138 + ", appName=" + app.getPackageName() 2139 + ", pkg=" + packageInfo.getPackageName() 2140 + ", comp=" + data.intent.getComponent().toShortString() 2141 + ", dir=" + packageInfo.getAppDir()); 2142 2143 ContextImpl context = (ContextImpl)app.getBaseContext(); 2144 sCurrentBroadcastIntent.set(data.intent); 2145 receiver.setPendingResult(data); 2146 receiver.onReceive(context.getReceiverRestrictedContext(), 2147 data.intent); 2148 } catch (Exception e) { 2149 if (DEBUG_BROADCAST) Slog.i(TAG, 2150 "Finishing failed broadcast to " + data.intent.getComponent()); 2151 data.sendFinished(mgr); 2152 if (!mInstrumentation.onException(receiver, e)) { 2153 throw new RuntimeException( 2154 "Unable to start receiver " + component 2155 + ": " + e.toString(), e); 2156 } 2157 } finally { 2158 sCurrentBroadcastIntent.set(null); 2159 } 2160 2161 if (receiver.getPendingResult() != null) { 2162 data.finish(); 2163 } 2164 } 2165 2166 // Instantiate a BackupAgent and tell it that it's alive 2167 private void handleCreateBackupAgent(CreateBackupAgentData data) { 2168 if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data); 2169 2170 // no longer idle; we have backup work to do 2171 unscheduleGcIdler(); 2172 2173 // instantiate the BackupAgent class named in the manifest 2174 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 2175 String packageName = packageInfo.mPackageName; 2176 if (mBackupAgents.get(packageName) != null) { 2177 Slog.d(TAG, "BackupAgent " + " for " + packageName 2178 + " already exists"); 2179 return; 2180 } 2181 2182 BackupAgent agent = null; 2183 String classname = data.appInfo.backupAgentName; 2184 2185 // full backup operation but no app-supplied agent? use the default implementation 2186 if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL 2187 || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) { 2188 classname = "android.app.backup.FullBackupAgent"; 2189 } 2190 2191 try { 2192 IBinder binder = null; 2193 try { 2194 if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname); 2195 2196 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2197 agent = (BackupAgent) cl.loadClass(classname).newInstance(); 2198 2199 // set up the agent's context 2200 ContextImpl context = new ContextImpl(); 2201 context.init(packageInfo, null, this); 2202 context.setOuterContext(agent); 2203 agent.attach(context); 2204 2205 agent.onCreate(); 2206 binder = agent.onBind(); 2207 mBackupAgents.put(packageName, agent); 2208 } catch (Exception e) { 2209 // If this is during restore, fail silently; otherwise go 2210 // ahead and let the user see the crash. 2211 Slog.e(TAG, "Agent threw during creation: " + e); 2212 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE 2213 && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) { 2214 throw e; 2215 } 2216 // falling through with 'binder' still null 2217 } 2218 2219 // tell the OS that we're live now 2220 try { 2221 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder); 2222 } catch (RemoteException e) { 2223 // nothing to do. 2224 } 2225 } catch (Exception e) { 2226 throw new RuntimeException("Unable to create BackupAgent " 2227 + classname + ": " + e.toString(), e); 2228 } 2229 } 2230 2231 // Tear down a BackupAgent 2232 private void handleDestroyBackupAgent(CreateBackupAgentData data) { 2233 if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data); 2234 2235 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 2236 String packageName = packageInfo.mPackageName; 2237 BackupAgent agent = mBackupAgents.get(packageName); 2238 if (agent != null) { 2239 try { 2240 agent.onDestroy(); 2241 } catch (Exception e) { 2242 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo); 2243 e.printStackTrace(); 2244 } 2245 mBackupAgents.remove(packageName); 2246 } else { 2247 Slog.w(TAG, "Attempt to destroy unknown backup agent " + data); 2248 } 2249 } 2250 2251 private void handleCreateService(CreateServiceData data) { 2252 // If we are getting ready to gc after going to the background, well 2253 // we are back active so skip it. 2254 unscheduleGcIdler(); 2255 2256 LoadedApk packageInfo = getPackageInfoNoCheck( 2257 data.info.applicationInfo, data.compatInfo); 2258 Service service = null; 2259 try { 2260 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2261 service = (Service) cl.loadClass(data.info.name).newInstance(); 2262 } catch (Exception e) { 2263 if (!mInstrumentation.onException(service, e)) { 2264 throw new RuntimeException( 2265 "Unable to instantiate service " + data.info.name 2266 + ": " + e.toString(), e); 2267 } 2268 } 2269 2270 try { 2271 if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); 2272 2273 ContextImpl context = new ContextImpl(); 2274 context.init(packageInfo, null, this); 2275 2276 Application app = packageInfo.makeApplication(false, mInstrumentation); 2277 context.setOuterContext(service); 2278 service.attach(context, this, data.info.name, data.token, app, 2279 ActivityManagerNative.getDefault()); 2280 service.onCreate(); 2281 mServices.put(data.token, service); 2282 try { 2283 ActivityManagerNative.getDefault().serviceDoneExecuting( 2284 data.token, 0, 0, 0); 2285 } catch (RemoteException e) { 2286 // nothing to do. 2287 } 2288 } catch (Exception e) { 2289 if (!mInstrumentation.onException(service, e)) { 2290 throw new RuntimeException( 2291 "Unable to create service " + data.info.name 2292 + ": " + e.toString(), e); 2293 } 2294 } 2295 } 2296 2297 private void handleBindService(BindServiceData data) { 2298 Service s = mServices.get(data.token); 2299 if (DEBUG_SERVICE) 2300 Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind); 2301 if (s != null) { 2302 try { 2303 data.intent.setExtrasClassLoader(s.getClassLoader()); 2304 try { 2305 if (!data.rebind) { 2306 IBinder binder = s.onBind(data.intent); 2307 ActivityManagerNative.getDefault().publishService( 2308 data.token, data.intent, binder); 2309 } else { 2310 s.onRebind(data.intent); 2311 ActivityManagerNative.getDefault().serviceDoneExecuting( 2312 data.token, 0, 0, 0); 2313 } 2314 ensureJitEnabled(); 2315 } catch (RemoteException ex) { 2316 } 2317 } catch (Exception e) { 2318 if (!mInstrumentation.onException(s, e)) { 2319 throw new RuntimeException( 2320 "Unable to bind to service " + s 2321 + " with " + data.intent + ": " + e.toString(), e); 2322 } 2323 } 2324 } 2325 } 2326 2327 private void handleUnbindService(BindServiceData data) { 2328 Service s = mServices.get(data.token); 2329 if (s != null) { 2330 try { 2331 data.intent.setExtrasClassLoader(s.getClassLoader()); 2332 boolean doRebind = s.onUnbind(data.intent); 2333 try { 2334 if (doRebind) { 2335 ActivityManagerNative.getDefault().unbindFinished( 2336 data.token, data.intent, doRebind); 2337 } else { 2338 ActivityManagerNative.getDefault().serviceDoneExecuting( 2339 data.token, 0, 0, 0); 2340 } 2341 } catch (RemoteException ex) { 2342 } 2343 } catch (Exception e) { 2344 if (!mInstrumentation.onException(s, e)) { 2345 throw new RuntimeException( 2346 "Unable to unbind to service " + s 2347 + " with " + data.intent + ": " + e.toString(), e); 2348 } 2349 } 2350 } 2351 } 2352 2353 private void handleDumpService(DumpComponentInfo info) { 2354 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 2355 try { 2356 Service s = mServices.get(info.token); 2357 if (s != null) { 2358 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor())); 2359 s.dump(info.fd.getFileDescriptor(), pw, info.args); 2360 pw.flush(); 2361 } 2362 } finally { 2363 IoUtils.closeQuietly(info.fd); 2364 StrictMode.setThreadPolicy(oldPolicy); 2365 } 2366 } 2367 2368 private void handleDumpActivity(DumpComponentInfo info) { 2369 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 2370 try { 2371 ActivityClientRecord r = mActivities.get(info.token); 2372 if (r != null && r.activity != null) { 2373 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor())); 2374 r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args); 2375 pw.flush(); 2376 } 2377 } finally { 2378 IoUtils.closeQuietly(info.fd); 2379 StrictMode.setThreadPolicy(oldPolicy); 2380 } 2381 } 2382 2383 private void handleDumpProvider(DumpComponentInfo info) { 2384 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 2385 try { 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 } 2392 } finally { 2393 IoUtils.closeQuietly(info.fd); 2394 StrictMode.setThreadPolicy(oldPolicy); 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 static 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 for (ActivityClientRecord ar : mActivities.values()) { 3431 Activity a = ar.activity; 3432 if (a != null) { 3433 Configuration thisConfig = applyConfigCompatMainThread(newConfig, 3434 ar.packageInfo.mCompatibilityInfo.getIfNeeded()); 3435 if (!ar.activity.mFinished && (allActivities || !ar.paused)) { 3436 // If the activity is currently resumed, its configuration 3437 // needs to change right now. 3438 callbacks.add(a); 3439 } else if (thisConfig != null) { 3440 // Otherwise, we will tell it about the change 3441 // the next time it is resumed or shown. Note that 3442 // the activity manager may, before then, decide the 3443 // activity needs to be destroyed to handle its new 3444 // configuration. 3445 if (DEBUG_CONFIGURATION) { 3446 Slog.v(TAG, "Setting activity " 3447 + ar.activityInfo.name + " newConfig=" + thisConfig); 3448 } 3449 ar.newConfig = thisConfig; 3450 } 3451 } 3452 } 3453 } 3454 if (mServices.size() > 0) { 3455 for (Service service : mServices.values()) { 3456 callbacks.add(service); 3457 } 3458 } 3459 synchronized (mProviderMap) { 3460 if (mLocalProviders.size() > 0) { 3461 for (ProviderClientRecord providerClientRecord : mLocalProviders.values()) { 3462 callbacks.add(providerClientRecord.mLocalProvider); 3463 } 3464 } 3465 } 3466 final int N = mAllApplications.size(); 3467 for (int i=0; i<N; i++) { 3468 callbacks.add(mAllApplications.get(i)); 3469 } 3470 3471 return callbacks; 3472 } 3473 3474 private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) { 3475 // Only for Activity objects, check that they actually call up to their 3476 // superclass implementation. ComponentCallbacks2 is an interface, so 3477 // we check the runtime type and act accordingly. 3478 Activity activity = (cb instanceof Activity) ? (Activity) cb : null; 3479 if (activity != null) { 3480 activity.mCalled = false; 3481 } 3482 3483 boolean shouldChangeConfig = false; 3484 if ((activity == null) || (activity.mCurrentConfig == null)) { 3485 shouldChangeConfig = true; 3486 } else { 3487 3488 // If the new config is the same as the config this Activity 3489 // is already running with then don't bother calling 3490 // onConfigurationChanged 3491 int diff = activity.mCurrentConfig.diff(config); 3492 if (diff != 0) { 3493 // If this activity doesn't handle any of the config changes 3494 // then don't bother calling onConfigurationChanged as we're 3495 // going to destroy it. 3496 if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) { 3497 shouldChangeConfig = true; 3498 } 3499 } 3500 } 3501 3502 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb 3503 + ": shouldChangeConfig=" + shouldChangeConfig); 3504 if (shouldChangeConfig) { 3505 cb.onConfigurationChanged(config); 3506 3507 if (activity != null) { 3508 if (!activity.mCalled) { 3509 throw new SuperNotCalledException( 3510 "Activity " + activity.getLocalClassName() + 3511 " did not call through to super.onConfigurationChanged()"); 3512 } 3513 activity.mConfigChangeFlags = 0; 3514 activity.mCurrentConfig = new Configuration(config); 3515 } 3516 } 3517 } 3518 3519 public final void applyConfigurationToResources(Configuration config) { 3520 synchronized (mPackages) { 3521 applyConfigurationToResourcesLocked(config, null); 3522 } 3523 } 3524 3525 final boolean applyConfigurationToResourcesLocked(Configuration config, 3526 CompatibilityInfo compat) { 3527 if (mResConfiguration == null) { 3528 mResConfiguration = new Configuration(); 3529 } 3530 if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) { 3531 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq=" 3532 + mResConfiguration.seq + ", newSeq=" + config.seq); 3533 return false; 3534 } 3535 int changes = mResConfiguration.updateFrom(config); 3536 DisplayMetrics dm = getDisplayMetricsLocked(null, true); 3537 3538 if (compat != null && (mResCompatibilityInfo == null || 3539 !mResCompatibilityInfo.equals(compat))) { 3540 mResCompatibilityInfo = compat; 3541 changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT 3542 | ActivityInfo.CONFIG_SCREEN_SIZE 3543 | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 3544 } 3545 3546 // set it for java, this also affects newly created Resources 3547 if (config.locale != null) { 3548 Locale.setDefault(config.locale); 3549 } 3550 3551 Resources.updateSystemConfiguration(config, dm, compat); 3552 3553 ApplicationPackageManager.configurationChanged(); 3554 //Slog.i(TAG, "Configuration changed in " + currentPackageName()); 3555 3556 Iterator<WeakReference<Resources>> it = 3557 mActiveResources.values().iterator(); 3558 //Iterator<Map.Entry<String, WeakReference<Resources>>> it = 3559 // mActiveResources.entrySet().iterator(); 3560 while (it.hasNext()) { 3561 WeakReference<Resources> v = it.next(); 3562 Resources r = v.get(); 3563 if (r != null) { 3564 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources " 3565 + r + " config to: " + config); 3566 r.updateConfiguration(config, dm, compat); 3567 //Slog.i(TAG, "Updated app resources " + v.getKey() 3568 // + " " + r + ": " + r.getConfiguration()); 3569 } else { 3570 //Slog.i(TAG, "Removing old resources " + v.getKey()); 3571 it.remove(); 3572 } 3573 } 3574 3575 return changes != 0; 3576 } 3577 3578 final Configuration applyCompatConfiguration() { 3579 Configuration config = mConfiguration; 3580 if (mCompatConfiguration == null) { 3581 mCompatConfiguration = new Configuration(); 3582 } 3583 mCompatConfiguration.setTo(mConfiguration); 3584 if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) { 3585 mResCompatibilityInfo.applyToConfiguration(mCompatConfiguration); 3586 config = mCompatConfiguration; 3587 } 3588 return config; 3589 } 3590 3591 final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) { 3592 3593 ArrayList<ComponentCallbacks2> callbacks = null; 3594 3595 synchronized (mPackages) { 3596 if (mPendingConfiguration != null) { 3597 if (!mPendingConfiguration.isOtherSeqNewer(config)) { 3598 config = mPendingConfiguration; 3599 } 3600 mPendingConfiguration = null; 3601 } 3602 3603 if (config == null) { 3604 return; 3605 } 3606 3607 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: " 3608 + config); 3609 3610 applyConfigurationToResourcesLocked(config, compat); 3611 3612 if (mConfiguration == null) { 3613 mConfiguration = new Configuration(); 3614 } 3615 if (!mConfiguration.isOtherSeqNewer(config) && compat == null) { 3616 return; 3617 } 3618 mConfiguration.updateFrom(config); 3619 config = applyCompatConfiguration(); 3620 callbacks = collectComponentCallbacksLocked(false, config); 3621 } 3622 3623 // Cleanup hardware accelerated stuff 3624 WindowManagerImpl.getDefault().trimLocalMemory(); 3625 3626 if (callbacks != null) { 3627 final int N = callbacks.size(); 3628 for (int i=0; i<N; i++) { 3629 performConfigurationChanged(callbacks.get(i), config); 3630 } 3631 } 3632 } 3633 3634 final void handleActivityConfigurationChanged(IBinder token) { 3635 ActivityClientRecord r = mActivities.get(token); 3636 if (r == null || r.activity == null) { 3637 return; 3638 } 3639 3640 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: " 3641 + r.activityInfo.name); 3642 3643 performConfigurationChanged(r.activity, mCompatConfiguration); 3644 } 3645 3646 final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) { 3647 if (start) { 3648 try { 3649 switch (profileType) { 3650 case 1: 3651 ViewDebug.startLooperProfiling(pcd.path, pcd.fd.getFileDescriptor()); 3652 break; 3653 default: 3654 mProfiler.setProfiler(pcd.path, pcd.fd); 3655 mProfiler.autoStopProfiler = false; 3656 mProfiler.startProfiling(); 3657 break; 3658 } 3659 } catch (RuntimeException e) { 3660 Slog.w(TAG, "Profiling failed on path " + pcd.path 3661 + " -- can the process access this path?"); 3662 } finally { 3663 try { 3664 pcd.fd.close(); 3665 } catch (IOException e) { 3666 Slog.w(TAG, "Failure closing profile fd", e); 3667 } 3668 } 3669 } else { 3670 switch (profileType) { 3671 case 1: 3672 ViewDebug.stopLooperProfiling(); 3673 break; 3674 default: 3675 mProfiler.stopProfiling(); 3676 break; 3677 } 3678 } 3679 } 3680 3681 static final void handleDumpHeap(boolean managed, DumpHeapData dhd) { 3682 if (managed) { 3683 try { 3684 Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor()); 3685 } catch (IOException e) { 3686 Slog.w(TAG, "Managed heap dump failed on path " + dhd.path 3687 + " -- can the process access this path?"); 3688 } finally { 3689 try { 3690 dhd.fd.close(); 3691 } catch (IOException e) { 3692 Slog.w(TAG, "Failure closing profile fd", e); 3693 } 3694 } 3695 } else { 3696 Debug.dumpNativeHeap(dhd.fd.getFileDescriptor()); 3697 } 3698 } 3699 3700 final void handleDispatchPackageBroadcast(int cmd, String[] packages) { 3701 boolean hasPkgInfo = false; 3702 if (packages != null) { 3703 for (int i=packages.length-1; i>=0; i--) { 3704 //Slog.i(TAG, "Cleaning old package: " + packages[i]); 3705 if (!hasPkgInfo) { 3706 WeakReference<LoadedApk> ref; 3707 ref = mPackages.get(packages[i]); 3708 if (ref != null && ref.get() != null) { 3709 hasPkgInfo = true; 3710 } else { 3711 ref = mResourcePackages.get(packages[i]); 3712 if (ref != null && ref.get() != null) { 3713 hasPkgInfo = true; 3714 } 3715 } 3716 } 3717 mPackages.remove(packages[i]); 3718 mResourcePackages.remove(packages[i]); 3719 } 3720 } 3721 ApplicationPackageManager.handlePackageBroadcast(cmd, packages, 3722 hasPkgInfo); 3723 } 3724 3725 final void handleLowMemory() { 3726 ArrayList<ComponentCallbacks2> callbacks; 3727 3728 synchronized (mPackages) { 3729 callbacks = collectComponentCallbacksLocked(true, null); 3730 } 3731 3732 final int N = callbacks.size(); 3733 for (int i=0; i<N; i++) { 3734 callbacks.get(i).onLowMemory(); 3735 } 3736 3737 // Ask SQLite to free up as much memory as it can, mostly from its page caches. 3738 if (Process.myUid() != Process.SYSTEM_UID) { 3739 int sqliteReleased = SQLiteDatabase.releaseMemory(); 3740 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); 3741 } 3742 3743 // Ask graphics to free up as much as possible (font/image caches) 3744 Canvas.freeCaches(); 3745 3746 BinderInternal.forceGc("mem"); 3747 } 3748 3749 final void handleTrimMemory(int level) { 3750 WindowManagerImpl.getDefault().trimMemory(level); 3751 ArrayList<ComponentCallbacks2> callbacks; 3752 3753 synchronized (mPackages) { 3754 callbacks = collectComponentCallbacksLocked(true, null); 3755 } 3756 3757 final int N = callbacks.size(); 3758 for (int i = 0; i < N; i++) { 3759 callbacks.get(i).onTrimMemory(level); 3760 } 3761 WindowManagerImpl.getDefault().terminateEgl(); 3762 } 3763 3764 private void setupGraphicsSupport(LoadedApk info) { 3765 if (Process.isIsolated()) { 3766 // Isolated processes aren't going to do UI. 3767 return; 3768 } 3769 try { 3770 int uid = Process.myUid(); 3771 String[] packages = getPackageManager().getPackagesForUid(uid); 3772 3773 // If there are several packages in this application we won't 3774 // initialize the graphics disk caches 3775 if (packages != null && packages.length == 1) { 3776 ContextImpl appContext = new ContextImpl(); 3777 appContext.init(info, null, this); 3778 3779 HardwareRenderer.setupDiskCache(appContext.getCacheDir()); 3780 RenderScript.setupDiskCache(appContext.getCacheDir()); 3781 } 3782 } catch (RemoteException e) { 3783 // Ignore 3784 } 3785 } 3786 3787 private void handleBindApplication(AppBindData data) { 3788 mBoundApplication = data; 3789 mConfiguration = new Configuration(data.config); 3790 mCompatConfiguration = new Configuration(data.config); 3791 3792 mProfiler = new Profiler(); 3793 mProfiler.profileFile = data.initProfileFile; 3794 mProfiler.profileFd = data.initProfileFd; 3795 mProfiler.autoStopProfiler = data.initAutoStopProfiler; 3796 3797 // send up app name; do this *before* waiting for debugger 3798 Process.setArgV0(data.processName); 3799 android.ddm.DdmHandleAppName.setAppName(data.processName); 3800 3801 if (data.persistent) { 3802 // Persistent processes on low-memory devices do not get to 3803 // use hardware accelerated drawing, since this can add too much 3804 // overhead to the process. 3805 Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); 3806 if (!ActivityManager.isHighEndGfx(display)) { 3807 HardwareRenderer.disable(false); 3808 } 3809 } 3810 3811 if (mProfiler.profileFd != null) { 3812 mProfiler.startProfiling(); 3813 } 3814 3815 // If the app is Honeycomb MR1 or earlier, switch its AsyncTask 3816 // implementation to use the pool executor. Normally, we use the 3817 // serialized executor as the default. This has to happen in the 3818 // main thread so the main looper is set right. 3819 if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { 3820 AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 3821 } 3822 3823 /* 3824 * Before spawning a new process, reset the time zone to be the system time zone. 3825 * This needs to be done because the system time zone could have changed after the 3826 * the spawning of this process. Without doing this this process would have the incorrect 3827 * system time zone. 3828 */ 3829 TimeZone.setDefault(null); 3830 3831 /* 3832 * Initialize the default locale in this process for the reasons we set the time zone. 3833 */ 3834 Locale.setDefault(data.config.locale); 3835 3836 /* 3837 * Update the system configuration since its preloaded and might not 3838 * reflect configuration changes. The configuration object passed 3839 * in AppBindData can be safely assumed to be up to date 3840 */ 3841 applyConfigurationToResourcesLocked(data.config, data.compatInfo); 3842 applyCompatConfiguration(); 3843 3844 data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 3845 3846 setupGraphicsSupport(data.info); 3847 3848 /** 3849 * For system applications on userdebug/eng builds, log stack 3850 * traces of disk and network access to dropbox for analysis. 3851 */ 3852 if ((data.appInfo.flags & 3853 (ApplicationInfo.FLAG_SYSTEM | 3854 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) { 3855 StrictMode.conditionallyEnableDebugLogging(); 3856 } 3857 3858 /** 3859 * For apps targetting SDK Honeycomb or later, we don't allow 3860 * network usage on the main event loop / UI thread. 3861 * 3862 * Note to those grepping: this is what ultimately throws 3863 * NetworkOnMainThreadException ... 3864 */ 3865 if (data.appInfo.targetSdkVersion > 9) { 3866 StrictMode.enableDeathOnNetwork(); 3867 } 3868 3869 /** 3870 * Switch this process to density compatibility mode if needed. 3871 */ 3872 if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) 3873 == 0) { 3874 Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); 3875 } 3876 3877 if (data.debugMode != IApplicationThread.DEBUG_OFF) { 3878 // XXX should have option to change the port. 3879 Debug.changeDebugPort(8100); 3880 if (data.debugMode == IApplicationThread.DEBUG_WAIT) { 3881 Slog.w(TAG, "Application " + data.info.getPackageName() 3882 + " is waiting for the debugger on port 8100..."); 3883 3884 IActivityManager mgr = ActivityManagerNative.getDefault(); 3885 try { 3886 mgr.showWaitingForDebugger(mAppThread, true); 3887 } catch (RemoteException ex) { 3888 } 3889 3890 Debug.waitForDebugger(); 3891 3892 try { 3893 mgr.showWaitingForDebugger(mAppThread, false); 3894 } catch (RemoteException ex) { 3895 } 3896 3897 } else { 3898 Slog.w(TAG, "Application " + data.info.getPackageName() 3899 + " can be debugged on port 8100..."); 3900 } 3901 } 3902 3903 // Enable OpenGL tracing if required 3904 if (data.enableOpenGlTrace) { 3905 GLUtils.enableTracing(); 3906 } 3907 3908 /** 3909 * Initialize the default http proxy in this process for the reasons we set the time zone. 3910 */ 3911 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); 3912 if (b != null) { 3913 // In pre-boot mode (doing initial launch to collect password), not 3914 // all system is up. This includes the connectivity service, so don't 3915 // crash if we can't get it. 3916 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); 3917 try { 3918 ProxyProperties proxyProperties = service.getProxy(); 3919 Proxy.setHttpProxySystemProperty(proxyProperties); 3920 } catch (RemoteException e) {} 3921 } 3922 3923 if (data.instrumentationName != null) { 3924 ContextImpl appContext = new ContextImpl(); 3925 appContext.init(data.info, null, this); 3926 InstrumentationInfo ii = null; 3927 try { 3928 ii = appContext.getPackageManager(). 3929 getInstrumentationInfo(data.instrumentationName, 0); 3930 } catch (PackageManager.NameNotFoundException e) { 3931 } 3932 if (ii == null) { 3933 throw new RuntimeException( 3934 "Unable to find instrumentation info for: " 3935 + data.instrumentationName); 3936 } 3937 3938 mInstrumentationAppDir = ii.sourceDir; 3939 mInstrumentationAppPackage = ii.packageName; 3940 mInstrumentedAppDir = data.info.getAppDir(); 3941 3942 ApplicationInfo instrApp = new ApplicationInfo(); 3943 instrApp.packageName = ii.packageName; 3944 instrApp.sourceDir = ii.sourceDir; 3945 instrApp.publicSourceDir = ii.publicSourceDir; 3946 instrApp.dataDir = ii.dataDir; 3947 instrApp.nativeLibraryDir = ii.nativeLibraryDir; 3948 LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, 3949 appContext.getClassLoader(), false, true); 3950 ContextImpl instrContext = new ContextImpl(); 3951 instrContext.init(pi, null, this); 3952 3953 try { 3954 java.lang.ClassLoader cl = instrContext.getClassLoader(); 3955 mInstrumentation = (Instrumentation) 3956 cl.loadClass(data.instrumentationName.getClassName()).newInstance(); 3957 } catch (Exception e) { 3958 throw new RuntimeException( 3959 "Unable to instantiate instrumentation " 3960 + data.instrumentationName + ": " + e.toString(), e); 3961 } 3962 3963 mInstrumentation.init(this, instrContext, appContext, 3964 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher); 3965 3966 if (mProfiler.profileFile != null && !ii.handleProfiling 3967 && mProfiler.profileFd == null) { 3968 mProfiler.handlingProfiling = true; 3969 File file = new File(mProfiler.profileFile); 3970 file.getParentFile().mkdirs(); 3971 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 3972 } 3973 3974 try { 3975 mInstrumentation.onCreate(data.instrumentationArgs); 3976 } 3977 catch (Exception e) { 3978 throw new RuntimeException( 3979 "Exception thrown in onCreate() of " 3980 + data.instrumentationName + ": " + e.toString(), e); 3981 } 3982 3983 } else { 3984 mInstrumentation = new Instrumentation(); 3985 } 3986 3987 if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { 3988 dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); 3989 } 3990 3991 // Allow disk access during application and provider setup. This could 3992 // block processing ordered broadcasts, but later processing would 3993 // probably end up doing the same disk access. 3994 final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); 3995 try { 3996 // If the app is being launched for full backup or restore, bring it up in 3997 // a restricted environment with the base application class. 3998 Application app = data.info.makeApplication(data.restrictedBackupMode, null); 3999 mInitialApplication = app; 4000 4001 // don't bring up providers in restricted mode; they may depend on the 4002 // app's custom Application class 4003 if (!data.restrictedBackupMode) { 4004 List<ProviderInfo> providers = data.providers; 4005 if (providers != null) { 4006 installContentProviders(app, providers); 4007 // For process that contains content providers, we want to 4008 // ensure that the JIT is enabled "at some point". 4009 mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); 4010 } 4011 } 4012 4013 try { 4014 mInstrumentation.callApplicationOnCreate(app); 4015 } catch (Exception e) { 4016 if (!mInstrumentation.onException(app, e)) { 4017 throw new RuntimeException( 4018 "Unable to create application " + app.getClass().getName() 4019 + ": " + e.toString(), e); 4020 } 4021 } 4022 } finally { 4023 StrictMode.setThreadPolicy(savedPolicy); 4024 } 4025 } 4026 4027 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) { 4028 IActivityManager am = ActivityManagerNative.getDefault(); 4029 if (mProfiler.profileFile != null && mProfiler.handlingProfiling 4030 && mProfiler.profileFd == null) { 4031 Debug.stopMethodTracing(); 4032 } 4033 //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault() 4034 // + ", app thr: " + mAppThread); 4035 try { 4036 am.finishInstrumentation(mAppThread, resultCode, results); 4037 } catch (RemoteException ex) { 4038 } 4039 } 4040 4041 private void installContentProviders( 4042 Context context, List<ProviderInfo> providers) { 4043 final ArrayList<IActivityManager.ContentProviderHolder> results = 4044 new ArrayList<IActivityManager.ContentProviderHolder>(); 4045 4046 for (ProviderInfo cpi : providers) { 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