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