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