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