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