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