ActivityThread.java revision b70f3dff01e7e1e85f77cf0b0b2eaba8200eb82c
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, null); 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, null); 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, Intent customIntent) { 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 if (customIntent != null) { 2223 activity.mIntent = customIntent; 2224 } 2225 r.lastNonConfigurationInstance = null; 2226 r.lastNonConfigurationChildInstances = null; 2227 activity.mStartedActivity = false; 2228 int theme = r.activityInfo.getThemeResource(); 2229 if (theme != 0) { 2230 activity.setTheme(theme); 2231 } 2232 2233 activity.mCalled = false; 2234 mInstrumentation.callActivityOnCreate(activity, r.state); 2235 if (!activity.mCalled) { 2236 throw new SuperNotCalledException( 2237 "Activity " + r.intent.getComponent().toShortString() + 2238 " did not call through to super.onCreate()"); 2239 } 2240 r.activity = activity; 2241 r.stopped = true; 2242 if (!r.activity.mFinished) { 2243 activity.performStart(); 2244 r.stopped = false; 2245 } 2246 if (!r.activity.mFinished) { 2247 if (r.state != null) { 2248 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); 2249 } 2250 } 2251 if (!r.activity.mFinished) { 2252 activity.mCalled = false; 2253 mInstrumentation.callActivityOnPostCreate(activity, r.state); 2254 if (!activity.mCalled) { 2255 throw new SuperNotCalledException( 2256 "Activity " + r.intent.getComponent().toShortString() + 2257 " did not call through to super.onPostCreate()"); 2258 } 2259 } 2260 r.state = null; 2261 } 2262 r.paused = true; 2263 2264 mActivities.put(r.token, r); 2265 2266 } catch (SuperNotCalledException e) { 2267 throw e; 2268 2269 } catch (Exception e) { 2270 if (!mInstrumentation.onException(activity, e)) { 2271 throw new RuntimeException( 2272 "Unable to start activity " + component 2273 + ": " + e.toString(), e); 2274 } 2275 } 2276 2277 return activity; 2278 } 2279 2280 private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) { 2281 // If we are getting ready to gc after going to the background, well 2282 // we are back active so skip it. 2283 unscheduleGcIdler(); 2284 2285 if (localLOGV) Log.v( 2286 TAG, "Handling launch of " + r); 2287 Activity a = performLaunchActivity(r, customIntent); 2288 2289 if (a != null) { 2290 handleResumeActivity(r.token, false, r.isForward); 2291 2292 if (!r.activity.mFinished && r.startsNotResumed) { 2293 // The activity manager actually wants this one to start out 2294 // paused, because it needs to be visible but isn't in the 2295 // foreground. We accomplish this by going through the 2296 // normal startup (because activities expect to go through 2297 // onResume() the first time they run, before their window 2298 // is displayed), and then pausing it. However, in this case 2299 // we do -not- need to do the full pause cycle (of freezing 2300 // and such) because the activity manager assumes it can just 2301 // retain the current state it has. 2302 try { 2303 r.activity.mCalled = false; 2304 mInstrumentation.callActivityOnPause(r.activity); 2305 if (!r.activity.mCalled) { 2306 throw new SuperNotCalledException( 2307 "Activity " + r.intent.getComponent().toShortString() + 2308 " did not call through to super.onPause()"); 2309 } 2310 2311 } catch (SuperNotCalledException e) { 2312 throw e; 2313 2314 } catch (Exception e) { 2315 if (!mInstrumentation.onException(r.activity, e)) { 2316 throw new RuntimeException( 2317 "Unable to pause activity " 2318 + r.intent.getComponent().toShortString() 2319 + ": " + e.toString(), e); 2320 } 2321 } 2322 r.paused = true; 2323 } 2324 } else { 2325 // If there was an error, for any reason, tell the activity 2326 // manager to stop us. 2327 try { 2328 ActivityManagerNative.getDefault() 2329 .finishActivity(r.token, Activity.RESULT_CANCELED, null); 2330 } catch (RemoteException ex) { 2331 } 2332 } 2333 } 2334 2335 private final void deliverNewIntents(ActivityRecord r, 2336 List<Intent> intents) { 2337 final int N = intents.size(); 2338 for (int i=0; i<N; i++) { 2339 Intent intent = intents.get(i); 2340 intent.setExtrasClassLoader(r.activity.getClassLoader()); 2341 mInstrumentation.callActivityOnNewIntent(r.activity, intent); 2342 } 2343 } 2344 2345 public final void performNewIntents(IBinder token, 2346 List<Intent> intents) { 2347 ActivityRecord r = mActivities.get(token); 2348 if (r != null) { 2349 final boolean resumed = !r.paused; 2350 if (resumed) { 2351 mInstrumentation.callActivityOnPause(r.activity); 2352 } 2353 deliverNewIntents(r, intents); 2354 if (resumed) { 2355 mInstrumentation.callActivityOnResume(r.activity); 2356 } 2357 } 2358 } 2359 2360 private final void handleNewIntent(NewIntentData data) { 2361 performNewIntents(data.token, data.intents); 2362 } 2363 2364 private final void handleReceiver(ReceiverData data) { 2365 // If we are getting ready to gc after going to the background, well 2366 // we are back active so skip it. 2367 unscheduleGcIdler(); 2368 2369 String component = data.intent.getComponent().getClassName(); 2370 2371 PackageInfo packageInfo = getPackageInfoNoCheck( 2372 data.info.applicationInfo); 2373 2374 IActivityManager mgr = ActivityManagerNative.getDefault(); 2375 2376 BroadcastReceiver receiver = null; 2377 try { 2378 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2379 data.intent.setExtrasClassLoader(cl); 2380 if (data.resultExtras != null) { 2381 data.resultExtras.setClassLoader(cl); 2382 } 2383 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); 2384 } catch (Exception e) { 2385 try { 2386 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode, 2387 data.resultData, data.resultExtras, data.resultAbort); 2388 } catch (RemoteException ex) { 2389 } 2390 throw new RuntimeException( 2391 "Unable to instantiate receiver " + component 2392 + ": " + e.toString(), e); 2393 } 2394 2395 try { 2396 Application app = packageInfo.makeApplication(); 2397 2398 if (localLOGV) Log.v( 2399 TAG, "Performing receive of " + data.intent 2400 + ": app=" + app 2401 + ", appName=" + app.getPackageName() 2402 + ", pkg=" + packageInfo.getPackageName() 2403 + ", comp=" + data.intent.getComponent().toShortString() 2404 + ", dir=" + packageInfo.getAppDir()); 2405 2406 ApplicationContext context = (ApplicationContext)app.getBaseContext(); 2407 receiver.setOrderedHint(true); 2408 receiver.setResult(data.resultCode, data.resultData, 2409 data.resultExtras); 2410 receiver.setOrderedHint(data.sync); 2411 receiver.onReceive(context.getReceiverRestrictedContext(), 2412 data.intent); 2413 } catch (Exception e) { 2414 try { 2415 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode, 2416 data.resultData, data.resultExtras, data.resultAbort); 2417 } catch (RemoteException ex) { 2418 } 2419 if (!mInstrumentation.onException(receiver, e)) { 2420 throw new RuntimeException( 2421 "Unable to start receiver " + component 2422 + ": " + e.toString(), e); 2423 } 2424 } 2425 2426 try { 2427 if (data.sync) { 2428 mgr.finishReceiver( 2429 mAppThread.asBinder(), receiver.getResultCode(), 2430 receiver.getResultData(), receiver.getResultExtras(false), 2431 receiver.getAbortBroadcast()); 2432 } else { 2433 mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false); 2434 } 2435 } catch (RemoteException ex) { 2436 } 2437 } 2438 2439 private final void handleCreateService(CreateServiceData data) { 2440 // If we are getting ready to gc after going to the background, well 2441 // we are back active so skip it. 2442 unscheduleGcIdler(); 2443 2444 PackageInfo packageInfo = getPackageInfoNoCheck( 2445 data.info.applicationInfo); 2446 Service service = null; 2447 try { 2448 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2449 service = (Service) cl.loadClass(data.info.name).newInstance(); 2450 } catch (Exception e) { 2451 if (!mInstrumentation.onException(service, e)) { 2452 throw new RuntimeException( 2453 "Unable to instantiate service " + data.info.name 2454 + ": " + e.toString(), e); 2455 } 2456 } 2457 2458 try { 2459 if (localLOGV) Log.v(TAG, "Creating service " + data.info.name); 2460 2461 ApplicationContext context = new ApplicationContext(); 2462 context.init(packageInfo, null, this); 2463 2464 Application app = packageInfo.makeApplication(); 2465 context.setOuterContext(service); 2466 service.attach(context, this, data.info.name, data.token, app, 2467 ActivityManagerNative.getDefault()); 2468 service.onCreate(); 2469 mServices.put(data.token, service); 2470 try { 2471 ActivityManagerNative.getDefault().serviceDoneExecuting(data.token); 2472 } catch (RemoteException e) { 2473 // nothing to do. 2474 } 2475 } catch (Exception e) { 2476 if (!mInstrumentation.onException(service, e)) { 2477 throw new RuntimeException( 2478 "Unable to create service " + data.info.name 2479 + ": " + e.toString(), e); 2480 } 2481 } 2482 } 2483 2484 private final void handleBindService(BindServiceData data) { 2485 Service s = mServices.get(data.token); 2486 if (s != null) { 2487 try { 2488 data.intent.setExtrasClassLoader(s.getClassLoader()); 2489 try { 2490 if (!data.rebind) { 2491 IBinder binder = s.onBind(data.intent); 2492 ActivityManagerNative.getDefault().publishService( 2493 data.token, data.intent, binder); 2494 } else { 2495 s.onRebind(data.intent); 2496 ActivityManagerNative.getDefault().serviceDoneExecuting( 2497 data.token); 2498 } 2499 } catch (RemoteException ex) { 2500 } 2501 } catch (Exception e) { 2502 if (!mInstrumentation.onException(s, e)) { 2503 throw new RuntimeException( 2504 "Unable to bind to service " + s 2505 + " with " + data.intent + ": " + e.toString(), e); 2506 } 2507 } 2508 } 2509 } 2510 2511 private final void handleUnbindService(BindServiceData data) { 2512 Service s = mServices.get(data.token); 2513 if (s != null) { 2514 try { 2515 data.intent.setExtrasClassLoader(s.getClassLoader()); 2516 boolean doRebind = s.onUnbind(data.intent); 2517 try { 2518 if (doRebind) { 2519 ActivityManagerNative.getDefault().unbindFinished( 2520 data.token, data.intent, doRebind); 2521 } else { 2522 ActivityManagerNative.getDefault().serviceDoneExecuting( 2523 data.token); 2524 } 2525 } catch (RemoteException ex) { 2526 } 2527 } catch (Exception e) { 2528 if (!mInstrumentation.onException(s, e)) { 2529 throw new RuntimeException( 2530 "Unable to unbind to service " + s 2531 + " with " + data.intent + ": " + e.toString(), e); 2532 } 2533 } 2534 } 2535 } 2536 2537 private void handleDumpService(DumpServiceInfo info) { 2538 try { 2539 Service s = mServices.get(info.service); 2540 if (s != null) { 2541 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd)); 2542 s.dump(info.fd, pw, info.args); 2543 pw.close(); 2544 } 2545 } finally { 2546 synchronized (info) { 2547 info.dumped = true; 2548 info.notifyAll(); 2549 } 2550 } 2551 } 2552 2553 private final void handleServiceArgs(ServiceArgsData data) { 2554 Service s = mServices.get(data.token); 2555 if (s != null) { 2556 try { 2557 if (data.args != null) { 2558 data.args.setExtrasClassLoader(s.getClassLoader()); 2559 } 2560 s.onStart(data.args, data.startId); 2561 try { 2562 ActivityManagerNative.getDefault().serviceDoneExecuting(data.token); 2563 } catch (RemoteException e) { 2564 // nothing to do. 2565 } 2566 } catch (Exception e) { 2567 if (!mInstrumentation.onException(s, e)) { 2568 throw new RuntimeException( 2569 "Unable to start service " + s 2570 + " with " + data.args + ": " + e.toString(), e); 2571 } 2572 } 2573 } 2574 } 2575 2576 private final void handleStopService(IBinder token) { 2577 Service s = mServices.remove(token); 2578 if (s != null) { 2579 try { 2580 if (localLOGV) Log.v(TAG, "Destroying service " + s); 2581 s.onDestroy(); 2582 Context context = s.getBaseContext(); 2583 if (context instanceof ApplicationContext) { 2584 final String who = s.getClassName(); 2585 ((ApplicationContext) context).scheduleFinalCleanup(who, "Service"); 2586 } 2587 try { 2588 ActivityManagerNative.getDefault().serviceDoneExecuting(token); 2589 } catch (RemoteException e) { 2590 // nothing to do. 2591 } 2592 } catch (Exception e) { 2593 if (!mInstrumentation.onException(s, e)) { 2594 throw new RuntimeException( 2595 "Unable to stop service " + s 2596 + ": " + e.toString(), e); 2597 } 2598 } 2599 } 2600 //Log.i(TAG, "Running services: " + mServices); 2601 } 2602 2603 public final ActivityRecord performResumeActivity(IBinder token, 2604 boolean clearHide) { 2605 ActivityRecord r = mActivities.get(token); 2606 if (localLOGV) Log.v(TAG, "Performing resume of " + r 2607 + " finished=" + r.activity.mFinished); 2608 if (r != null && !r.activity.mFinished) { 2609 if (clearHide) { 2610 r.hideForNow = false; 2611 r.activity.mStartedActivity = false; 2612 } 2613 try { 2614 if (r.pendingIntents != null) { 2615 deliverNewIntents(r, r.pendingIntents); 2616 r.pendingIntents = null; 2617 } 2618 if (r.pendingResults != null) { 2619 deliverResults(r, r.pendingResults); 2620 r.pendingResults = null; 2621 } 2622 r.activity.performResume(); 2623 2624 EventLog.writeEvent(LOG_ON_RESUME_CALLED, 2625 r.activity.getComponentName().getClassName()); 2626 2627 r.paused = false; 2628 r.stopped = false; 2629 if (r.activity.mStartedActivity) { 2630 r.hideForNow = true; 2631 } 2632 r.state = null; 2633 } catch (Exception e) { 2634 if (!mInstrumentation.onException(r.activity, e)) { 2635 throw new RuntimeException( 2636 "Unable to resume activity " 2637 + r.intent.getComponent().toShortString() 2638 + ": " + e.toString(), e); 2639 } 2640 } 2641 } 2642 return r; 2643 } 2644 2645 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) { 2646 // If we are getting ready to gc after going to the background, well 2647 // we are back active so skip it. 2648 unscheduleGcIdler(); 2649 2650 ActivityRecord r = performResumeActivity(token, clearHide); 2651 2652 if (r != null) { 2653 final Activity a = r.activity; 2654 2655 if (localLOGV) Log.v( 2656 TAG, "Resume " + r + " started activity: " + 2657 a.mStartedActivity + ", hideForNow: " + r.hideForNow 2658 + ", finished: " + a.mFinished); 2659 2660 final int forwardBit = isForward ? 2661 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0; 2662 2663 // If the window hasn't yet been added to the window manager, 2664 // and this guy didn't finish itself or start another activity, 2665 // then go ahead and add the window. 2666 if (r.window == null && !a.mFinished && !a.mStartedActivity) { 2667 r.window = r.activity.getWindow(); 2668 View decor = r.window.getDecorView(); 2669 decor.setVisibility(View.INVISIBLE); 2670 ViewManager wm = a.getWindowManager(); 2671 WindowManager.LayoutParams l = r.window.getAttributes(); 2672 a.mDecor = decor; 2673 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 2674 l.softInputMode |= forwardBit; 2675 if (a.mVisibleFromClient) { 2676 a.mWindowAdded = true; 2677 wm.addView(decor, l); 2678 } 2679 2680 // If the window has already been added, but during resume 2681 // we started another activity, then don't yet make the 2682 // window visisble. 2683 } else if (a.mStartedActivity) { 2684 if (localLOGV) Log.v( 2685 TAG, "Launch " + r + " mStartedActivity set"); 2686 r.hideForNow = true; 2687 } 2688 2689 // The window is now visible if it has been added, we are not 2690 // simply finishing, and we are not starting another activity. 2691 if (!r.activity.mFinished && r.activity.mDecor != null 2692 && !r.hideForNow) { 2693 if (r.newConfig != null) { 2694 performConfigurationChanged(r.activity, r.newConfig); 2695 r.newConfig = null; 2696 } 2697 if (localLOGV) Log.v(TAG, "Resuming " + r + " with isForward=" 2698 + isForward); 2699 WindowManager.LayoutParams l = r.window.getAttributes(); 2700 if ((l.softInputMode 2701 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) 2702 != forwardBit) { 2703 l.softInputMode = (l.softInputMode 2704 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)) 2705 | forwardBit; 2706 ViewManager wm = a.getWindowManager(); 2707 View decor = r.window.getDecorView(); 2708 wm.updateViewLayout(decor, l); 2709 } 2710 r.activity.mVisibleFromServer = true; 2711 mNumVisibleActivities++; 2712 if (r.activity.mVisibleFromClient) { 2713 r.activity.makeVisible(); 2714 } 2715 } 2716 2717 r.nextIdle = mNewActivities; 2718 mNewActivities = r; 2719 if (localLOGV) Log.v( 2720 TAG, "Scheduling idle handler for " + r); 2721 Looper.myQueue().addIdleHandler(new Idler()); 2722 2723 } else { 2724 // If an exception was thrown when trying to resume, then 2725 // just end this activity. 2726 try { 2727 ActivityManagerNative.getDefault() 2728 .finishActivity(token, Activity.RESULT_CANCELED, null); 2729 } catch (RemoteException ex) { 2730 } 2731 } 2732 } 2733 2734 private int mThumbnailWidth = -1; 2735 private int mThumbnailHeight = -1; 2736 2737 private final Bitmap createThumbnailBitmap(ActivityRecord r) { 2738 Bitmap thumbnail = null; 2739 try { 2740 int w = mThumbnailWidth; 2741 int h; 2742 if (w < 0) { 2743 Resources res = r.activity.getResources(); 2744 mThumbnailHeight = h = 2745 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); 2746 2747 mThumbnailWidth = w = 2748 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); 2749 } else { 2750 h = mThumbnailHeight; 2751 } 2752 2753 // XXX Only set hasAlpha if needed? 2754 thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565); 2755 thumbnail.eraseColor(0); 2756 Canvas cv = new Canvas(thumbnail); 2757 if (!r.activity.onCreateThumbnail(thumbnail, cv)) { 2758 thumbnail = null; 2759 } 2760 } catch (Exception e) { 2761 if (!mInstrumentation.onException(r.activity, e)) { 2762 throw new RuntimeException( 2763 "Unable to create thumbnail of " 2764 + r.intent.getComponent().toShortString() 2765 + ": " + e.toString(), e); 2766 } 2767 thumbnail = null; 2768 } 2769 2770 return thumbnail; 2771 } 2772 2773 private final void handlePauseActivity(IBinder token, boolean finished, 2774 boolean userLeaving, int configChanges) { 2775 ActivityRecord r = mActivities.get(token); 2776 if (r != null) { 2777 //Log.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); 2778 if (userLeaving) { 2779 performUserLeavingActivity(r); 2780 } 2781 2782 r.activity.mConfigChangeFlags |= configChanges; 2783 Bundle state = performPauseActivity(token, finished, true); 2784 2785 // Tell the activity manager we have paused. 2786 try { 2787 ActivityManagerNative.getDefault().activityPaused(token, state); 2788 } catch (RemoteException ex) { 2789 } 2790 } 2791 } 2792 2793 final void performUserLeavingActivity(ActivityRecord r) { 2794 mInstrumentation.callActivityOnUserLeaving(r.activity); 2795 } 2796 2797 final Bundle performPauseActivity(IBinder token, boolean finished, 2798 boolean saveState) { 2799 ActivityRecord r = mActivities.get(token); 2800 return r != null ? performPauseActivity(r, finished, saveState) : null; 2801 } 2802 2803 final Bundle performPauseActivity(ActivityRecord r, boolean finished, 2804 boolean saveState) { 2805 if (r.paused) { 2806 if (r.activity.mFinished) { 2807 // If we are finishing, we won't call onResume() in certain cases. 2808 // So here we likewise don't want to call onPause() if the activity 2809 // isn't resumed. 2810 return null; 2811 } 2812 RuntimeException e = new RuntimeException( 2813 "Performing pause of activity that is not resumed: " 2814 + r.intent.getComponent().toShortString()); 2815 Log.e(TAG, e.getMessage(), e); 2816 } 2817 Bundle state = null; 2818 if (finished) { 2819 r.activity.mFinished = true; 2820 } 2821 try { 2822 // Next have the activity save its current state and managed dialogs... 2823 if (!r.activity.mFinished && saveState) { 2824 state = new Bundle(); 2825 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); 2826 r.state = state; 2827 } 2828 // Now we are idle. 2829 r.activity.mCalled = false; 2830 mInstrumentation.callActivityOnPause(r.activity); 2831 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName()); 2832 if (!r.activity.mCalled) { 2833 throw new SuperNotCalledException( 2834 "Activity " + r.intent.getComponent().toShortString() + 2835 " did not call through to super.onPause()"); 2836 } 2837 2838 } catch (SuperNotCalledException e) { 2839 throw e; 2840 2841 } catch (Exception e) { 2842 if (!mInstrumentation.onException(r.activity, e)) { 2843 throw new RuntimeException( 2844 "Unable to pause activity " 2845 + r.intent.getComponent().toShortString() 2846 + ": " + e.toString(), e); 2847 } 2848 } 2849 r.paused = true; 2850 return state; 2851 } 2852 2853 final void performStopActivity(IBinder token) { 2854 ActivityRecord r = mActivities.get(token); 2855 performStopActivityInner(r, null, false); 2856 } 2857 2858 private static class StopInfo { 2859 Bitmap thumbnail; 2860 CharSequence description; 2861 } 2862 2863 private final class ProviderRefCount { 2864 public int count; 2865 ProviderRefCount(int pCount) { 2866 count = pCount; 2867 } 2868 } 2869 2870 private final void performStopActivityInner(ActivityRecord r, 2871 StopInfo info, boolean keepShown) { 2872 if (localLOGV) Log.v(TAG, "Performing stop of " + r); 2873 if (r != null) { 2874 if (!keepShown && r.stopped) { 2875 if (r.activity.mFinished) { 2876 // If we are finishing, we won't call onResume() in certain 2877 // cases. So here we likewise don't want to call onStop() 2878 // if the activity isn't resumed. 2879 return; 2880 } 2881 RuntimeException e = new RuntimeException( 2882 "Performing stop of activity that is not resumed: " 2883 + r.intent.getComponent().toShortString()); 2884 Log.e(TAG, e.getMessage(), e); 2885 } 2886 2887 if (info != null) { 2888 try { 2889 // First create a thumbnail for the activity... 2890 //info.thumbnail = createThumbnailBitmap(r); 2891 info.description = r.activity.onCreateDescription(); 2892 } catch (Exception e) { 2893 if (!mInstrumentation.onException(r.activity, e)) { 2894 throw new RuntimeException( 2895 "Unable to save state of activity " 2896 + r.intent.getComponent().toShortString() 2897 + ": " + e.toString(), e); 2898 } 2899 } 2900 } 2901 2902 if (!keepShown) { 2903 try { 2904 // Now we are idle. 2905 r.activity.performStop(); 2906 } catch (Exception e) { 2907 if (!mInstrumentation.onException(r.activity, e)) { 2908 throw new RuntimeException( 2909 "Unable to stop activity " 2910 + r.intent.getComponent().toShortString() 2911 + ": " + e.toString(), e); 2912 } 2913 } 2914 r.stopped = true; 2915 } 2916 2917 r.paused = true; 2918 } 2919 } 2920 2921 private final void updateVisibility(ActivityRecord r, boolean show) { 2922 View v = r.activity.mDecor; 2923 if (v != null) { 2924 if (show) { 2925 if (!r.activity.mVisibleFromServer) { 2926 r.activity.mVisibleFromServer = true; 2927 mNumVisibleActivities++; 2928 if (r.activity.mVisibleFromClient) { 2929 r.activity.makeVisible(); 2930 } 2931 } 2932 if (r.newConfig != null) { 2933 performConfigurationChanged(r.activity, r.newConfig); 2934 r.newConfig = null; 2935 } 2936 } else { 2937 if (r.activity.mVisibleFromServer) { 2938 r.activity.mVisibleFromServer = false; 2939 mNumVisibleActivities--; 2940 v.setVisibility(View.INVISIBLE); 2941 } 2942 } 2943 } 2944 } 2945 2946 private final void handleStopActivity(IBinder token, boolean show, int configChanges) { 2947 ActivityRecord r = mActivities.get(token); 2948 r.activity.mConfigChangeFlags |= configChanges; 2949 2950 StopInfo info = new StopInfo(); 2951 performStopActivityInner(r, info, show); 2952 2953 if (localLOGV) Log.v( 2954 TAG, "Finishing stop of " + r + ": show=" + show 2955 + " win=" + r.window); 2956 2957 updateVisibility(r, show); 2958 2959 // Tell activity manager we have been stopped. 2960 try { 2961 ActivityManagerNative.getDefault().activityStopped( 2962 r.token, info.thumbnail, info.description); 2963 } catch (RemoteException ex) { 2964 } 2965 } 2966 2967 final void performRestartActivity(IBinder token) { 2968 ActivityRecord r = mActivities.get(token); 2969 if (r.stopped) { 2970 r.activity.performRestart(); 2971 r.stopped = false; 2972 } 2973 } 2974 2975 private final void handleWindowVisibility(IBinder token, boolean show) { 2976 ActivityRecord r = mActivities.get(token); 2977 if (!show && !r.stopped) { 2978 performStopActivityInner(r, null, show); 2979 } else if (show && r.stopped) { 2980 // If we are getting ready to gc after going to the background, well 2981 // we are back active so skip it. 2982 unscheduleGcIdler(); 2983 2984 r.activity.performRestart(); 2985 r.stopped = false; 2986 } 2987 if (r.activity.mDecor != null) { 2988 if (Config.LOGV) Log.v( 2989 TAG, "Handle window " + r + " visibility: " + show); 2990 updateVisibility(r, show); 2991 } 2992 } 2993 2994 private final void deliverResults(ActivityRecord r, List<ResultInfo> results) { 2995 final int N = results.size(); 2996 for (int i=0; i<N; i++) { 2997 ResultInfo ri = results.get(i); 2998 try { 2999 if (ri.mData != null) { 3000 ri.mData.setExtrasClassLoader(r.activity.getClassLoader()); 3001 } 3002 if (DEBUG_RESULTS) Log.v(TAG, 3003 "Delivering result to activity " + r + " : " + ri); 3004 r.activity.dispatchActivityResult(ri.mResultWho, 3005 ri.mRequestCode, ri.mResultCode, ri.mData); 3006 } catch (Exception e) { 3007 if (!mInstrumentation.onException(r.activity, e)) { 3008 throw new RuntimeException( 3009 "Failure delivering result " + ri + " to activity " 3010 + r.intent.getComponent().toShortString() 3011 + ": " + e.toString(), e); 3012 } 3013 } 3014 } 3015 } 3016 3017 private final void handleSendResult(ResultData res) { 3018 ActivityRecord r = mActivities.get(res.token); 3019 if (DEBUG_RESULTS) Log.v(TAG, "Handling send result to " + r); 3020 if (r != null) { 3021 final boolean resumed = !r.paused; 3022 if (!r.activity.mFinished && r.activity.mDecor != null 3023 && r.hideForNow && resumed) { 3024 // We had hidden the activity because it started another 3025 // one... we have gotten a result back and we are not 3026 // paused, so make sure our window is visible. 3027 updateVisibility(r, true); 3028 } 3029 if (resumed) { 3030 try { 3031 // Now we are idle. 3032 r.activity.mCalled = false; 3033 mInstrumentation.callActivityOnPause(r.activity); 3034 if (!r.activity.mCalled) { 3035 throw new SuperNotCalledException( 3036 "Activity " + r.intent.getComponent().toShortString() 3037 + " did not call through to super.onPause()"); 3038 } 3039 } catch (SuperNotCalledException e) { 3040 throw e; 3041 } catch (Exception e) { 3042 if (!mInstrumentation.onException(r.activity, e)) { 3043 throw new RuntimeException( 3044 "Unable to pause activity " 3045 + r.intent.getComponent().toShortString() 3046 + ": " + e.toString(), e); 3047 } 3048 } 3049 } 3050 deliverResults(r, res.results); 3051 if (resumed) { 3052 mInstrumentation.callActivityOnResume(r.activity); 3053 } 3054 } 3055 } 3056 3057 public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) { 3058 return performDestroyActivity(token, finishing, 0, false); 3059 } 3060 3061 private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing, 3062 int configChanges, boolean getNonConfigInstance) { 3063 ActivityRecord r = mActivities.get(token); 3064 if (localLOGV) Log.v(TAG, "Performing finish of " + r); 3065 if (r != null) { 3066 r.activity.mConfigChangeFlags |= configChanges; 3067 if (finishing) { 3068 r.activity.mFinished = true; 3069 } 3070 if (!r.paused) { 3071 try { 3072 r.activity.mCalled = false; 3073 mInstrumentation.callActivityOnPause(r.activity); 3074 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, 3075 r.activity.getComponentName().getClassName()); 3076 if (!r.activity.mCalled) { 3077 throw new SuperNotCalledException( 3078 "Activity " + r.intent.getComponent().toShortString() 3079 + " did not call through to super.onPause()"); 3080 } 3081 } catch (SuperNotCalledException e) { 3082 throw e; 3083 } catch (Exception e) { 3084 if (!mInstrumentation.onException(r.activity, e)) { 3085 throw new RuntimeException( 3086 "Unable to pause activity " 3087 + r.intent.getComponent().toShortString() 3088 + ": " + e.toString(), e); 3089 } 3090 } 3091 r.paused = true; 3092 } 3093 if (!r.stopped) { 3094 try { 3095 r.activity.performStop(); 3096 } catch (SuperNotCalledException e) { 3097 throw e; 3098 } catch (Exception e) { 3099 if (!mInstrumentation.onException(r.activity, e)) { 3100 throw new RuntimeException( 3101 "Unable to stop activity " 3102 + r.intent.getComponent().toShortString() 3103 + ": " + e.toString(), e); 3104 } 3105 } 3106 r.stopped = true; 3107 } 3108 if (getNonConfigInstance) { 3109 try { 3110 r.lastNonConfigurationInstance 3111 = r.activity.onRetainNonConfigurationInstance(); 3112 } catch (Exception e) { 3113 if (!mInstrumentation.onException(r.activity, e)) { 3114 throw new RuntimeException( 3115 "Unable to retain activity " 3116 + r.intent.getComponent().toShortString() 3117 + ": " + e.toString(), e); 3118 } 3119 } 3120 try { 3121 r.lastNonConfigurationChildInstances 3122 = r.activity.onRetainNonConfigurationChildInstances(); 3123 } catch (Exception e) { 3124 if (!mInstrumentation.onException(r.activity, e)) { 3125 throw new RuntimeException( 3126 "Unable to retain child activities " 3127 + r.intent.getComponent().toShortString() 3128 + ": " + e.toString(), e); 3129 } 3130 } 3131 3132 } 3133 try { 3134 r.activity.mCalled = false; 3135 r.activity.onDestroy(); 3136 if (!r.activity.mCalled) { 3137 throw new SuperNotCalledException( 3138 "Activity " + r.intent.getComponent().toShortString() + 3139 " did not call through to super.onDestroy()"); 3140 } 3141 if (r.window != null) { 3142 r.window.closeAllPanels(); 3143 } 3144 } catch (SuperNotCalledException e) { 3145 throw e; 3146 } catch (Exception e) { 3147 if (!mInstrumentation.onException(r.activity, e)) { 3148 throw new RuntimeException( 3149 "Unable to destroy activity " 3150 + r.intent.getComponent().toShortString() 3151 + ": " + e.toString(), e); 3152 } 3153 } 3154 } 3155 mActivities.remove(token); 3156 3157 return r; 3158 } 3159 3160 private final void handleDestroyActivity(IBinder token, boolean finishing, 3161 int configChanges, boolean getNonConfigInstance) { 3162 ActivityRecord r = performDestroyActivity(token, finishing, 3163 configChanges, getNonConfigInstance); 3164 if (r != null) { 3165 WindowManager wm = r.activity.getWindowManager(); 3166 View v = r.activity.mDecor; 3167 if (v != null) { 3168 if (r.activity.mVisibleFromServer) { 3169 mNumVisibleActivities--; 3170 } 3171 IBinder wtoken = v.getWindowToken(); 3172 if (r.activity.mWindowAdded) { 3173 wm.removeViewImmediate(v); 3174 } 3175 if (wtoken != null) { 3176 WindowManagerImpl.getDefault().closeAll(wtoken, 3177 r.activity.getClass().getName(), "Activity"); 3178 } 3179 r.activity.mDecor = null; 3180 } 3181 WindowManagerImpl.getDefault().closeAll(token, 3182 r.activity.getClass().getName(), "Activity"); 3183 3184 // Mocked out contexts won't be participating in the normal 3185 // process lifecycle, but if we're running with a proper 3186 // ApplicationContext we need to have it tear down things 3187 // cleanly. 3188 Context c = r.activity.getBaseContext(); 3189 if (c instanceof ApplicationContext) { 3190 ((ApplicationContext) c).scheduleFinalCleanup( 3191 r.activity.getClass().getName(), "Activity"); 3192 } 3193 } 3194 if (finishing) { 3195 try { 3196 ActivityManagerNative.getDefault().activityDestroyed(token); 3197 } catch (RemoteException ex) { 3198 // If the system process has died, it's game over for everyone. 3199 } 3200 } 3201 } 3202 3203 private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) { 3204 // If we are getting ready to gc after going to the background, well 3205 // we are back active so skip it. 3206 unscheduleGcIdler(); 3207 3208 Configuration changedConfig = null; 3209 3210 // First: make sure we have the most recent configuration and most 3211 // recent version of the activity, or skip it if some previous call 3212 // had taken a more recent version. 3213 synchronized (mRelaunchingActivities) { 3214 int N = mRelaunchingActivities.size(); 3215 IBinder token = tmp.token; 3216 tmp = null; 3217 for (int i=0; i<N; i++) { 3218 ActivityRecord r = mRelaunchingActivities.get(i); 3219 if (r.token == token) { 3220 tmp = r; 3221 mRelaunchingActivities.remove(i); 3222 i--; 3223 N--; 3224 } 3225 } 3226 3227 if (tmp == null) { 3228 return; 3229 } 3230 3231 if (mPendingConfiguration != null) { 3232 changedConfig = mPendingConfiguration; 3233 mPendingConfiguration = null; 3234 } 3235 } 3236 3237 // If there was a pending configuration change, execute it first. 3238 if (changedConfig != null) { 3239 handleConfigurationChanged(changedConfig); 3240 } 3241 3242 ActivityRecord r = mActivities.get(tmp.token); 3243 if (localLOGV) Log.v(TAG, "Handling relaunch of " + r); 3244 if (r == null) { 3245 return; 3246 } 3247 3248 r.activity.mConfigChangeFlags |= configChanges; 3249 Intent currentIntent = r.activity.mIntent; 3250 3251 Bundle savedState = null; 3252 if (!r.paused) { 3253 savedState = performPauseActivity(r.token, false, true); 3254 } 3255 3256 handleDestroyActivity(r.token, false, configChanges, true); 3257 3258 r.activity = null; 3259 r.window = null; 3260 r.hideForNow = false; 3261 r.nextIdle = null; 3262 // Merge any pending results and pending intents; don't just replace them 3263 if (tmp.pendingResults != null) { 3264 if (r.pendingResults == null) { 3265 r.pendingResults = tmp.pendingResults; 3266 } else { 3267 r.pendingResults.addAll(tmp.pendingResults); 3268 } 3269 } 3270 if (tmp.pendingIntents != null) { 3271 if (r.pendingIntents == null) { 3272 r.pendingIntents = tmp.pendingIntents; 3273 } else { 3274 r.pendingIntents.addAll(tmp.pendingIntents); 3275 } 3276 } 3277 r.startsNotResumed = tmp.startsNotResumed; 3278 if (savedState != null) { 3279 r.state = savedState; 3280 } 3281 3282 handleLaunchActivity(r, currentIntent); 3283 } 3284 3285 private final void handleRequestThumbnail(IBinder token) { 3286 ActivityRecord r = mActivities.get(token); 3287 Bitmap thumbnail = createThumbnailBitmap(r); 3288 CharSequence description = null; 3289 try { 3290 description = r.activity.onCreateDescription(); 3291 } catch (Exception e) { 3292 if (!mInstrumentation.onException(r.activity, e)) { 3293 throw new RuntimeException( 3294 "Unable to create description of activity " 3295 + r.intent.getComponent().toShortString() 3296 + ": " + e.toString(), e); 3297 } 3298 } 3299 //System.out.println("Reporting top thumbnail " + thumbnail); 3300 try { 3301 ActivityManagerNative.getDefault().reportThumbnail( 3302 token, thumbnail, description); 3303 } catch (RemoteException ex) { 3304 } 3305 } 3306 3307 ArrayList<ComponentCallbacks> collectComponentCallbacksLocked( 3308 boolean allActivities, Configuration newConfig) { 3309 ArrayList<ComponentCallbacks> callbacks 3310 = new ArrayList<ComponentCallbacks>(); 3311 3312 if (mActivities.size() > 0) { 3313 Iterator<ActivityRecord> it = mActivities.values().iterator(); 3314 while (it.hasNext()) { 3315 ActivityRecord ar = it.next(); 3316 Activity a = ar.activity; 3317 if (a != null) { 3318 if (!ar.activity.mFinished && (allActivities || 3319 (a != null && !ar.paused))) { 3320 // If the activity is currently resumed, its configuration 3321 // needs to change right now. 3322 callbacks.add(a); 3323 } else if (newConfig != null) { 3324 // Otherwise, we will tell it about the change 3325 // the next time it is resumed or shown. Note that 3326 // the activity manager may, before then, decide the 3327 // activity needs to be destroyed to handle its new 3328 // configuration. 3329 ar.newConfig = newConfig; 3330 } 3331 } 3332 } 3333 } 3334 if (mServices.size() > 0) { 3335 Iterator<Service> it = mServices.values().iterator(); 3336 while (it.hasNext()) { 3337 callbacks.add(it.next()); 3338 } 3339 } 3340 synchronized (mProviderMap) { 3341 if (mLocalProviders.size() > 0) { 3342 Iterator<ProviderRecord> it = mLocalProviders.values().iterator(); 3343 while (it.hasNext()) { 3344 callbacks.add(it.next().mLocalProvider); 3345 } 3346 } 3347 } 3348 final int N = mAllApplications.size(); 3349 for (int i=0; i<N; i++) { 3350 callbacks.add(mAllApplications.get(i)); 3351 } 3352 3353 return callbacks; 3354 } 3355 3356 private final void performConfigurationChanged( 3357 ComponentCallbacks cb, Configuration config) { 3358 // Only for Activity objects, check that they actually call up to their 3359 // superclass implementation. ComponentCallbacks is an interface, so 3360 // we check the runtime type and act accordingly. 3361 Activity activity = (cb instanceof Activity) ? (Activity) cb : null; 3362 if (activity != null) { 3363 activity.mCalled = false; 3364 } 3365 3366 boolean shouldChangeConfig = false; 3367 if ((activity == null) || (activity.mCurrentConfig == null)) { 3368 shouldChangeConfig = true; 3369 } else { 3370 3371 // If the new config is the same as the config this Activity 3372 // is already running with then don't bother calling 3373 // onConfigurationChanged 3374 int diff = activity.mCurrentConfig.diff(config); 3375 if (diff != 0) { 3376 3377 // If this activity doesn't handle any of the config changes 3378 // then don't bother calling onConfigurationChanged as we're 3379 // going to destroy it. 3380 if ((~activity.mActivityInfo.configChanges & diff) == 0) { 3381 shouldChangeConfig = true; 3382 } 3383 } 3384 } 3385 3386 if (shouldChangeConfig) { 3387 cb.onConfigurationChanged(config); 3388 3389 if (activity != null) { 3390 if (!activity.mCalled) { 3391 throw new SuperNotCalledException( 3392 "Activity " + activity.getLocalClassName() + 3393 " did not call through to super.onConfigurationChanged()"); 3394 } 3395 activity.mConfigChangeFlags = 0; 3396 activity.mCurrentConfig = new Configuration(config); 3397 } 3398 } 3399 } 3400 3401 final void handleConfigurationChanged(Configuration config) { 3402 3403 synchronized (mRelaunchingActivities) { 3404 if (mPendingConfiguration != null) { 3405 config = mPendingConfiguration; 3406 mPendingConfiguration = null; 3407 } 3408 } 3409 3410 ArrayList<ComponentCallbacks> callbacks 3411 = new ArrayList<ComponentCallbacks>(); 3412 3413 synchronized(mPackages) { 3414 if (mConfiguration == null) { 3415 mConfiguration = new Configuration(); 3416 } 3417 mConfiguration.updateFrom(config); 3418 DisplayMetrics dm = getDisplayMetricsLocked(true); 3419 3420 // set it for java, this also affects newly created Resources 3421 if (config.locale != null) { 3422 Locale.setDefault(config.locale); 3423 } 3424 3425 Resources.updateSystemConfiguration(config, null); 3426 3427 ApplicationContext.ApplicationPackageManager.configurationChanged(); 3428 //Log.i(TAG, "Configuration changed in " + currentPackageName()); 3429 { 3430 Iterator<WeakReference<Resources>> it = 3431 mActiveResources.values().iterator(); 3432 //Iterator<Map.Entry<String, WeakReference<Resources>>> it = 3433 // mActiveResources.entrySet().iterator(); 3434 while (it.hasNext()) { 3435 WeakReference<Resources> v = it.next(); 3436 Resources r = v.get(); 3437 if (r != null) { 3438 r.updateConfiguration(config, dm); 3439 //Log.i(TAG, "Updated app resources " + v.getKey() 3440 // + " " + r + ": " + r.getConfiguration()); 3441 } else { 3442 //Log.i(TAG, "Removing old resources " + v.getKey()); 3443 it.remove(); 3444 } 3445 } 3446 } 3447 3448 callbacks = collectComponentCallbacksLocked(false, config); 3449 } 3450 3451 final int N = callbacks.size(); 3452 for (int i=0; i<N; i++) { 3453 performConfigurationChanged(callbacks.get(i), config); 3454 } 3455 } 3456 3457 final void handleActivityConfigurationChanged(IBinder token) { 3458 ActivityRecord r = mActivities.get(token); 3459 if (r == null || r.activity == null) { 3460 return; 3461 } 3462 3463 performConfigurationChanged(r.activity, mConfiguration); 3464 } 3465 3466 final void handleProfilerControl(boolean start, String path) { 3467 if (start) { 3468 File file = new File(path); 3469 file.getParentFile().mkdirs(); 3470 try { 3471 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 3472 } catch (RuntimeException e) { 3473 Log.w(TAG, "Profiling failed on path " + path 3474 + " -- can the process access this path?"); 3475 } 3476 } else { 3477 Debug.stopMethodTracing(); 3478 } 3479 } 3480 3481 final void handleLowMemory() { 3482 ArrayList<ComponentCallbacks> callbacks 3483 = new ArrayList<ComponentCallbacks>(); 3484 3485 synchronized(mPackages) { 3486 callbacks = collectComponentCallbacksLocked(true, null); 3487 } 3488 3489 final int N = callbacks.size(); 3490 for (int i=0; i<N; i++) { 3491 callbacks.get(i).onLowMemory(); 3492 } 3493 3494 // Ask SQLite to free up as much memory as it can, mostly from its page caches. 3495 if (Process.myUid() != Process.SYSTEM_UID) { 3496 int sqliteReleased = SQLiteDatabase.releaseMemory(); 3497 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); 3498 } 3499 3500 BinderInternal.forceGc("mem"); 3501 } 3502 3503 private final void handleBindApplication(AppBindData data) { 3504 mBoundApplication = data; 3505 mConfiguration = new Configuration(data.config); 3506 3507 // We now rely on this being set by zygote. 3508 //Process.setGid(data.appInfo.gid); 3509 //Process.setUid(data.appInfo.uid); 3510 3511 // send up app name; do this *before* waiting for debugger 3512 android.ddm.DdmHandleAppName.setAppName(data.processName); 3513 3514 /* 3515 * Before spawning a new process, reset the time zone to be the system time zone. 3516 * This needs to be done because the system time zone could have changed after the 3517 * the spawning of this process. Without doing this this process would have the incorrect 3518 * system time zone. 3519 */ 3520 TimeZone.setDefault(null); 3521 3522 /* 3523 * Initialize the default locale in this process for the reasons we set the time zone. 3524 */ 3525 Locale.setDefault(data.config.locale); 3526 3527 data.info = getPackageInfoNoCheck(data.appInfo); 3528 3529 if (data.debugMode != IApplicationThread.DEBUG_OFF) { 3530 // XXX should have option to change the port. 3531 Debug.changeDebugPort(8100); 3532 if (data.debugMode == IApplicationThread.DEBUG_WAIT) { 3533 Log.w(TAG, "Application " + data.info.getPackageName() 3534 + " is waiting for the debugger on port 8100..."); 3535 3536 IActivityManager mgr = ActivityManagerNative.getDefault(); 3537 try { 3538 mgr.showWaitingForDebugger(mAppThread, true); 3539 } catch (RemoteException ex) { 3540 } 3541 3542 Debug.waitForDebugger(); 3543 3544 try { 3545 mgr.showWaitingForDebugger(mAppThread, false); 3546 } catch (RemoteException ex) { 3547 } 3548 3549 } else { 3550 Log.w(TAG, "Application " + data.info.getPackageName() 3551 + " can be debugged on port 8100..."); 3552 } 3553 } 3554 3555 if (data.instrumentationName != null) { 3556 ApplicationContext appContext = new ApplicationContext(); 3557 appContext.init(data.info, null, this); 3558 InstrumentationInfo ii = null; 3559 try { 3560 ii = appContext.getPackageManager(). 3561 getInstrumentationInfo(data.instrumentationName, 0); 3562 } catch (PackageManager.NameNotFoundException e) { 3563 } 3564 if (ii == null) { 3565 throw new RuntimeException( 3566 "Unable to find instrumentation info for: " 3567 + data.instrumentationName); 3568 } 3569 3570 mInstrumentationAppDir = ii.sourceDir; 3571 mInstrumentationAppPackage = ii.packageName; 3572 mInstrumentedAppDir = data.info.getAppDir(); 3573 3574 ApplicationInfo instrApp = new ApplicationInfo(); 3575 instrApp.packageName = ii.packageName; 3576 instrApp.sourceDir = ii.sourceDir; 3577 instrApp.publicSourceDir = ii.publicSourceDir; 3578 instrApp.dataDir = ii.dataDir; 3579 PackageInfo pi = getPackageInfo(instrApp, 3580 appContext.getClassLoader(), false, true); 3581 ApplicationContext instrContext = new ApplicationContext(); 3582 instrContext.init(pi, null, this); 3583 3584 try { 3585 java.lang.ClassLoader cl = instrContext.getClassLoader(); 3586 mInstrumentation = (Instrumentation) 3587 cl.loadClass(data.instrumentationName.getClassName()).newInstance(); 3588 } catch (Exception e) { 3589 throw new RuntimeException( 3590 "Unable to instantiate instrumentation " 3591 + data.instrumentationName + ": " + e.toString(), e); 3592 } 3593 3594 mInstrumentation.init(this, instrContext, appContext, 3595 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher); 3596 3597 if (data.profileFile != null && !ii.handleProfiling) { 3598 data.handlingProfiling = true; 3599 File file = new File(data.profileFile); 3600 file.getParentFile().mkdirs(); 3601 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 3602 } 3603 3604 try { 3605 mInstrumentation.onCreate(data.instrumentationArgs); 3606 } 3607 catch (Exception e) { 3608 throw new RuntimeException( 3609 "Exception thrown in onCreate() of " 3610 + data.instrumentationName + ": " + e.toString(), e); 3611 } 3612 3613 } else { 3614 mInstrumentation = new Instrumentation(); 3615 } 3616 3617 Application app = data.info.makeApplication(); 3618 mInitialApplication = app; 3619 3620 List<ProviderInfo> providers = data.providers; 3621 if (providers != null) { 3622 installContentProviders(app, providers); 3623 } 3624 3625 try { 3626 mInstrumentation.callApplicationOnCreate(app); 3627 } catch (Exception e) { 3628 if (!mInstrumentation.onException(app, e)) { 3629 throw new RuntimeException( 3630 "Unable to create application " + app.getClass().getName() 3631 + ": " + e.toString(), e); 3632 } 3633 } 3634 } 3635 3636 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) { 3637 IActivityManager am = ActivityManagerNative.getDefault(); 3638 if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) { 3639 Debug.stopMethodTracing(); 3640 } 3641 //Log.i(TAG, "am: " + ActivityManagerNative.getDefault() 3642 // + ", app thr: " + mAppThread); 3643 try { 3644 am.finishInstrumentation(mAppThread, resultCode, results); 3645 } catch (RemoteException ex) { 3646 } 3647 } 3648 3649 private final void installContentProviders( 3650 Context context, List<ProviderInfo> providers) { 3651 final ArrayList<IActivityManager.ContentProviderHolder> results = 3652 new ArrayList<IActivityManager.ContentProviderHolder>(); 3653 3654 Iterator<ProviderInfo> i = providers.iterator(); 3655 while (i.hasNext()) { 3656 ProviderInfo cpi = i.next(); 3657 StringBuilder buf = new StringBuilder(128); 3658 buf.append("Publishing provider "); 3659 buf.append(cpi.authority); 3660 buf.append(": "); 3661 buf.append(cpi.name); 3662 Log.i(TAG, buf.toString()); 3663 IContentProvider cp = installProvider(context, null, cpi, false); 3664 if (cp != null) { 3665 IActivityManager.ContentProviderHolder cph = 3666 new IActivityManager.ContentProviderHolder(cpi); 3667 cph.provider = cp; 3668 results.add(cph); 3669 // Don't ever unload this provider from the process. 3670 synchronized(mProviderMap) { 3671 mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000)); 3672 } 3673 } 3674 } 3675 3676 try { 3677 ActivityManagerNative.getDefault().publishContentProviders( 3678 getApplicationThread(), results); 3679 } catch (RemoteException ex) { 3680 } 3681 } 3682 3683 private final IContentProvider getProvider(Context context, String name) { 3684 synchronized(mProviderMap) { 3685 final ProviderRecord pr = mProviderMap.get(name); 3686 if (pr != null) { 3687 return pr.mProvider; 3688 } 3689 } 3690 3691 IActivityManager.ContentProviderHolder holder = null; 3692 try { 3693 holder = ActivityManagerNative.getDefault().getContentProvider( 3694 getApplicationThread(), name); 3695 } catch (RemoteException ex) { 3696 } 3697 if (holder == null) { 3698 Log.e(TAG, "Failed to find provider info for " + name); 3699 return null; 3700 } 3701 if (holder.permissionFailure != null) { 3702 throw new SecurityException("Permission " + holder.permissionFailure 3703 + " required for provider " + name); 3704 } 3705 3706 IContentProvider prov = installProvider(context, holder.provider, 3707 holder.info, true); 3708 //Log.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded); 3709 if (holder.noReleaseNeeded || holder.provider == null) { 3710 // We are not going to release the provider if it is an external 3711 // provider that doesn't care about being released, or if it is 3712 // a local provider running in this process. 3713 //Log.i(TAG, "*** NO RELEASE NEEDED"); 3714 synchronized(mProviderMap) { 3715 mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000)); 3716 } 3717 } 3718 return prov; 3719 } 3720 3721 public final IContentProvider acquireProvider(Context c, String name) { 3722 IContentProvider provider = getProvider(c, name); 3723 if(provider == null) 3724 return null; 3725 IBinder jBinder = provider.asBinder(); 3726 synchronized(mProviderMap) { 3727 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 3728 if(prc == null) { 3729 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); 3730 } else { 3731 prc.count++; 3732 } //end else 3733 } //end synchronized 3734 return provider; 3735 } 3736 3737 public final boolean releaseProvider(IContentProvider provider) { 3738 if(provider == null) { 3739 return false; 3740 } 3741 IBinder jBinder = provider.asBinder(); 3742 synchronized(mProviderMap) { 3743 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 3744 if(prc == null) { 3745 if(localLOGV) Log.v(TAG, "releaseProvider::Weird shouldnt be here"); 3746 return false; 3747 } else { 3748 prc.count--; 3749 if(prc.count == 0) { 3750 mProviderRefCountMap.remove(jBinder); 3751 //invoke removeProvider to dereference provider 3752 removeProviderLocked(provider); 3753 } //end if 3754 } //end else 3755 } //end synchronized 3756 return true; 3757 } 3758 3759 public final void removeProviderLocked(IContentProvider provider) { 3760 if (provider == null) { 3761 return; 3762 } 3763 IBinder providerBinder = provider.asBinder(); 3764 boolean amRemoveFlag = false; 3765 3766 // remove the provider from mProviderMap 3767 Iterator<ProviderRecord> iter = mProviderMap.values().iterator(); 3768 while (iter.hasNext()) { 3769 ProviderRecord pr = iter.next(); 3770 IBinder myBinder = pr.mProvider.asBinder(); 3771 if (myBinder == providerBinder) { 3772 //find if its published by this process itself 3773 if(pr.mLocalProvider != null) { 3774 if(localLOGV) Log.i(TAG, "removeProvider::found local provider returning"); 3775 return; 3776 } 3777 if(localLOGV) Log.v(TAG, "removeProvider::Not local provider Unlinking " + 3778 "death recipient"); 3779 //content provider is in another process 3780 myBinder.unlinkToDeath(pr, 0); 3781 iter.remove(); 3782 //invoke remove only once for the very first name seen 3783 if(!amRemoveFlag) { 3784 try { 3785 if(localLOGV) Log.v(TAG, "removeProvider::Invoking " + 3786 "ActivityManagerNative.removeContentProvider("+pr.mName); 3787 ActivityManagerNative.getDefault().removeContentProvider(getApplicationThread(), pr.mName); 3788 amRemoveFlag = true; 3789 } catch (RemoteException e) { 3790 //do nothing content provider object is dead any way 3791 } //end catch 3792 } 3793 } //end if myBinder 3794 } //end while iter 3795 } 3796 3797 final void removeDeadProvider(String name, IContentProvider provider) { 3798 synchronized(mProviderMap) { 3799 ProviderRecord pr = mProviderMap.get(name); 3800 if (pr.mProvider.asBinder() == provider.asBinder()) { 3801 Log.i(TAG, "Removing dead content provider: " + name); 3802 mProviderMap.remove(name); 3803 } 3804 } 3805 } 3806 3807 final void removeDeadProviderLocked(String name, IContentProvider provider) { 3808 ProviderRecord pr = mProviderMap.get(name); 3809 if (pr.mProvider.asBinder() == provider.asBinder()) { 3810 Log.i(TAG, "Removing dead content provider: " + name); 3811 mProviderMap.remove(name); 3812 } 3813 } 3814 3815 private final IContentProvider installProvider(Context context, 3816 IContentProvider provider, ProviderInfo info, boolean noisy) { 3817 ContentProvider localProvider = null; 3818 if (provider == null) { 3819 if (noisy) { 3820 Log.d(TAG, "Loading provider " + info.authority + ": " 3821 + info.name); 3822 } 3823 Context c = null; 3824 ApplicationInfo ai = info.applicationInfo; 3825 if (context.getPackageName().equals(ai.packageName)) { 3826 c = context; 3827 } else if (mInitialApplication != null && 3828 mInitialApplication.getPackageName().equals(ai.packageName)) { 3829 c = mInitialApplication; 3830 } else { 3831 try { 3832 c = context.createPackageContext(ai.packageName, 3833 Context.CONTEXT_INCLUDE_CODE); 3834 } catch (PackageManager.NameNotFoundException e) { 3835 } 3836 } 3837 if (c == null) { 3838 Log.w(TAG, "Unable to get context for package " + 3839 ai.packageName + 3840 " while loading content provider " + 3841 info.name); 3842 return null; 3843 } 3844 try { 3845 final java.lang.ClassLoader cl = c.getClassLoader(); 3846 localProvider = (ContentProvider)cl. 3847 loadClass(info.name).newInstance(); 3848 provider = localProvider.getIContentProvider(); 3849 if (provider == null) { 3850 Log.e(TAG, "Failed to instantiate class " + 3851 info.name + " from sourceDir " + 3852 info.applicationInfo.sourceDir); 3853 return null; 3854 } 3855 if (Config.LOGV) Log.v( 3856 TAG, "Instantiating local provider " + info.name); 3857 // XXX Need to create the correct context for this provider. 3858 localProvider.attachInfo(c, info); 3859 } catch (java.lang.Exception e) { 3860 if (!mInstrumentation.onException(null, e)) { 3861 throw new RuntimeException( 3862 "Unable to get provider " + info.name 3863 + ": " + e.toString(), e); 3864 } 3865 return null; 3866 } 3867 } else if (localLOGV) { 3868 Log.v(TAG, "Installing external provider " + info.authority + ": " 3869 + info.name); 3870 } 3871 3872 synchronized (mProviderMap) { 3873 // Cache the pointer for the remote provider. 3874 String names[] = PATTERN_SEMICOLON.split(info.authority); 3875 for (int i=0; i<names.length; i++) { 3876 ProviderRecord pr = new ProviderRecord(names[i], provider, 3877 localProvider); 3878 try { 3879 provider.asBinder().linkToDeath(pr, 0); 3880 mProviderMap.put(names[i], pr); 3881 } catch (RemoteException e) { 3882 return null; 3883 } 3884 } 3885 if (localProvider != null) { 3886 mLocalProviders.put(provider.asBinder(), 3887 new ProviderRecord(null, provider, localProvider)); 3888 } 3889 } 3890 3891 return provider; 3892 } 3893 3894 private final void attach(boolean system) { 3895 sThreadLocal.set(this); 3896 mSystemThread = system; 3897 AndroidHttpClient.setThreadBlocked(true); 3898 if (!system) { 3899 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>"); 3900 RuntimeInit.setApplicationObject(mAppThread.asBinder()); 3901 IActivityManager mgr = ActivityManagerNative.getDefault(); 3902 try { 3903 mgr.attachApplication(mAppThread); 3904 } catch (RemoteException ex) { 3905 } 3906 } else { 3907 // Don't set application object here -- if the system crashes, 3908 // we can't display an alert, we just want to die die die. 3909 android.ddm.DdmHandleAppName.setAppName("system_process"); 3910 try { 3911 mInstrumentation = new Instrumentation(); 3912 ApplicationContext context = new ApplicationContext(); 3913 context.init(getSystemContext().mPackageInfo, null, this); 3914 Application app = Instrumentation.newApplication(Application.class, context); 3915 mAllApplications.add(app); 3916 mInitialApplication = app; 3917 app.onCreate(); 3918 } catch (Exception e) { 3919 throw new RuntimeException( 3920 "Unable to instantiate Application():" + e.toString(), e); 3921 } 3922 } 3923 } 3924 3925 private final void detach() 3926 { 3927 AndroidHttpClient.setThreadBlocked(false); 3928 sThreadLocal.set(null); 3929 } 3930 3931 public static final ActivityThread systemMain() { 3932 ActivityThread thread = new ActivityThread(); 3933 thread.attach(true); 3934 return thread; 3935 } 3936 3937 public final void installSystemProviders(List providers) { 3938 if (providers != null) { 3939 installContentProviders(mInitialApplication, 3940 (List<ProviderInfo>)providers); 3941 } 3942 } 3943 3944 public static final void main(String[] args) { 3945 Process.setArgV0("<pre-initialized>"); 3946 3947 Looper.prepareMainLooper(); 3948 3949 ActivityThread thread = new ActivityThread(); 3950 thread.attach(false); 3951 3952 Looper.loop(); 3953 3954 if (Process.supportsProcesses()) { 3955 throw new RuntimeException("Main thread loop unexpectedly exited"); 3956 } 3957 3958 thread.detach(); 3959 String name; 3960 if (thread.mInitialApplication != null) name = thread.mInitialApplication.getPackageName(); 3961 else name = "<unknown>"; 3962 Log.i(TAG, "Main thread of " + name + " is now exiting"); 3963 } 3964} 3965