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