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