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