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