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