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