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