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