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