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