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