ActivityThread.java revision 06de2ea752171f52a4e6e6872cb3a0689e591dcb
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 public void setSchedulingGroup(int group) { 1517 // Note: do this immediately, since going into the foreground 1518 // should happen regardless of what pending work we have to do 1519 // and the activity manager will wait for us to report back that 1520 // we are done before sending us to the background. 1521 try { 1522 Process.setProcessGroup(Process.myPid(), group); 1523 } catch (Exception e) { 1524 Log.w(TAG, "Failed setting process group to " + group, e); 1525 } 1526 } 1527 1528 @Override 1529 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1530 long nativeMax = Debug.getNativeHeapSize() / 1024; 1531 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; 1532 long nativeFree = Debug.getNativeHeapFreeSize() / 1024; 1533 1534 Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); 1535 Debug.getMemoryInfo(memInfo); 1536 1537 final int nativeShared = memInfo.nativeSharedDirty; 1538 final int dalvikShared = memInfo.dalvikSharedDirty; 1539 final int otherShared = memInfo.otherSharedDirty; 1540 1541 final int nativePrivate = memInfo.nativePrivateDirty; 1542 final int dalvikPrivate = memInfo.dalvikPrivateDirty; 1543 final int otherPrivate = memInfo.otherPrivateDirty; 1544 1545 Runtime runtime = Runtime.getRuntime(); 1546 1547 long dalvikMax = runtime.totalMemory() / 1024; 1548 long dalvikFree = runtime.freeMemory() / 1024; 1549 long dalvikAllocated = dalvikMax - dalvikFree; 1550 long viewInstanceCount = ViewDebug.getViewInstanceCount(); 1551 long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount(); 1552 long appContextInstanceCount = ApplicationContext.getInstanceCount(); 1553 long activityInstanceCount = Activity.getInstanceCount(); 1554 int globalAssetCount = AssetManager.getGlobalAssetCount(); 1555 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount(); 1556 int binderLocalObjectCount = Debug.getBinderLocalObjectCount(); 1557 int binderProxyObjectCount = Debug.getBinderProxyObjectCount(); 1558 int binderDeathObjectCount = Debug.getBinderDeathObjectCount(); 1559 int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount(); 1560 long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024; 1561 SQLiteDebug.PagerStats stats = new SQLiteDebug.PagerStats(); 1562 SQLiteDebug.getPagerStats(stats); 1563 1564 // Check to see if we were called by checkin server. If so, print terse format. 1565 boolean doCheckinFormat = false; 1566 if (args != null) { 1567 for (String arg : args) { 1568 if ("-c".equals(arg)) doCheckinFormat = true; 1569 } 1570 } 1571 1572 // For checkin, we print one long comma-separated list of values 1573 if (doCheckinFormat) { 1574 // NOTE: if you change anything significant below, also consider changing 1575 // ACTIVITY_THREAD_CHECKIN_VERSION. 1576 String processName = (mBoundApplication != null) 1577 ? mBoundApplication.processName : "unknown"; 1578 1579 // Header 1580 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(','); 1581 pw.print(Process.myPid()); pw.print(','); 1582 pw.print(processName); pw.print(','); 1583 1584 // Heap info - max 1585 pw.print(nativeMax); pw.print(','); 1586 pw.print(dalvikMax); pw.print(','); 1587 pw.print("N/A,"); 1588 pw.print(nativeMax + dalvikMax); pw.print(','); 1589 1590 // Heap info - allocated 1591 pw.print(nativeAllocated); pw.print(','); 1592 pw.print(dalvikAllocated); pw.print(','); 1593 pw.print("N/A,"); 1594 pw.print(nativeAllocated + dalvikAllocated); pw.print(','); 1595 1596 // Heap info - free 1597 pw.print(nativeFree); pw.print(','); 1598 pw.print(dalvikFree); pw.print(','); 1599 pw.print("N/A,"); 1600 pw.print(nativeFree + dalvikFree); pw.print(','); 1601 1602 // Heap info - proportional set size 1603 pw.print(memInfo.nativePss); pw.print(','); 1604 pw.print(memInfo.dalvikPss); pw.print(','); 1605 pw.print(memInfo.otherPss); pw.print(','); 1606 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(','); 1607 1608 // Heap info - shared 1609 pw.print(nativeShared); pw.print(','); 1610 pw.print(dalvikShared); pw.print(','); 1611 pw.print(otherShared); pw.print(','); 1612 pw.print(nativeShared + dalvikShared + otherShared); pw.print(','); 1613 1614 // Heap info - private 1615 pw.print(nativePrivate); pw.print(','); 1616 pw.print(dalvikPrivate); pw.print(','); 1617 pw.print(otherPrivate); pw.print(','); 1618 pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(','); 1619 1620 // Object counts 1621 pw.print(viewInstanceCount); pw.print(','); 1622 pw.print(viewRootInstanceCount); pw.print(','); 1623 pw.print(appContextInstanceCount); pw.print(','); 1624 pw.print(activityInstanceCount); pw.print(','); 1625 1626 pw.print(globalAssetCount); pw.print(','); 1627 pw.print(globalAssetManagerCount); pw.print(','); 1628 pw.print(binderLocalObjectCount); pw.print(','); 1629 pw.print(binderProxyObjectCount); pw.print(','); 1630 1631 pw.print(binderDeathObjectCount); pw.print(','); 1632 pw.print(openSslSocketCount); pw.print(','); 1633 1634 // SQL 1635 pw.print(sqliteAllocated); pw.print(','); 1636 pw.print(stats.databaseBytes / 1024); pw.print(','); 1637 pw.print(stats.numPagers); pw.print(','); 1638 pw.print((stats.totalBytes - stats.referencedBytes) / 1024); pw.print(','); 1639 pw.print(stats.referencedBytes / 1024); pw.print('\n'); 1640 1641 return; 1642 } 1643 1644 // otherwise, show human-readable format 1645 printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total"); 1646 printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax); 1647 printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A", 1648 nativeAllocated + dalvikAllocated); 1649 printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A", 1650 nativeFree + dalvikFree); 1651 1652 printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss, 1653 memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); 1654 1655 printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared, 1656 nativeShared + dalvikShared + otherShared); 1657 printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate, 1658 nativePrivate + dalvikPrivate + otherPrivate); 1659 1660 pw.println(" "); 1661 pw.println(" Objects"); 1662 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:", 1663 viewRootInstanceCount); 1664 1665 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount, 1666 "Activities:", activityInstanceCount); 1667 1668 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount, 1669 "AssetManagers:", globalAssetManagerCount); 1670 1671 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount, 1672 "Proxy Binders:", binderProxyObjectCount); 1673 printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount); 1674 1675 printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount); 1676 1677 // SQLite mem info 1678 pw.println(" "); 1679 pw.println(" SQL"); 1680 printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "dbFiles:", 1681 stats.databaseBytes / 1024); 1682 printRow(pw, TWO_COUNT_COLUMNS, "numPagers:", stats.numPagers, "inactivePageKB:", 1683 (stats.totalBytes - stats.referencedBytes) / 1024); 1684 printRow(pw, ONE_COUNT_COLUMN, "activePageKB:", stats.referencedBytes / 1024); 1685 } 1686 1687 private void printRow(PrintWriter pw, String format, Object...objs) { 1688 pw.println(String.format(format, objs)); 1689 } 1690 } 1691 1692 private final class H extends Handler { 1693 public static final int LAUNCH_ACTIVITY = 100; 1694 public static final int PAUSE_ACTIVITY = 101; 1695 public static final int PAUSE_ACTIVITY_FINISHING= 102; 1696 public static final int STOP_ACTIVITY_SHOW = 103; 1697 public static final int STOP_ACTIVITY_HIDE = 104; 1698 public static final int SHOW_WINDOW = 105; 1699 public static final int HIDE_WINDOW = 106; 1700 public static final int RESUME_ACTIVITY = 107; 1701 public static final int SEND_RESULT = 108; 1702 public static final int DESTROY_ACTIVITY = 109; 1703 public static final int BIND_APPLICATION = 110; 1704 public static final int EXIT_APPLICATION = 111; 1705 public static final int NEW_INTENT = 112; 1706 public static final int RECEIVER = 113; 1707 public static final int CREATE_SERVICE = 114; 1708 public static final int SERVICE_ARGS = 115; 1709 public static final int STOP_SERVICE = 116; 1710 public static final int REQUEST_THUMBNAIL = 117; 1711 public static final int CONFIGURATION_CHANGED = 118; 1712 public static final int CLEAN_UP_CONTEXT = 119; 1713 public static final int GC_WHEN_IDLE = 120; 1714 public static final int BIND_SERVICE = 121; 1715 public static final int UNBIND_SERVICE = 122; 1716 public static final int DUMP_SERVICE = 123; 1717 public static final int LOW_MEMORY = 124; 1718 public static final int ACTIVITY_CONFIGURATION_CHANGED = 125; 1719 public static final int RELAUNCH_ACTIVITY = 126; 1720 public static final int PROFILER_CONTROL = 127; 1721 String codeToString(int code) { 1722 if (localLOGV) { 1723 switch (code) { 1724 case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY"; 1725 case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY"; 1726 case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING"; 1727 case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW"; 1728 case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE"; 1729 case SHOW_WINDOW: return "SHOW_WINDOW"; 1730 case HIDE_WINDOW: return "HIDE_WINDOW"; 1731 case RESUME_ACTIVITY: return "RESUME_ACTIVITY"; 1732 case SEND_RESULT: return "SEND_RESULT"; 1733 case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY"; 1734 case BIND_APPLICATION: return "BIND_APPLICATION"; 1735 case EXIT_APPLICATION: return "EXIT_APPLICATION"; 1736 case NEW_INTENT: return "NEW_INTENT"; 1737 case RECEIVER: return "RECEIVER"; 1738 case CREATE_SERVICE: return "CREATE_SERVICE"; 1739 case SERVICE_ARGS: return "SERVICE_ARGS"; 1740 case STOP_SERVICE: return "STOP_SERVICE"; 1741 case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL"; 1742 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED"; 1743 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT"; 1744 case GC_WHEN_IDLE: return "GC_WHEN_IDLE"; 1745 case BIND_SERVICE: return "BIND_SERVICE"; 1746 case UNBIND_SERVICE: return "UNBIND_SERVICE"; 1747 case DUMP_SERVICE: return "DUMP_SERVICE"; 1748 case LOW_MEMORY: return "LOW_MEMORY"; 1749 case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED"; 1750 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; 1751 case PROFILER_CONTROL: return "PROFILER_CONTROL"; 1752 } 1753 } 1754 return "(unknown)"; 1755 } 1756 public void handleMessage(Message msg) { 1757 switch (msg.what) { 1758 case LAUNCH_ACTIVITY: { 1759 ActivityRecord r = (ActivityRecord)msg.obj; 1760 1761 r.packageInfo = getPackageInfoNoCheck( 1762 r.activityInfo.applicationInfo); 1763 handleLaunchActivity(r, null); 1764 } break; 1765 case RELAUNCH_ACTIVITY: { 1766 ActivityRecord r = (ActivityRecord)msg.obj; 1767 handleRelaunchActivity(r, msg.arg1); 1768 } break; 1769 case PAUSE_ACTIVITY: 1770 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2); 1771 break; 1772 case PAUSE_ACTIVITY_FINISHING: 1773 handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2); 1774 break; 1775 case STOP_ACTIVITY_SHOW: 1776 handleStopActivity((IBinder)msg.obj, true, msg.arg2); 1777 break; 1778 case STOP_ACTIVITY_HIDE: 1779 handleStopActivity((IBinder)msg.obj, false, msg.arg2); 1780 break; 1781 case SHOW_WINDOW: 1782 handleWindowVisibility((IBinder)msg.obj, true); 1783 break; 1784 case HIDE_WINDOW: 1785 handleWindowVisibility((IBinder)msg.obj, false); 1786 break; 1787 case RESUME_ACTIVITY: 1788 handleResumeActivity((IBinder)msg.obj, true, 1789 msg.arg1 != 0); 1790 break; 1791 case SEND_RESULT: 1792 handleSendResult((ResultData)msg.obj); 1793 break; 1794 case DESTROY_ACTIVITY: 1795 handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0, 1796 msg.arg2, false); 1797 break; 1798 case BIND_APPLICATION: 1799 AppBindData data = (AppBindData)msg.obj; 1800 handleBindApplication(data); 1801 break; 1802 case EXIT_APPLICATION: 1803 if (mInitialApplication != null) { 1804 mInitialApplication.onTerminate(); 1805 } 1806 Looper.myLooper().quit(); 1807 break; 1808 case NEW_INTENT: 1809 handleNewIntent((NewIntentData)msg.obj); 1810 break; 1811 case RECEIVER: 1812 handleReceiver((ReceiverData)msg.obj); 1813 break; 1814 case CREATE_SERVICE: 1815 handleCreateService((CreateServiceData)msg.obj); 1816 break; 1817 case BIND_SERVICE: 1818 handleBindService((BindServiceData)msg.obj); 1819 break; 1820 case UNBIND_SERVICE: 1821 handleUnbindService((BindServiceData)msg.obj); 1822 break; 1823 case SERVICE_ARGS: 1824 handleServiceArgs((ServiceArgsData)msg.obj); 1825 break; 1826 case STOP_SERVICE: 1827 handleStopService((IBinder)msg.obj); 1828 break; 1829 case REQUEST_THUMBNAIL: 1830 handleRequestThumbnail((IBinder)msg.obj); 1831 break; 1832 case CONFIGURATION_CHANGED: 1833 handleConfigurationChanged((Configuration)msg.obj); 1834 break; 1835 case CLEAN_UP_CONTEXT: 1836 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj; 1837 cci.context.performFinalCleanup(cci.who, cci.what); 1838 break; 1839 case GC_WHEN_IDLE: 1840 scheduleGcIdler(); 1841 break; 1842 case DUMP_SERVICE: 1843 handleDumpService((DumpServiceInfo)msg.obj); 1844 break; 1845 case LOW_MEMORY: 1846 handleLowMemory(); 1847 break; 1848 case ACTIVITY_CONFIGURATION_CHANGED: 1849 handleActivityConfigurationChanged((IBinder)msg.obj); 1850 break; 1851 case PROFILER_CONTROL: 1852 handleProfilerControl(msg.arg1 != 0, (String)msg.obj); 1853 break; 1854 } 1855 } 1856 } 1857 1858 private final class Idler implements MessageQueue.IdleHandler { 1859 public final boolean queueIdle() { 1860 ActivityRecord a = mNewActivities; 1861 if (a != null) { 1862 mNewActivities = null; 1863 IActivityManager am = ActivityManagerNative.getDefault(); 1864 ActivityRecord prev; 1865 do { 1866 if (localLOGV) Log.v( 1867 TAG, "Reporting idle of " + a + 1868 " finished=" + 1869 (a.activity != null ? a.activity.mFinished : false)); 1870 if (a.activity != null && !a.activity.mFinished) { 1871 try { 1872 am.activityIdle(a.token); 1873 } catch (RemoteException ex) { 1874 } 1875 } 1876 prev = a; 1877 a = a.nextIdle; 1878 prev.nextIdle = null; 1879 } while (a != null); 1880 } 1881 return false; 1882 } 1883 } 1884 1885 final class GcIdler implements MessageQueue.IdleHandler { 1886 public final boolean queueIdle() { 1887 doGcIfNeeded(); 1888 return false; 1889 } 1890 } 1891 1892 static IPackageManager sPackageManager; 1893 1894 final ApplicationThread mAppThread = new ApplicationThread(); 1895 final Looper mLooper = Looper.myLooper(); 1896 final H mH = new H(); 1897 final HashMap<IBinder, ActivityRecord> mActivities 1898 = new HashMap<IBinder, ActivityRecord>(); 1899 // List of new activities (via ActivityRecord.nextIdle) that should 1900 // be reported when next we idle. 1901 ActivityRecord mNewActivities = null; 1902 // Number of activities that are currently visible on-screen. 1903 int mNumVisibleActivities = 0; 1904 final HashMap<IBinder, Service> mServices 1905 = new HashMap<IBinder, Service>(); 1906 AppBindData mBoundApplication; 1907 Configuration mConfiguration; 1908 Application mInitialApplication; 1909 final ArrayList<Application> mAllApplications 1910 = new ArrayList<Application>(); 1911 static final ThreadLocal sThreadLocal = new ThreadLocal(); 1912 Instrumentation mInstrumentation; 1913 String mInstrumentationAppDir = null; 1914 String mInstrumentationAppPackage = null; 1915 String mInstrumentedAppDir = null; 1916 boolean mSystemThread = false; 1917 1918 /** 1919 * Activities that are enqueued to be relaunched. This list is accessed 1920 * by multiple threads, so you must synchronize on it when accessing it. 1921 */ 1922 final ArrayList<ActivityRecord> mRelaunchingActivities 1923 = new ArrayList<ActivityRecord>(); 1924 Configuration mPendingConfiguration = null; 1925 1926 // These can be accessed by multiple threads; mPackages is the lock. 1927 // XXX For now we keep around information about all packages we have 1928 // seen, not removing entries from this map. 1929 final HashMap<String, WeakReference<PackageInfo>> mPackages 1930 = new HashMap<String, WeakReference<PackageInfo>>(); 1931 final HashMap<String, WeakReference<PackageInfo>> mResourcePackages 1932 = new HashMap<String, WeakReference<PackageInfo>>(); 1933 Display mDisplay = null; 1934 DisplayMetrics mDisplayMetrics = null; 1935 HashMap<String, WeakReference<Resources> > mActiveResources 1936 = new HashMap<String, WeakReference<Resources> >(); 1937 1938 // The lock of mProviderMap protects the following variables. 1939 final HashMap<String, ProviderRecord> mProviderMap 1940 = new HashMap<String, ProviderRecord>(); 1941 final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap 1942 = new HashMap<IBinder, ProviderRefCount>(); 1943 final HashMap<IBinder, ProviderRecord> mLocalProviders 1944 = new HashMap<IBinder, ProviderRecord>(); 1945 1946 final GcIdler mGcIdler = new GcIdler(); 1947 boolean mGcIdlerScheduled = false; 1948 1949 public final PackageInfo getPackageInfo(String packageName, int flags) { 1950 synchronized (mPackages) { 1951 WeakReference<PackageInfo> ref; 1952 if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) { 1953 ref = mPackages.get(packageName); 1954 } else { 1955 ref = mResourcePackages.get(packageName); 1956 } 1957 PackageInfo packageInfo = ref != null ? ref.get() : null; 1958 //Log.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo); 1959 if (packageInfo != null && (packageInfo.mResources == null 1960 || packageInfo.mResources.getAssets().isUpToDate())) { 1961 if (packageInfo.isSecurityViolation() 1962 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) { 1963 throw new SecurityException( 1964 "Requesting code from " + packageName 1965 + " to be run in process " 1966 + mBoundApplication.processName 1967 + "/" + mBoundApplication.appInfo.uid); 1968 } 1969 return packageInfo; 1970 } 1971 } 1972 1973 ApplicationInfo ai = null; 1974 try { 1975 ai = getPackageManager().getApplicationInfo(packageName, 1976 PackageManager.GET_SHARED_LIBRARY_FILES); 1977 } catch (RemoteException e) { 1978 } 1979 1980 if (ai != null) { 1981 return getPackageInfo(ai, flags); 1982 } 1983 1984 return null; 1985 } 1986 1987 public final PackageInfo getPackageInfo(ApplicationInfo ai, int flags) { 1988 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0; 1989 boolean securityViolation = includeCode && ai.uid != 0 1990 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null 1991 ? ai.uid != mBoundApplication.appInfo.uid : true); 1992 if ((flags&(Context.CONTEXT_INCLUDE_CODE 1993 |Context.CONTEXT_IGNORE_SECURITY)) 1994 == Context.CONTEXT_INCLUDE_CODE) { 1995 if (securityViolation) { 1996 String msg = "Requesting code from " + ai.packageName 1997 + " (with uid " + ai.uid + ")"; 1998 if (mBoundApplication != null) { 1999 msg = msg + " to be run in process " 2000 + mBoundApplication.processName + " (with uid " 2001 + mBoundApplication.appInfo.uid + ")"; 2002 } 2003 throw new SecurityException(msg); 2004 } 2005 } 2006 return getPackageInfo(ai, null, securityViolation, includeCode); 2007 } 2008 2009 public final PackageInfo getPackageInfoNoCheck(ApplicationInfo ai) { 2010 return getPackageInfo(ai, null, false, true); 2011 } 2012 2013 private final PackageInfo getPackageInfo(ApplicationInfo aInfo, 2014 ClassLoader baseLoader, boolean securityViolation, boolean includeCode) { 2015 synchronized (mPackages) { 2016 WeakReference<PackageInfo> ref; 2017 if (includeCode) { 2018 ref = mPackages.get(aInfo.packageName); 2019 } else { 2020 ref = mResourcePackages.get(aInfo.packageName); 2021 } 2022 PackageInfo packageInfo = ref != null ? ref.get() : null; 2023 if (packageInfo == null || (packageInfo.mResources != null 2024 && !packageInfo.mResources.getAssets().isUpToDate())) { 2025 if (localLOGV) Log.v(TAG, (includeCode ? "Loading code package " 2026 : "Loading resource-only package ") + aInfo.packageName 2027 + " (in " + (mBoundApplication != null 2028 ? mBoundApplication.processName : null) 2029 + ")"); 2030 packageInfo = 2031 new PackageInfo(this, aInfo, this, baseLoader, 2032 securityViolation, includeCode && 2033 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0); 2034 if (includeCode) { 2035 mPackages.put(aInfo.packageName, 2036 new WeakReference<PackageInfo>(packageInfo)); 2037 } else { 2038 mResourcePackages.put(aInfo.packageName, 2039 new WeakReference<PackageInfo>(packageInfo)); 2040 } 2041 } 2042 return packageInfo; 2043 } 2044 } 2045 2046 public final boolean hasPackageInfo(String packageName) { 2047 synchronized (mPackages) { 2048 WeakReference<PackageInfo> ref; 2049 ref = mPackages.get(packageName); 2050 if (ref != null && ref.get() != null) { 2051 return true; 2052 } 2053 ref = mResourcePackages.get(packageName); 2054 if (ref != null && ref.get() != null) { 2055 return true; 2056 } 2057 return false; 2058 } 2059 } 2060 2061 ActivityThread() { 2062 } 2063 2064 public ApplicationThread getApplicationThread() 2065 { 2066 return mAppThread; 2067 } 2068 2069 public Instrumentation getInstrumentation() 2070 { 2071 return mInstrumentation; 2072 } 2073 2074 public Configuration getConfiguration() { 2075 return mConfiguration; 2076 } 2077 2078 public boolean isProfiling() { 2079 return mBoundApplication != null && mBoundApplication.profileFile != null; 2080 } 2081 2082 public String getProfileFilePath() { 2083 return mBoundApplication.profileFile; 2084 } 2085 2086 public Looper getLooper() { 2087 return mLooper; 2088 } 2089 2090 public Application getApplication() { 2091 return mInitialApplication; 2092 } 2093 2094 public ApplicationContext getSystemContext() { 2095 synchronized (this) { 2096 if (mSystemContext == null) { 2097 ApplicationContext context = 2098 ApplicationContext.createSystemContext(this); 2099 PackageInfo info = new PackageInfo(this, "android", context); 2100 context.init(info, null, this); 2101 context.getResources().updateConfiguration( 2102 getConfiguration(), getDisplayMetricsLocked(false)); 2103 mSystemContext = context; 2104 //Log.i(TAG, "Created system resources " + context.getResources() 2105 // + ": " + context.getResources().getConfiguration()); 2106 } 2107 } 2108 return mSystemContext; 2109 } 2110 2111 void scheduleGcIdler() { 2112 if (!mGcIdlerScheduled) { 2113 mGcIdlerScheduled = true; 2114 Looper.myQueue().addIdleHandler(mGcIdler); 2115 } 2116 mH.removeMessages(H.GC_WHEN_IDLE); 2117 } 2118 2119 void unscheduleGcIdler() { 2120 if (mGcIdlerScheduled) { 2121 mGcIdlerScheduled = false; 2122 Looper.myQueue().removeIdleHandler(mGcIdler); 2123 } 2124 mH.removeMessages(H.GC_WHEN_IDLE); 2125 } 2126 2127 void doGcIfNeeded() { 2128 mGcIdlerScheduled = false; 2129 final long now = SystemClock.uptimeMillis(); 2130 //Log.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime() 2131 // + "m now=" + now); 2132 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) { 2133 //Log.i(TAG, "**** WE DO, WE DO WANT TO GC!"); 2134 BinderInternal.forceGc("bg"); 2135 } 2136 } 2137 2138 public final ActivityInfo resolveActivityInfo(Intent intent) { 2139 ActivityInfo aInfo = intent.resolveActivityInfo( 2140 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES); 2141 if (aInfo == null) { 2142 // Throw an exception. 2143 Instrumentation.checkStartActivityResult( 2144 IActivityManager.START_CLASS_NOT_FOUND, intent); 2145 } 2146 return aInfo; 2147 } 2148 2149 public final Activity startActivityNow(Activity parent, String id, 2150 Intent intent, IBinder token, Bundle state) { 2151 ActivityInfo aInfo = resolveActivityInfo(intent); 2152 return startActivityNow(parent, id, intent, aInfo, token, state); 2153 } 2154 2155 public final Activity startActivityNow(Activity parent, String id, 2156 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state) { 2157 return startActivityNow(parent, id, intent, activityInfo, token, state, null); 2158 } 2159 2160 public final Activity startActivityNow(Activity parent, String id, 2161 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state, 2162 Object lastNonConfigurationInstance) { 2163 ActivityRecord r = new ActivityRecord(); 2164 r.token = token; 2165 r.intent = intent; 2166 r.state = state; 2167 r.parent = parent; 2168 r.embeddedID = id; 2169 r.activityInfo = activityInfo; 2170 r.lastNonConfigurationInstance = lastNonConfigurationInstance; 2171 if (localLOGV) { 2172 ComponentName compname = intent.getComponent(); 2173 String name; 2174 if (compname != null) { 2175 name = compname.toShortString(); 2176 } else { 2177 name = "(Intent " + intent + ").getComponent() returned null"; 2178 } 2179 Log.v(TAG, "Performing launch: action=" + intent.getAction() 2180 + ", comp=" + name 2181 + ", token=" + token); 2182 } 2183 return performLaunchActivity(r, null); 2184 } 2185 2186 public final Activity getActivity(IBinder token) { 2187 return mActivities.get(token).activity; 2188 } 2189 2190 public final void sendActivityResult( 2191 IBinder token, String id, int requestCode, 2192 int resultCode, Intent data) { 2193 if (DEBUG_RESULTS) Log.v(TAG, "sendActivityResult: id=" + id 2194 + " req=" + requestCode + " res=" + resultCode + " data=" + data); 2195 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 2196 list.add(new ResultInfo(id, requestCode, resultCode, data)); 2197 mAppThread.scheduleSendResult(token, list); 2198 } 2199 2200 // if the thread hasn't started yet, we don't have the handler, so just 2201 // save the messages until we're ready. 2202 private final void queueOrSendMessage(int what, Object obj) { 2203 queueOrSendMessage(what, obj, 0, 0); 2204 } 2205 2206 private final void queueOrSendMessage(int what, Object obj, int arg1) { 2207 queueOrSendMessage(what, obj, arg1, 0); 2208 } 2209 2210 private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { 2211 synchronized (this) { 2212 if (localLOGV) Log.v( 2213 TAG, "SCHEDULE " + what + " " + mH.codeToString(what) 2214 + ": " + arg1 + " / " + obj); 2215 Message msg = Message.obtain(); 2216 msg.what = what; 2217 msg.obj = obj; 2218 msg.arg1 = arg1; 2219 msg.arg2 = arg2; 2220 mH.sendMessage(msg); 2221 } 2222 } 2223 2224 final void scheduleContextCleanup(ApplicationContext context, String who, 2225 String what) { 2226 ContextCleanupInfo cci = new ContextCleanupInfo(); 2227 cci.context = context; 2228 cci.who = who; 2229 cci.what = what; 2230 queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci); 2231 } 2232 2233 private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) { 2234 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); 2235 2236 ActivityInfo aInfo = r.activityInfo; 2237 if (r.packageInfo == null) { 2238 r.packageInfo = getPackageInfo(aInfo.applicationInfo, 2239 Context.CONTEXT_INCLUDE_CODE); 2240 } 2241 2242 ComponentName component = r.intent.getComponent(); 2243 if (component == null) { 2244 component = r.intent.resolveActivity( 2245 mInitialApplication.getPackageManager()); 2246 r.intent.setComponent(component); 2247 } 2248 2249 if (r.activityInfo.targetActivity != null) { 2250 component = new ComponentName(r.activityInfo.packageName, 2251 r.activityInfo.targetActivity); 2252 } 2253 2254 Activity activity = null; 2255 try { 2256 java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); 2257 activity = mInstrumentation.newActivity( 2258 cl, component.getClassName(), r.intent); 2259 r.intent.setExtrasClassLoader(cl); 2260 if (r.state != null) { 2261 r.state.setClassLoader(cl); 2262 } 2263 } catch (Exception e) { 2264 if (!mInstrumentation.onException(activity, e)) { 2265 throw new RuntimeException( 2266 "Unable to instantiate activity " + component 2267 + ": " + e.toString(), e); 2268 } 2269 } 2270 2271 try { 2272 Application app = r.packageInfo.makeApplication(); 2273 2274 if (localLOGV) Log.v(TAG, "Performing launch of " + r); 2275 if (localLOGV) Log.v( 2276 TAG, r + ": app=" + app 2277 + ", appName=" + app.getPackageName() 2278 + ", pkg=" + r.packageInfo.getPackageName() 2279 + ", comp=" + r.intent.getComponent().toShortString() 2280 + ", dir=" + r.packageInfo.getAppDir()); 2281 2282 if (activity != null) { 2283 ApplicationContext appContext = new ApplicationContext(); 2284 appContext.init(r.packageInfo, r.token, this); 2285 appContext.setOuterContext(activity); 2286 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); 2287 Configuration config = new Configuration(mConfiguration); 2288 activity.attach(appContext, this, getInstrumentation(), r.token, app, 2289 r.intent, r.activityInfo, title, r.parent, r.embeddedID, 2290 r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances, 2291 config); 2292 2293 if (customIntent != null) { 2294 activity.mIntent = customIntent; 2295 } 2296 r.lastNonConfigurationInstance = null; 2297 r.lastNonConfigurationChildInstances = null; 2298 activity.mStartedActivity = false; 2299 int theme = r.activityInfo.getThemeResource(); 2300 if (theme != 0) { 2301 activity.setTheme(theme); 2302 } 2303 2304 activity.mCalled = false; 2305 mInstrumentation.callActivityOnCreate(activity, r.state); 2306 if (!activity.mCalled) { 2307 throw new SuperNotCalledException( 2308 "Activity " + r.intent.getComponent().toShortString() + 2309 " did not call through to super.onCreate()"); 2310 } 2311 r.activity = activity; 2312 r.stopped = true; 2313 if (!r.activity.mFinished) { 2314 activity.performStart(); 2315 r.stopped = false; 2316 } 2317 if (!r.activity.mFinished) { 2318 if (r.state != null) { 2319 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); 2320 } 2321 } 2322 if (!r.activity.mFinished) { 2323 activity.mCalled = false; 2324 mInstrumentation.callActivityOnPostCreate(activity, r.state); 2325 if (!activity.mCalled) { 2326 throw new SuperNotCalledException( 2327 "Activity " + r.intent.getComponent().toShortString() + 2328 " did not call through to super.onPostCreate()"); 2329 } 2330 } 2331 r.state = null; 2332 } 2333 r.paused = true; 2334 2335 mActivities.put(r.token, r); 2336 2337 } catch (SuperNotCalledException e) { 2338 throw e; 2339 2340 } catch (Exception e) { 2341 if (!mInstrumentation.onException(activity, e)) { 2342 throw new RuntimeException( 2343 "Unable to start activity " + component 2344 + ": " + e.toString(), e); 2345 } 2346 } 2347 2348 return activity; 2349 } 2350 2351 private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) { 2352 // If we are getting ready to gc after going to the background, well 2353 // we are back active so skip it. 2354 unscheduleGcIdler(); 2355 2356 if (localLOGV) Log.v( 2357 TAG, "Handling launch of " + r); 2358 Activity a = performLaunchActivity(r, customIntent); 2359 2360 if (a != null) { 2361 handleResumeActivity(r.token, false, r.isForward); 2362 2363 if (!r.activity.mFinished && r.startsNotResumed) { 2364 // The activity manager actually wants this one to start out 2365 // paused, because it needs to be visible but isn't in the 2366 // foreground. We accomplish this by going through the 2367 // normal startup (because activities expect to go through 2368 // onResume() the first time they run, before their window 2369 // is displayed), and then pausing it. However, in this case 2370 // we do -not- need to do the full pause cycle (of freezing 2371 // and such) because the activity manager assumes it can just 2372 // retain the current state it has. 2373 try { 2374 r.activity.mCalled = false; 2375 mInstrumentation.callActivityOnPause(r.activity); 2376 if (!r.activity.mCalled) { 2377 throw new SuperNotCalledException( 2378 "Activity " + r.intent.getComponent().toShortString() + 2379 " did not call through to super.onPause()"); 2380 } 2381 2382 } catch (SuperNotCalledException e) { 2383 throw e; 2384 2385 } catch (Exception e) { 2386 if (!mInstrumentation.onException(r.activity, e)) { 2387 throw new RuntimeException( 2388 "Unable to pause activity " 2389 + r.intent.getComponent().toShortString() 2390 + ": " + e.toString(), e); 2391 } 2392 } 2393 r.paused = true; 2394 } 2395 } else { 2396 // If there was an error, for any reason, tell the activity 2397 // manager to stop us. 2398 try { 2399 ActivityManagerNative.getDefault() 2400 .finishActivity(r.token, Activity.RESULT_CANCELED, null); 2401 } catch (RemoteException ex) { 2402 } 2403 } 2404 } 2405 2406 private final void deliverNewIntents(ActivityRecord r, 2407 List<Intent> intents) { 2408 final int N = intents.size(); 2409 for (int i=0; i<N; i++) { 2410 Intent intent = intents.get(i); 2411 intent.setExtrasClassLoader(r.activity.getClassLoader()); 2412 mInstrumentation.callActivityOnNewIntent(r.activity, intent); 2413 } 2414 } 2415 2416 public final void performNewIntents(IBinder token, 2417 List<Intent> intents) { 2418 ActivityRecord r = mActivities.get(token); 2419 if (r != null) { 2420 final boolean resumed = !r.paused; 2421 if (resumed) { 2422 mInstrumentation.callActivityOnPause(r.activity); 2423 } 2424 deliverNewIntents(r, intents); 2425 if (resumed) { 2426 mInstrumentation.callActivityOnResume(r.activity); 2427 } 2428 } 2429 } 2430 2431 private final void handleNewIntent(NewIntentData data) { 2432 performNewIntents(data.token, data.intents); 2433 } 2434 2435 private final void handleReceiver(ReceiverData data) { 2436 // If we are getting ready to gc after going to the background, well 2437 // we are back active so skip it. 2438 unscheduleGcIdler(); 2439 2440 String component = data.intent.getComponent().getClassName(); 2441 2442 PackageInfo packageInfo = getPackageInfoNoCheck( 2443 data.info.applicationInfo); 2444 2445 IActivityManager mgr = ActivityManagerNative.getDefault(); 2446 2447 BroadcastReceiver receiver = null; 2448 try { 2449 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2450 data.intent.setExtrasClassLoader(cl); 2451 if (data.resultExtras != null) { 2452 data.resultExtras.setClassLoader(cl); 2453 } 2454 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); 2455 } catch (Exception e) { 2456 try { 2457 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode, 2458 data.resultData, data.resultExtras, data.resultAbort); 2459 } catch (RemoteException ex) { 2460 } 2461 throw new RuntimeException( 2462 "Unable to instantiate receiver " + component 2463 + ": " + e.toString(), e); 2464 } 2465 2466 try { 2467 Application app = packageInfo.makeApplication(); 2468 2469 if (localLOGV) Log.v( 2470 TAG, "Performing receive of " + data.intent 2471 + ": app=" + app 2472 + ", appName=" + app.getPackageName() 2473 + ", pkg=" + packageInfo.getPackageName() 2474 + ", comp=" + data.intent.getComponent().toShortString() 2475 + ", dir=" + packageInfo.getAppDir()); 2476 2477 ApplicationContext context = (ApplicationContext)app.getBaseContext(); 2478 receiver.setOrderedHint(true); 2479 receiver.setResult(data.resultCode, data.resultData, 2480 data.resultExtras); 2481 receiver.setOrderedHint(data.sync); 2482 receiver.onReceive(context.getReceiverRestrictedContext(), 2483 data.intent); 2484 } catch (Exception e) { 2485 try { 2486 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode, 2487 data.resultData, data.resultExtras, data.resultAbort); 2488 } catch (RemoteException ex) { 2489 } 2490 if (!mInstrumentation.onException(receiver, e)) { 2491 throw new RuntimeException( 2492 "Unable to start receiver " + component 2493 + ": " + e.toString(), e); 2494 } 2495 } 2496 2497 try { 2498 if (data.sync) { 2499 mgr.finishReceiver( 2500 mAppThread.asBinder(), receiver.getResultCode(), 2501 receiver.getResultData(), receiver.getResultExtras(false), 2502 receiver.getAbortBroadcast()); 2503 } else { 2504 mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false); 2505 } 2506 } catch (RemoteException ex) { 2507 } 2508 } 2509 2510 private final void handleCreateService(CreateServiceData data) { 2511 // If we are getting ready to gc after going to the background, well 2512 // we are back active so skip it. 2513 unscheduleGcIdler(); 2514 2515 PackageInfo packageInfo = getPackageInfoNoCheck( 2516 data.info.applicationInfo); 2517 Service service = null; 2518 try { 2519 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2520 service = (Service) cl.loadClass(data.info.name).newInstance(); 2521 } catch (Exception e) { 2522 if (!mInstrumentation.onException(service, e)) { 2523 throw new RuntimeException( 2524 "Unable to instantiate service " + data.info.name 2525 + ": " + e.toString(), e); 2526 } 2527 } 2528 2529 try { 2530 if (localLOGV) Log.v(TAG, "Creating service " + data.info.name); 2531 2532 ApplicationContext context = new ApplicationContext(); 2533 context.init(packageInfo, null, this); 2534 2535 Application app = packageInfo.makeApplication(); 2536 context.setOuterContext(service); 2537 service.attach(context, this, data.info.name, data.token, app, 2538 ActivityManagerNative.getDefault()); 2539 service.onCreate(); 2540 mServices.put(data.token, service); 2541 try { 2542 ActivityManagerNative.getDefault().serviceDoneExecuting(data.token); 2543 } catch (RemoteException e) { 2544 // nothing to do. 2545 } 2546 } catch (Exception e) { 2547 if (!mInstrumentation.onException(service, e)) { 2548 throw new RuntimeException( 2549 "Unable to create service " + data.info.name 2550 + ": " + e.toString(), e); 2551 } 2552 } 2553 } 2554 2555 private final void handleBindService(BindServiceData data) { 2556 Service s = mServices.get(data.token); 2557 if (s != null) { 2558 try { 2559 data.intent.setExtrasClassLoader(s.getClassLoader()); 2560 try { 2561 if (!data.rebind) { 2562 IBinder binder = s.onBind(data.intent); 2563 ActivityManagerNative.getDefault().publishService( 2564 data.token, data.intent, binder); 2565 } else { 2566 s.onRebind(data.intent); 2567 ActivityManagerNative.getDefault().serviceDoneExecuting( 2568 data.token); 2569 } 2570 } catch (RemoteException ex) { 2571 } 2572 } catch (Exception e) { 2573 if (!mInstrumentation.onException(s, e)) { 2574 throw new RuntimeException( 2575 "Unable to bind to service " + s 2576 + " with " + data.intent + ": " + e.toString(), e); 2577 } 2578 } 2579 } 2580 } 2581 2582 private final void handleUnbindService(BindServiceData data) { 2583 Service s = mServices.get(data.token); 2584 if (s != null) { 2585 try { 2586 data.intent.setExtrasClassLoader(s.getClassLoader()); 2587 boolean doRebind = s.onUnbind(data.intent); 2588 try { 2589 if (doRebind) { 2590 ActivityManagerNative.getDefault().unbindFinished( 2591 data.token, data.intent, doRebind); 2592 } else { 2593 ActivityManagerNative.getDefault().serviceDoneExecuting( 2594 data.token); 2595 } 2596 } catch (RemoteException ex) { 2597 } 2598 } catch (Exception e) { 2599 if (!mInstrumentation.onException(s, e)) { 2600 throw new RuntimeException( 2601 "Unable to unbind to service " + s 2602 + " with " + data.intent + ": " + e.toString(), e); 2603 } 2604 } 2605 } 2606 } 2607 2608 private void handleDumpService(DumpServiceInfo info) { 2609 try { 2610 Service s = mServices.get(info.service); 2611 if (s != null) { 2612 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd)); 2613 s.dump(info.fd, pw, info.args); 2614 pw.close(); 2615 } 2616 } finally { 2617 synchronized (info) { 2618 info.dumped = true; 2619 info.notifyAll(); 2620 } 2621 } 2622 } 2623 2624 private final void handleServiceArgs(ServiceArgsData data) { 2625 Service s = mServices.get(data.token); 2626 if (s != null) { 2627 try { 2628 if (data.args != null) { 2629 data.args.setExtrasClassLoader(s.getClassLoader()); 2630 } 2631 s.onStart(data.args, data.startId); 2632 try { 2633 ActivityManagerNative.getDefault().serviceDoneExecuting(data.token); 2634 } catch (RemoteException e) { 2635 // nothing to do. 2636 } 2637 } catch (Exception e) { 2638 if (!mInstrumentation.onException(s, e)) { 2639 throw new RuntimeException( 2640 "Unable to start service " + s 2641 + " with " + data.args + ": " + e.toString(), e); 2642 } 2643 } 2644 } 2645 } 2646 2647 private final void handleStopService(IBinder token) { 2648 Service s = mServices.remove(token); 2649 if (s != null) { 2650 try { 2651 if (localLOGV) Log.v(TAG, "Destroying service " + s); 2652 s.onDestroy(); 2653 Context context = s.getBaseContext(); 2654 if (context instanceof ApplicationContext) { 2655 final String who = s.getClassName(); 2656 ((ApplicationContext) context).scheduleFinalCleanup(who, "Service"); 2657 } 2658 try { 2659 ActivityManagerNative.getDefault().serviceDoneExecuting(token); 2660 } catch (RemoteException e) { 2661 // nothing to do. 2662 } 2663 } catch (Exception e) { 2664 if (!mInstrumentation.onException(s, e)) { 2665 throw new RuntimeException( 2666 "Unable to stop service " + s 2667 + ": " + e.toString(), e); 2668 } 2669 } 2670 } 2671 //Log.i(TAG, "Running services: " + mServices); 2672 } 2673 2674 public final ActivityRecord performResumeActivity(IBinder token, 2675 boolean clearHide) { 2676 ActivityRecord r = mActivities.get(token); 2677 if (localLOGV) Log.v(TAG, "Performing resume of " + r 2678 + " finished=" + r.activity.mFinished); 2679 if (r != null && !r.activity.mFinished) { 2680 if (clearHide) { 2681 r.hideForNow = false; 2682 r.activity.mStartedActivity = false; 2683 } 2684 try { 2685 if (r.pendingIntents != null) { 2686 deliverNewIntents(r, r.pendingIntents); 2687 r.pendingIntents = null; 2688 } 2689 if (r.pendingResults != null) { 2690 deliverResults(r, r.pendingResults); 2691 r.pendingResults = null; 2692 } 2693 r.activity.performResume(); 2694 2695 EventLog.writeEvent(LOG_ON_RESUME_CALLED, 2696 r.activity.getComponentName().getClassName()); 2697 2698 r.paused = false; 2699 r.stopped = false; 2700 if (r.activity.mStartedActivity) { 2701 r.hideForNow = true; 2702 } 2703 r.state = null; 2704 } catch (Exception e) { 2705 if (!mInstrumentation.onException(r.activity, e)) { 2706 throw new RuntimeException( 2707 "Unable to resume activity " 2708 + r.intent.getComponent().toShortString() 2709 + ": " + e.toString(), e); 2710 } 2711 } 2712 } 2713 return r; 2714 } 2715 2716 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) { 2717 // If we are getting ready to gc after going to the background, well 2718 // we are back active so skip it. 2719 unscheduleGcIdler(); 2720 2721 ActivityRecord r = performResumeActivity(token, clearHide); 2722 2723 if (r != null) { 2724 final Activity a = r.activity; 2725 2726 if (localLOGV) Log.v( 2727 TAG, "Resume " + r + " started activity: " + 2728 a.mStartedActivity + ", hideForNow: " + r.hideForNow 2729 + ", finished: " + a.mFinished); 2730 2731 final int forwardBit = isForward ? 2732 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0; 2733 2734 // If the window hasn't yet been added to the window manager, 2735 // and this guy didn't finish itself or start another activity, 2736 // then go ahead and add the window. 2737 if (r.window == null && !a.mFinished && !a.mStartedActivity) { 2738 r.window = r.activity.getWindow(); 2739 View decor = r.window.getDecorView(); 2740 decor.setVisibility(View.INVISIBLE); 2741 ViewManager wm = a.getWindowManager(); 2742 WindowManager.LayoutParams l = r.window.getAttributes(); 2743 a.mDecor = decor; 2744 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 2745 l.softInputMode |= forwardBit; 2746 if (a.mVisibleFromClient) { 2747 a.mWindowAdded = true; 2748 wm.addView(decor, l); 2749 } 2750 2751 // If the window has already been added, but during resume 2752 // we started another activity, then don't yet make the 2753 // window visisble. 2754 } else if (a.mStartedActivity) { 2755 if (localLOGV) Log.v( 2756 TAG, "Launch " + r + " mStartedActivity set"); 2757 r.hideForNow = true; 2758 } 2759 2760 // The window is now visible if it has been added, we are not 2761 // simply finishing, and we are not starting another activity. 2762 if (!r.activity.mFinished && r.activity.mDecor != null 2763 && !r.hideForNow) { 2764 if (r.newConfig != null) { 2765 performConfigurationChanged(r.activity, r.newConfig); 2766 r.newConfig = null; 2767 } 2768 if (localLOGV) Log.v(TAG, "Resuming " + r + " with isForward=" 2769 + isForward); 2770 WindowManager.LayoutParams l = r.window.getAttributes(); 2771 if ((l.softInputMode 2772 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) 2773 != forwardBit) { 2774 l.softInputMode = (l.softInputMode 2775 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)) 2776 | forwardBit; 2777 ViewManager wm = a.getWindowManager(); 2778 View decor = r.window.getDecorView(); 2779 wm.updateViewLayout(decor, l); 2780 } 2781 r.activity.mVisibleFromServer = true; 2782 mNumVisibleActivities++; 2783 if (r.activity.mVisibleFromClient) { 2784 r.activity.makeVisible(); 2785 } 2786 } 2787 2788 r.nextIdle = mNewActivities; 2789 mNewActivities = r; 2790 if (localLOGV) Log.v( 2791 TAG, "Scheduling idle handler for " + r); 2792 Looper.myQueue().addIdleHandler(new Idler()); 2793 2794 } else { 2795 // If an exception was thrown when trying to resume, then 2796 // just end this activity. 2797 try { 2798 ActivityManagerNative.getDefault() 2799 .finishActivity(token, Activity.RESULT_CANCELED, null); 2800 } catch (RemoteException ex) { 2801 } 2802 } 2803 } 2804 2805 private int mThumbnailWidth = -1; 2806 private int mThumbnailHeight = -1; 2807 2808 private final Bitmap createThumbnailBitmap(ActivityRecord r) { 2809 Bitmap thumbnail = null; 2810 try { 2811 int w = mThumbnailWidth; 2812 int h; 2813 if (w < 0) { 2814 Resources res = r.activity.getResources(); 2815 mThumbnailHeight = h = 2816 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); 2817 2818 mThumbnailWidth = w = 2819 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); 2820 } else { 2821 h = mThumbnailHeight; 2822 } 2823 2824 // XXX Only set hasAlpha if needed? 2825 thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565); 2826 thumbnail.eraseColor(0); 2827 Canvas cv = new Canvas(thumbnail); 2828 if (!r.activity.onCreateThumbnail(thumbnail, cv)) { 2829 thumbnail = null; 2830 } 2831 } catch (Exception e) { 2832 if (!mInstrumentation.onException(r.activity, e)) { 2833 throw new RuntimeException( 2834 "Unable to create thumbnail of " 2835 + r.intent.getComponent().toShortString() 2836 + ": " + e.toString(), e); 2837 } 2838 thumbnail = null; 2839 } 2840 2841 return thumbnail; 2842 } 2843 2844 private final void handlePauseActivity(IBinder token, boolean finished, 2845 boolean userLeaving, int configChanges) { 2846 ActivityRecord r = mActivities.get(token); 2847 if (r != null) { 2848 //Log.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); 2849 if (userLeaving) { 2850 performUserLeavingActivity(r); 2851 } 2852 2853 r.activity.mConfigChangeFlags |= configChanges; 2854 Bundle state = performPauseActivity(token, finished, true); 2855 2856 // Tell the activity manager we have paused. 2857 try { 2858 ActivityManagerNative.getDefault().activityPaused(token, state); 2859 } catch (RemoteException ex) { 2860 } 2861 } 2862 } 2863 2864 final void performUserLeavingActivity(ActivityRecord r) { 2865 mInstrumentation.callActivityOnUserLeaving(r.activity); 2866 } 2867 2868 final Bundle performPauseActivity(IBinder token, boolean finished, 2869 boolean saveState) { 2870 ActivityRecord r = mActivities.get(token); 2871 return r != null ? performPauseActivity(r, finished, saveState) : null; 2872 } 2873 2874 final Bundle performPauseActivity(ActivityRecord r, boolean finished, 2875 boolean saveState) { 2876 if (r.paused) { 2877 if (r.activity.mFinished) { 2878 // If we are finishing, we won't call onResume() in certain cases. 2879 // So here we likewise don't want to call onPause() if the activity 2880 // isn't resumed. 2881 return null; 2882 } 2883 RuntimeException e = new RuntimeException( 2884 "Performing pause of activity that is not resumed: " 2885 + r.intent.getComponent().toShortString()); 2886 Log.e(TAG, e.getMessage(), e); 2887 } 2888 Bundle state = null; 2889 if (finished) { 2890 r.activity.mFinished = true; 2891 } 2892 try { 2893 // Next have the activity save its current state and managed dialogs... 2894 if (!r.activity.mFinished && saveState) { 2895 state = new Bundle(); 2896 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); 2897 r.state = state; 2898 } 2899 // Now we are idle. 2900 r.activity.mCalled = false; 2901 mInstrumentation.callActivityOnPause(r.activity); 2902 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName()); 2903 if (!r.activity.mCalled) { 2904 throw new SuperNotCalledException( 2905 "Activity " + r.intent.getComponent().toShortString() + 2906 " did not call through to super.onPause()"); 2907 } 2908 2909 } catch (SuperNotCalledException e) { 2910 throw e; 2911 2912 } catch (Exception e) { 2913 if (!mInstrumentation.onException(r.activity, e)) { 2914 throw new RuntimeException( 2915 "Unable to pause activity " 2916 + r.intent.getComponent().toShortString() 2917 + ": " + e.toString(), e); 2918 } 2919 } 2920 r.paused = true; 2921 return state; 2922 } 2923 2924 final void performStopActivity(IBinder token) { 2925 ActivityRecord r = mActivities.get(token); 2926 performStopActivityInner(r, null, false); 2927 } 2928 2929 private static class StopInfo { 2930 Bitmap thumbnail; 2931 CharSequence description; 2932 } 2933 2934 private final class ProviderRefCount { 2935 public int count; 2936 ProviderRefCount(int pCount) { 2937 count = pCount; 2938 } 2939 } 2940 2941 private final void performStopActivityInner(ActivityRecord r, 2942 StopInfo info, boolean keepShown) { 2943 if (localLOGV) Log.v(TAG, "Performing stop of " + r); 2944 if (r != null) { 2945 if (!keepShown && r.stopped) { 2946 if (r.activity.mFinished) { 2947 // If we are finishing, we won't call onResume() in certain 2948 // cases. So here we likewise don't want to call onStop() 2949 // if the activity isn't resumed. 2950 return; 2951 } 2952 RuntimeException e = new RuntimeException( 2953 "Performing stop of activity that is not resumed: " 2954 + r.intent.getComponent().toShortString()); 2955 Log.e(TAG, e.getMessage(), e); 2956 } 2957 2958 if (info != null) { 2959 try { 2960 // First create a thumbnail for the activity... 2961 //info.thumbnail = createThumbnailBitmap(r); 2962 info.description = r.activity.onCreateDescription(); 2963 } catch (Exception e) { 2964 if (!mInstrumentation.onException(r.activity, e)) { 2965 throw new RuntimeException( 2966 "Unable to save state of activity " 2967 + r.intent.getComponent().toShortString() 2968 + ": " + e.toString(), e); 2969 } 2970 } 2971 } 2972 2973 if (!keepShown) { 2974 try { 2975 // Now we are idle. 2976 r.activity.performStop(); 2977 } catch (Exception e) { 2978 if (!mInstrumentation.onException(r.activity, e)) { 2979 throw new RuntimeException( 2980 "Unable to stop activity " 2981 + r.intent.getComponent().toShortString() 2982 + ": " + e.toString(), e); 2983 } 2984 } 2985 r.stopped = true; 2986 } 2987 2988 r.paused = true; 2989 } 2990 } 2991 2992 private final void updateVisibility(ActivityRecord r, boolean show) { 2993 View v = r.activity.mDecor; 2994 if (v != null) { 2995 if (show) { 2996 if (!r.activity.mVisibleFromServer) { 2997 r.activity.mVisibleFromServer = true; 2998 mNumVisibleActivities++; 2999 if (r.activity.mVisibleFromClient) { 3000 r.activity.makeVisible(); 3001 } 3002 } 3003 if (r.newConfig != null) { 3004 performConfigurationChanged(r.activity, r.newConfig); 3005 r.newConfig = null; 3006 } 3007 } else { 3008 if (r.activity.mVisibleFromServer) { 3009 r.activity.mVisibleFromServer = false; 3010 mNumVisibleActivities--; 3011 v.setVisibility(View.INVISIBLE); 3012 } 3013 } 3014 } 3015 } 3016 3017 private final void handleStopActivity(IBinder token, boolean show, int configChanges) { 3018 ActivityRecord r = mActivities.get(token); 3019 r.activity.mConfigChangeFlags |= configChanges; 3020 3021 StopInfo info = new StopInfo(); 3022 performStopActivityInner(r, info, show); 3023 3024 if (localLOGV) Log.v( 3025 TAG, "Finishing stop of " + r + ": show=" + show 3026 + " win=" + r.window); 3027 3028 updateVisibility(r, show); 3029 3030 // Tell activity manager we have been stopped. 3031 try { 3032 ActivityManagerNative.getDefault().activityStopped( 3033 r.token, info.thumbnail, info.description); 3034 } catch (RemoteException ex) { 3035 } 3036 } 3037 3038 final void performRestartActivity(IBinder token) { 3039 ActivityRecord r = mActivities.get(token); 3040 if (r.stopped) { 3041 r.activity.performRestart(); 3042 r.stopped = false; 3043 } 3044 } 3045 3046 private final void handleWindowVisibility(IBinder token, boolean show) { 3047 ActivityRecord r = mActivities.get(token); 3048 if (!show && !r.stopped) { 3049 performStopActivityInner(r, null, show); 3050 } else if (show && r.stopped) { 3051 // If we are getting ready to gc after going to the background, well 3052 // we are back active so skip it. 3053 unscheduleGcIdler(); 3054 3055 r.activity.performRestart(); 3056 r.stopped = false; 3057 } 3058 if (r.activity.mDecor != null) { 3059 if (Config.LOGV) Log.v( 3060 TAG, "Handle window " + r + " visibility: " + show); 3061 updateVisibility(r, show); 3062 } 3063 } 3064 3065 private final void deliverResults(ActivityRecord r, List<ResultInfo> results) { 3066 final int N = results.size(); 3067 for (int i=0; i<N; i++) { 3068 ResultInfo ri = results.get(i); 3069 try { 3070 if (ri.mData != null) { 3071 ri.mData.setExtrasClassLoader(r.activity.getClassLoader()); 3072 } 3073 if (DEBUG_RESULTS) Log.v(TAG, 3074 "Delivering result to activity " + r + " : " + ri); 3075 r.activity.dispatchActivityResult(ri.mResultWho, 3076 ri.mRequestCode, ri.mResultCode, ri.mData); 3077 } catch (Exception e) { 3078 if (!mInstrumentation.onException(r.activity, e)) { 3079 throw new RuntimeException( 3080 "Failure delivering result " + ri + " to activity " 3081 + r.intent.getComponent().toShortString() 3082 + ": " + e.toString(), e); 3083 } 3084 } 3085 } 3086 } 3087 3088 private final void handleSendResult(ResultData res) { 3089 ActivityRecord r = mActivities.get(res.token); 3090 if (DEBUG_RESULTS) Log.v(TAG, "Handling send result to " + r); 3091 if (r != null) { 3092 final boolean resumed = !r.paused; 3093 if (!r.activity.mFinished && r.activity.mDecor != null 3094 && r.hideForNow && resumed) { 3095 // We had hidden the activity because it started another 3096 // one... we have gotten a result back and we are not 3097 // paused, so make sure our window is visible. 3098 updateVisibility(r, true); 3099 } 3100 if (resumed) { 3101 try { 3102 // Now we are idle. 3103 r.activity.mCalled = false; 3104 mInstrumentation.callActivityOnPause(r.activity); 3105 if (!r.activity.mCalled) { 3106 throw new SuperNotCalledException( 3107 "Activity " + r.intent.getComponent().toShortString() 3108 + " did not call through to super.onPause()"); 3109 } 3110 } catch (SuperNotCalledException e) { 3111 throw e; 3112 } catch (Exception e) { 3113 if (!mInstrumentation.onException(r.activity, e)) { 3114 throw new RuntimeException( 3115 "Unable to pause activity " 3116 + r.intent.getComponent().toShortString() 3117 + ": " + e.toString(), e); 3118 } 3119 } 3120 } 3121 deliverResults(r, res.results); 3122 if (resumed) { 3123 mInstrumentation.callActivityOnResume(r.activity); 3124 } 3125 } 3126 } 3127 3128 public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) { 3129 return performDestroyActivity(token, finishing, 0, false); 3130 } 3131 3132 private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing, 3133 int configChanges, boolean getNonConfigInstance) { 3134 ActivityRecord r = mActivities.get(token); 3135 if (localLOGV) Log.v(TAG, "Performing finish of " + r); 3136 if (r != null) { 3137 r.activity.mConfigChangeFlags |= configChanges; 3138 if (finishing) { 3139 r.activity.mFinished = true; 3140 } 3141 if (!r.paused) { 3142 try { 3143 r.activity.mCalled = false; 3144 mInstrumentation.callActivityOnPause(r.activity); 3145 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, 3146 r.activity.getComponentName().getClassName()); 3147 if (!r.activity.mCalled) { 3148 throw new SuperNotCalledException( 3149 "Activity " + r.intent.getComponent().toShortString() 3150 + " did not call through to super.onPause()"); 3151 } 3152 } catch (SuperNotCalledException e) { 3153 throw e; 3154 } catch (Exception e) { 3155 if (!mInstrumentation.onException(r.activity, e)) { 3156 throw new RuntimeException( 3157 "Unable to pause activity " 3158 + r.intent.getComponent().toShortString() 3159 + ": " + e.toString(), e); 3160 } 3161 } 3162 r.paused = true; 3163 } 3164 if (!r.stopped) { 3165 try { 3166 r.activity.performStop(); 3167 } catch (SuperNotCalledException e) { 3168 throw e; 3169 } catch (Exception e) { 3170 if (!mInstrumentation.onException(r.activity, e)) { 3171 throw new RuntimeException( 3172 "Unable to stop activity " 3173 + r.intent.getComponent().toShortString() 3174 + ": " + e.toString(), e); 3175 } 3176 } 3177 r.stopped = true; 3178 } 3179 if (getNonConfigInstance) { 3180 try { 3181 r.lastNonConfigurationInstance 3182 = r.activity.onRetainNonConfigurationInstance(); 3183 } catch (Exception e) { 3184 if (!mInstrumentation.onException(r.activity, e)) { 3185 throw new RuntimeException( 3186 "Unable to retain activity " 3187 + r.intent.getComponent().toShortString() 3188 + ": " + e.toString(), e); 3189 } 3190 } 3191 try { 3192 r.lastNonConfigurationChildInstances 3193 = r.activity.onRetainNonConfigurationChildInstances(); 3194 } catch (Exception e) { 3195 if (!mInstrumentation.onException(r.activity, e)) { 3196 throw new RuntimeException( 3197 "Unable to retain child activities " 3198 + r.intent.getComponent().toShortString() 3199 + ": " + e.toString(), e); 3200 } 3201 } 3202 3203 } 3204 try { 3205 r.activity.mCalled = false; 3206 r.activity.onDestroy(); 3207 if (!r.activity.mCalled) { 3208 throw new SuperNotCalledException( 3209 "Activity " + r.intent.getComponent().toShortString() + 3210 " did not call through to super.onDestroy()"); 3211 } 3212 if (r.window != null) { 3213 r.window.closeAllPanels(); 3214 } 3215 } catch (SuperNotCalledException e) { 3216 throw e; 3217 } catch (Exception e) { 3218 if (!mInstrumentation.onException(r.activity, e)) { 3219 throw new RuntimeException( 3220 "Unable to destroy activity " 3221 + r.intent.getComponent().toShortString() 3222 + ": " + e.toString(), e); 3223 } 3224 } 3225 } 3226 mActivities.remove(token); 3227 3228 return r; 3229 } 3230 3231 private final void handleDestroyActivity(IBinder token, boolean finishing, 3232 int configChanges, boolean getNonConfigInstance) { 3233 ActivityRecord r = performDestroyActivity(token, finishing, 3234 configChanges, getNonConfigInstance); 3235 if (r != null) { 3236 WindowManager wm = r.activity.getWindowManager(); 3237 View v = r.activity.mDecor; 3238 if (v != null) { 3239 if (r.activity.mVisibleFromServer) { 3240 mNumVisibleActivities--; 3241 } 3242 IBinder wtoken = v.getWindowToken(); 3243 if (r.activity.mWindowAdded) { 3244 wm.removeViewImmediate(v); 3245 } 3246 if (wtoken != null) { 3247 WindowManagerImpl.getDefault().closeAll(wtoken, 3248 r.activity.getClass().getName(), "Activity"); 3249 } 3250 r.activity.mDecor = null; 3251 } 3252 WindowManagerImpl.getDefault().closeAll(token, 3253 r.activity.getClass().getName(), "Activity"); 3254 3255 // Mocked out contexts won't be participating in the normal 3256 // process lifecycle, but if we're running with a proper 3257 // ApplicationContext we need to have it tear down things 3258 // cleanly. 3259 Context c = r.activity.getBaseContext(); 3260 if (c instanceof ApplicationContext) { 3261 ((ApplicationContext) c).scheduleFinalCleanup( 3262 r.activity.getClass().getName(), "Activity"); 3263 } 3264 } 3265 if (finishing) { 3266 try { 3267 ActivityManagerNative.getDefault().activityDestroyed(token); 3268 } catch (RemoteException ex) { 3269 // If the system process has died, it's game over for everyone. 3270 } 3271 } 3272 } 3273 3274 private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) { 3275 // If we are getting ready to gc after going to the background, well 3276 // we are back active so skip it. 3277 unscheduleGcIdler(); 3278 3279 Configuration changedConfig = null; 3280 3281 // First: make sure we have the most recent configuration and most 3282 // recent version of the activity, or skip it if some previous call 3283 // had taken a more recent version. 3284 synchronized (mRelaunchingActivities) { 3285 int N = mRelaunchingActivities.size(); 3286 IBinder token = tmp.token; 3287 tmp = null; 3288 for (int i=0; i<N; i++) { 3289 ActivityRecord r = mRelaunchingActivities.get(i); 3290 if (r.token == token) { 3291 tmp = r; 3292 mRelaunchingActivities.remove(i); 3293 i--; 3294 N--; 3295 } 3296 } 3297 3298 if (tmp == null) { 3299 return; 3300 } 3301 3302 if (mPendingConfiguration != null) { 3303 changedConfig = mPendingConfiguration; 3304 mPendingConfiguration = null; 3305 } 3306 } 3307 3308 // If there was a pending configuration change, execute it first. 3309 if (changedConfig != null) { 3310 handleConfigurationChanged(changedConfig); 3311 } 3312 3313 ActivityRecord r = mActivities.get(tmp.token); 3314 if (localLOGV) Log.v(TAG, "Handling relaunch of " + r); 3315 if (r == null) { 3316 return; 3317 } 3318 3319 r.activity.mConfigChangeFlags |= configChanges; 3320 Intent currentIntent = r.activity.mIntent; 3321 3322 Bundle savedState = null; 3323 if (!r.paused) { 3324 savedState = performPauseActivity(r.token, false, true); 3325 } 3326 3327 handleDestroyActivity(r.token, false, configChanges, true); 3328 3329 r.activity = null; 3330 r.window = null; 3331 r.hideForNow = false; 3332 r.nextIdle = null; 3333 // Merge any pending results and pending intents; don't just replace them 3334 if (tmp.pendingResults != null) { 3335 if (r.pendingResults == null) { 3336 r.pendingResults = tmp.pendingResults; 3337 } else { 3338 r.pendingResults.addAll(tmp.pendingResults); 3339 } 3340 } 3341 if (tmp.pendingIntents != null) { 3342 if (r.pendingIntents == null) { 3343 r.pendingIntents = tmp.pendingIntents; 3344 } else { 3345 r.pendingIntents.addAll(tmp.pendingIntents); 3346 } 3347 } 3348 r.startsNotResumed = tmp.startsNotResumed; 3349 if (savedState != null) { 3350 r.state = savedState; 3351 } 3352 3353 handleLaunchActivity(r, currentIntent); 3354 } 3355 3356 private final void handleRequestThumbnail(IBinder token) { 3357 ActivityRecord r = mActivities.get(token); 3358 Bitmap thumbnail = createThumbnailBitmap(r); 3359 CharSequence description = null; 3360 try { 3361 description = r.activity.onCreateDescription(); 3362 } catch (Exception e) { 3363 if (!mInstrumentation.onException(r.activity, e)) { 3364 throw new RuntimeException( 3365 "Unable to create description of activity " 3366 + r.intent.getComponent().toShortString() 3367 + ": " + e.toString(), e); 3368 } 3369 } 3370 //System.out.println("Reporting top thumbnail " + thumbnail); 3371 try { 3372 ActivityManagerNative.getDefault().reportThumbnail( 3373 token, thumbnail, description); 3374 } catch (RemoteException ex) { 3375 } 3376 } 3377 3378 ArrayList<ComponentCallbacks> collectComponentCallbacksLocked( 3379 boolean allActivities, Configuration newConfig) { 3380 ArrayList<ComponentCallbacks> callbacks 3381 = new ArrayList<ComponentCallbacks>(); 3382 3383 if (mActivities.size() > 0) { 3384 Iterator<ActivityRecord> it = mActivities.values().iterator(); 3385 while (it.hasNext()) { 3386 ActivityRecord ar = it.next(); 3387 Activity a = ar.activity; 3388 if (a != null) { 3389 if (!ar.activity.mFinished && (allActivities || 3390 (a != null && !ar.paused))) { 3391 // If the activity is currently resumed, its configuration 3392 // needs to change right now. 3393 callbacks.add(a); 3394 } else if (newConfig != null) { 3395 // Otherwise, we will tell it about the change 3396 // the next time it is resumed or shown. Note that 3397 // the activity manager may, before then, decide the 3398 // activity needs to be destroyed to handle its new 3399 // configuration. 3400 ar.newConfig = newConfig; 3401 } 3402 } 3403 } 3404 } 3405 if (mServices.size() > 0) { 3406 Iterator<Service> it = mServices.values().iterator(); 3407 while (it.hasNext()) { 3408 callbacks.add(it.next()); 3409 } 3410 } 3411 synchronized (mProviderMap) { 3412 if (mLocalProviders.size() > 0) { 3413 Iterator<ProviderRecord> it = mLocalProviders.values().iterator(); 3414 while (it.hasNext()) { 3415 callbacks.add(it.next().mLocalProvider); 3416 } 3417 } 3418 } 3419 final int N = mAllApplications.size(); 3420 for (int i=0; i<N; i++) { 3421 callbacks.add(mAllApplications.get(i)); 3422 } 3423 3424 return callbacks; 3425 } 3426 3427 private final void performConfigurationChanged( 3428 ComponentCallbacks cb, Configuration config) { 3429 // Only for Activity objects, check that they actually call up to their 3430 // superclass implementation. ComponentCallbacks is an interface, so 3431 // we check the runtime type and act accordingly. 3432 Activity activity = (cb instanceof Activity) ? (Activity) cb : null; 3433 if (activity != null) { 3434 activity.mCalled = false; 3435 } 3436 3437 boolean shouldChangeConfig = false; 3438 if ((activity == null) || (activity.mCurrentConfig == null)) { 3439 shouldChangeConfig = true; 3440 } else { 3441 3442 // If the new config is the same as the config this Activity 3443 // is already running with then don't bother calling 3444 // onConfigurationChanged 3445 int diff = activity.mCurrentConfig.diff(config); 3446 if (diff != 0) { 3447 3448 // If this activity doesn't handle any of the config changes 3449 // then don't bother calling onConfigurationChanged as we're 3450 // going to destroy it. 3451 if ((~activity.mActivityInfo.configChanges & diff) == 0) { 3452 shouldChangeConfig = true; 3453 } 3454 } 3455 } 3456 3457 if (shouldChangeConfig) { 3458 cb.onConfigurationChanged(config); 3459 3460 if (activity != null) { 3461 if (!activity.mCalled) { 3462 throw new SuperNotCalledException( 3463 "Activity " + activity.getLocalClassName() + 3464 " did not call through to super.onConfigurationChanged()"); 3465 } 3466 activity.mConfigChangeFlags = 0; 3467 activity.mCurrentConfig = new Configuration(config); 3468 } 3469 } 3470 } 3471 3472 final void handleConfigurationChanged(Configuration config) { 3473 3474 synchronized (mRelaunchingActivities) { 3475 if (mPendingConfiguration != null) { 3476 config = mPendingConfiguration; 3477 mPendingConfiguration = null; 3478 } 3479 } 3480 3481 ArrayList<ComponentCallbacks> callbacks 3482 = new ArrayList<ComponentCallbacks>(); 3483 3484 synchronized(mPackages) { 3485 if (mConfiguration == null) { 3486 mConfiguration = new Configuration(); 3487 } 3488 mConfiguration.updateFrom(config); 3489 DisplayMetrics dm = getDisplayMetricsLocked(true); 3490 DisplayMetrics appDm = new DisplayMetrics(); 3491 appDm.setTo(dm); 3492 3493 // set it for java, this also affects newly created Resources 3494 if (config.locale != null) { 3495 Locale.setDefault(config.locale); 3496 } 3497 3498 Resources.updateSystemConfiguration(config, null); 3499 3500 ApplicationContext.ApplicationPackageManager.configurationChanged(); 3501 //Log.i(TAG, "Configuration changed in " + currentPackageName()); 3502 { 3503 Iterator<WeakReference<Resources>> it = 3504 mActiveResources.values().iterator(); 3505 //Iterator<Map.Entry<String, WeakReference<Resources>>> it = 3506 // mActiveResources.entrySet().iterator(); 3507 while (it.hasNext()) { 3508 WeakReference<Resources> v = it.next(); 3509 Resources r = v.get(); 3510 if (r != null) { 3511 // keep the original density based on application cale. 3512 appDm.updateDensity(r.getDisplayMetrics().density); 3513 r.updateConfiguration(config, appDm); 3514 // reset 3515 appDm.setTo(dm); 3516 //Log.i(TAG, "Updated app resources " + v.getKey() 3517 // + " " + r + ": " + r.getConfiguration()); 3518 } else { 3519 //Log.i(TAG, "Removing old resources " + v.getKey()); 3520 it.remove(); 3521 } 3522 } 3523 } 3524 3525 callbacks = collectComponentCallbacksLocked(false, config); 3526 } 3527 3528 final int N = callbacks.size(); 3529 for (int i=0; i<N; i++) { 3530 performConfigurationChanged(callbacks.get(i), config); 3531 } 3532 } 3533 3534 final void handleActivityConfigurationChanged(IBinder token) { 3535 ActivityRecord r = mActivities.get(token); 3536 if (r == null || r.activity == null) { 3537 return; 3538 } 3539 3540 performConfigurationChanged(r.activity, mConfiguration); 3541 } 3542 3543 final void handleProfilerControl(boolean start, String path) { 3544 if (start) { 3545 File file = new File(path); 3546 file.getParentFile().mkdirs(); 3547 try { 3548 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 3549 } catch (RuntimeException e) { 3550 Log.w(TAG, "Profiling failed on path " + path 3551 + " -- can the process access this path?"); 3552 } 3553 } else { 3554 Debug.stopMethodTracing(); 3555 } 3556 } 3557 3558 final void handleLowMemory() { 3559 ArrayList<ComponentCallbacks> callbacks 3560 = new ArrayList<ComponentCallbacks>(); 3561 3562 synchronized(mPackages) { 3563 callbacks = collectComponentCallbacksLocked(true, null); 3564 } 3565 3566 final int N = callbacks.size(); 3567 for (int i=0; i<N; i++) { 3568 callbacks.get(i).onLowMemory(); 3569 } 3570 3571 // Ask SQLite to free up as much memory as it can, mostly from its page caches. 3572 if (Process.myUid() != Process.SYSTEM_UID) { 3573 int sqliteReleased = SQLiteDatabase.releaseMemory(); 3574 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); 3575 } 3576 3577 // Ask graphics to free up as much as possible (font/image caches) 3578 Canvas.freeCaches(); 3579 3580 BinderInternal.forceGc("mem"); 3581 } 3582 3583 private final void handleBindApplication(AppBindData data) { 3584 mBoundApplication = data; 3585 mConfiguration = new Configuration(data.config); 3586 3587 // We now rely on this being set by zygote. 3588 //Process.setGid(data.appInfo.gid); 3589 //Process.setUid(data.appInfo.uid); 3590 3591 // send up app name; do this *before* waiting for debugger 3592 android.ddm.DdmHandleAppName.setAppName(data.processName); 3593 3594 /* 3595 * Before spawning a new process, reset the time zone to be the system time zone. 3596 * This needs to be done because the system time zone could have changed after the 3597 * the spawning of this process. Without doing this this process would have the incorrect 3598 * system time zone. 3599 */ 3600 TimeZone.setDefault(null); 3601 3602 /* 3603 * Initialize the default locale in this process for the reasons we set the time zone. 3604 */ 3605 Locale.setDefault(data.config.locale); 3606 3607 data.info = getPackageInfoNoCheck(data.appInfo); 3608 3609 if (data.debugMode != IApplicationThread.DEBUG_OFF) { 3610 // XXX should have option to change the port. 3611 Debug.changeDebugPort(8100); 3612 if (data.debugMode == IApplicationThread.DEBUG_WAIT) { 3613 Log.w(TAG, "Application " + data.info.getPackageName() 3614 + " is waiting for the debugger on port 8100..."); 3615 3616 IActivityManager mgr = ActivityManagerNative.getDefault(); 3617 try { 3618 mgr.showWaitingForDebugger(mAppThread, true); 3619 } catch (RemoteException ex) { 3620 } 3621 3622 Debug.waitForDebugger(); 3623 3624 try { 3625 mgr.showWaitingForDebugger(mAppThread, false); 3626 } catch (RemoteException ex) { 3627 } 3628 3629 } else { 3630 Log.w(TAG, "Application " + data.info.getPackageName() 3631 + " can be debugged on port 8100..."); 3632 } 3633 } 3634 3635 if (data.instrumentationName != null) { 3636 ApplicationContext appContext = new ApplicationContext(); 3637 appContext.init(data.info, null, this); 3638 InstrumentationInfo ii = null; 3639 try { 3640 ii = appContext.getPackageManager(). 3641 getInstrumentationInfo(data.instrumentationName, 0); 3642 } catch (PackageManager.NameNotFoundException e) { 3643 } 3644 if (ii == null) { 3645 throw new RuntimeException( 3646 "Unable to find instrumentation info for: " 3647 + data.instrumentationName); 3648 } 3649 3650 mInstrumentationAppDir = ii.sourceDir; 3651 mInstrumentationAppPackage = ii.packageName; 3652 mInstrumentedAppDir = data.info.getAppDir(); 3653 3654 ApplicationInfo instrApp = new ApplicationInfo(); 3655 instrApp.packageName = ii.packageName; 3656 instrApp.sourceDir = ii.sourceDir; 3657 instrApp.publicSourceDir = ii.publicSourceDir; 3658 instrApp.dataDir = ii.dataDir; 3659 PackageInfo pi = getPackageInfo(instrApp, 3660 appContext.getClassLoader(), false, true); 3661 ApplicationContext instrContext = new ApplicationContext(); 3662 instrContext.init(pi, null, this); 3663 3664 try { 3665 java.lang.ClassLoader cl = instrContext.getClassLoader(); 3666 mInstrumentation = (Instrumentation) 3667 cl.loadClass(data.instrumentationName.getClassName()).newInstance(); 3668 } catch (Exception e) { 3669 throw new RuntimeException( 3670 "Unable to instantiate instrumentation " 3671 + data.instrumentationName + ": " + e.toString(), e); 3672 } 3673 3674 mInstrumentation.init(this, instrContext, appContext, 3675 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher); 3676 3677 if (data.profileFile != null && !ii.handleProfiling) { 3678 data.handlingProfiling = true; 3679 File file = new File(data.profileFile); 3680 file.getParentFile().mkdirs(); 3681 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 3682 } 3683 3684 try { 3685 mInstrumentation.onCreate(data.instrumentationArgs); 3686 } 3687 catch (Exception e) { 3688 throw new RuntimeException( 3689 "Exception thrown in onCreate() of " 3690 + data.instrumentationName + ": " + e.toString(), e); 3691 } 3692 3693 } else { 3694 mInstrumentation = new Instrumentation(); 3695 } 3696 3697 Application app = data.info.makeApplication(); 3698 mInitialApplication = app; 3699 3700 List<ProviderInfo> providers = data.providers; 3701 if (providers != null) { 3702 installContentProviders(app, providers); 3703 } 3704 3705 try { 3706 mInstrumentation.callApplicationOnCreate(app); 3707 } catch (Exception e) { 3708 if (!mInstrumentation.onException(app, e)) { 3709 throw new RuntimeException( 3710 "Unable to create application " + app.getClass().getName() 3711 + ": " + e.toString(), e); 3712 } 3713 } 3714 } 3715 3716 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) { 3717 IActivityManager am = ActivityManagerNative.getDefault(); 3718 if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) { 3719 Debug.stopMethodTracing(); 3720 } 3721 //Log.i(TAG, "am: " + ActivityManagerNative.getDefault() 3722 // + ", app thr: " + mAppThread); 3723 try { 3724 am.finishInstrumentation(mAppThread, resultCode, results); 3725 } catch (RemoteException ex) { 3726 } 3727 } 3728 3729 private final void installContentProviders( 3730 Context context, List<ProviderInfo> providers) { 3731 final ArrayList<IActivityManager.ContentProviderHolder> results = 3732 new ArrayList<IActivityManager.ContentProviderHolder>(); 3733 3734 Iterator<ProviderInfo> i = providers.iterator(); 3735 while (i.hasNext()) { 3736 ProviderInfo cpi = i.next(); 3737 StringBuilder buf = new StringBuilder(128); 3738 buf.append("Publishing provider "); 3739 buf.append(cpi.authority); 3740 buf.append(": "); 3741 buf.append(cpi.name); 3742 Log.i(TAG, buf.toString()); 3743 IContentProvider cp = installProvider(context, null, cpi, false); 3744 if (cp != null) { 3745 IActivityManager.ContentProviderHolder cph = 3746 new IActivityManager.ContentProviderHolder(cpi); 3747 cph.provider = cp; 3748 results.add(cph); 3749 // Don't ever unload this provider from the process. 3750 synchronized(mProviderMap) { 3751 mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000)); 3752 } 3753 } 3754 } 3755 3756 try { 3757 ActivityManagerNative.getDefault().publishContentProviders( 3758 getApplicationThread(), results); 3759 } catch (RemoteException ex) { 3760 } 3761 } 3762 3763 private final IContentProvider getProvider(Context context, String name) { 3764 synchronized(mProviderMap) { 3765 final ProviderRecord pr = mProviderMap.get(name); 3766 if (pr != null) { 3767 return pr.mProvider; 3768 } 3769 } 3770 3771 IActivityManager.ContentProviderHolder holder = null; 3772 try { 3773 holder = ActivityManagerNative.getDefault().getContentProvider( 3774 getApplicationThread(), name); 3775 } catch (RemoteException ex) { 3776 } 3777 if (holder == null) { 3778 Log.e(TAG, "Failed to find provider info for " + name); 3779 return null; 3780 } 3781 if (holder.permissionFailure != null) { 3782 throw new SecurityException("Permission " + holder.permissionFailure 3783 + " required for provider " + name); 3784 } 3785 3786 IContentProvider prov = installProvider(context, holder.provider, 3787 holder.info, true); 3788 //Log.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded); 3789 if (holder.noReleaseNeeded || holder.provider == null) { 3790 // We are not going to release the provider if it is an external 3791 // provider that doesn't care about being released, or if it is 3792 // a local provider running in this process. 3793 //Log.i(TAG, "*** NO RELEASE NEEDED"); 3794 synchronized(mProviderMap) { 3795 mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000)); 3796 } 3797 } 3798 return prov; 3799 } 3800 3801 public final IContentProvider acquireProvider(Context c, String name) { 3802 IContentProvider provider = getProvider(c, name); 3803 if(provider == null) 3804 return null; 3805 IBinder jBinder = provider.asBinder(); 3806 synchronized(mProviderMap) { 3807 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 3808 if(prc == null) { 3809 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); 3810 } else { 3811 prc.count++; 3812 } //end else 3813 } //end synchronized 3814 return provider; 3815 } 3816 3817 public final boolean releaseProvider(IContentProvider provider) { 3818 if(provider == null) { 3819 return false; 3820 } 3821 IBinder jBinder = provider.asBinder(); 3822 synchronized(mProviderMap) { 3823 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 3824 if(prc == null) { 3825 if(localLOGV) Log.v(TAG, "releaseProvider::Weird shouldnt be here"); 3826 return false; 3827 } else { 3828 prc.count--; 3829 if(prc.count == 0) { 3830 mProviderRefCountMap.remove(jBinder); 3831 //invoke removeProvider to dereference provider 3832 removeProviderLocked(provider); 3833 } //end if 3834 } //end else 3835 } //end synchronized 3836 return true; 3837 } 3838 3839 public final void removeProviderLocked(IContentProvider provider) { 3840 if (provider == null) { 3841 return; 3842 } 3843 IBinder providerBinder = provider.asBinder(); 3844 boolean amRemoveFlag = false; 3845 3846 // remove the provider from mProviderMap 3847 Iterator<ProviderRecord> iter = mProviderMap.values().iterator(); 3848 while (iter.hasNext()) { 3849 ProviderRecord pr = iter.next(); 3850 IBinder myBinder = pr.mProvider.asBinder(); 3851 if (myBinder == providerBinder) { 3852 //find if its published by this process itself 3853 if(pr.mLocalProvider != null) { 3854 if(localLOGV) Log.i(TAG, "removeProvider::found local provider returning"); 3855 return; 3856 } 3857 if(localLOGV) Log.v(TAG, "removeProvider::Not local provider Unlinking " + 3858 "death recipient"); 3859 //content provider is in another process 3860 myBinder.unlinkToDeath(pr, 0); 3861 iter.remove(); 3862 //invoke remove only once for the very first name seen 3863 if(!amRemoveFlag) { 3864 try { 3865 if(localLOGV) Log.v(TAG, "removeProvider::Invoking " + 3866 "ActivityManagerNative.removeContentProvider("+pr.mName); 3867 ActivityManagerNative.getDefault().removeContentProvider(getApplicationThread(), pr.mName); 3868 amRemoveFlag = true; 3869 } catch (RemoteException e) { 3870 //do nothing content provider object is dead any way 3871 } //end catch 3872 } 3873 } //end if myBinder 3874 } //end while iter 3875 } 3876 3877 final void removeDeadProvider(String name, IContentProvider provider) { 3878 synchronized(mProviderMap) { 3879 ProviderRecord pr = mProviderMap.get(name); 3880 if (pr.mProvider.asBinder() == provider.asBinder()) { 3881 Log.i(TAG, "Removing dead content provider: " + name); 3882 mProviderMap.remove(name); 3883 } 3884 } 3885 } 3886 3887 final void removeDeadProviderLocked(String name, IContentProvider provider) { 3888 ProviderRecord pr = mProviderMap.get(name); 3889 if (pr.mProvider.asBinder() == provider.asBinder()) { 3890 Log.i(TAG, "Removing dead content provider: " + name); 3891 mProviderMap.remove(name); 3892 } 3893 } 3894 3895 private final IContentProvider installProvider(Context context, 3896 IContentProvider provider, ProviderInfo info, boolean noisy) { 3897 ContentProvider localProvider = null; 3898 if (provider == null) { 3899 if (noisy) { 3900 Log.d(TAG, "Loading provider " + info.authority + ": " 3901 + info.name); 3902 } 3903 Context c = null; 3904 ApplicationInfo ai = info.applicationInfo; 3905 if (context.getPackageName().equals(ai.packageName)) { 3906 c = context; 3907 } else if (mInitialApplication != null && 3908 mInitialApplication.getPackageName().equals(ai.packageName)) { 3909 c = mInitialApplication; 3910 } else { 3911 try { 3912 c = context.createPackageContext(ai.packageName, 3913 Context.CONTEXT_INCLUDE_CODE); 3914 } catch (PackageManager.NameNotFoundException e) { 3915 } 3916 } 3917 if (c == null) { 3918 Log.w(TAG, "Unable to get context for package " + 3919 ai.packageName + 3920 " while loading content provider " + 3921 info.name); 3922 return null; 3923 } 3924 try { 3925 final java.lang.ClassLoader cl = c.getClassLoader(); 3926 localProvider = (ContentProvider)cl. 3927 loadClass(info.name).newInstance(); 3928 provider = localProvider.getIContentProvider(); 3929 if (provider == null) { 3930 Log.e(TAG, "Failed to instantiate class " + 3931 info.name + " from sourceDir " + 3932 info.applicationInfo.sourceDir); 3933 return null; 3934 } 3935 if (Config.LOGV) Log.v( 3936 TAG, "Instantiating local provider " + info.name); 3937 // XXX Need to create the correct context for this provider. 3938 localProvider.attachInfo(c, info); 3939 } catch (java.lang.Exception e) { 3940 if (!mInstrumentation.onException(null, e)) { 3941 throw new RuntimeException( 3942 "Unable to get provider " + info.name 3943 + ": " + e.toString(), e); 3944 } 3945 return null; 3946 } 3947 } else if (localLOGV) { 3948 Log.v(TAG, "Installing external provider " + info.authority + ": " 3949 + info.name); 3950 } 3951 3952 synchronized (mProviderMap) { 3953 // Cache the pointer for the remote provider. 3954 String names[] = PATTERN_SEMICOLON.split(info.authority); 3955 for (int i=0; i<names.length; i++) { 3956 ProviderRecord pr = new ProviderRecord(names[i], provider, 3957 localProvider); 3958 try { 3959 provider.asBinder().linkToDeath(pr, 0); 3960 mProviderMap.put(names[i], pr); 3961 } catch (RemoteException e) { 3962 return null; 3963 } 3964 } 3965 if (localProvider != null) { 3966 mLocalProviders.put(provider.asBinder(), 3967 new ProviderRecord(null, provider, localProvider)); 3968 } 3969 } 3970 3971 return provider; 3972 } 3973 3974 private final void attach(boolean system) { 3975 sThreadLocal.set(this); 3976 mSystemThread = system; 3977 AndroidHttpClient.setThreadBlocked(true); 3978 if (!system) { 3979 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>"); 3980 RuntimeInit.setApplicationObject(mAppThread.asBinder()); 3981 IActivityManager mgr = ActivityManagerNative.getDefault(); 3982 try { 3983 mgr.attachApplication(mAppThread); 3984 } catch (RemoteException ex) { 3985 } 3986 } else { 3987 // Don't set application object here -- if the system crashes, 3988 // we can't display an alert, we just want to die die die. 3989 android.ddm.DdmHandleAppName.setAppName("system_process"); 3990 try { 3991 mInstrumentation = new Instrumentation(); 3992 ApplicationContext context = new ApplicationContext(); 3993 context.init(getSystemContext().mPackageInfo, null, this); 3994 Application app = Instrumentation.newApplication(Application.class, context); 3995 mAllApplications.add(app); 3996 mInitialApplication = app; 3997 app.onCreate(); 3998 } catch (Exception e) { 3999 throw new RuntimeException( 4000 "Unable to instantiate Application():" + e.toString(), e); 4001 } 4002 } 4003 } 4004 4005 private final void detach() 4006 { 4007 AndroidHttpClient.setThreadBlocked(false); 4008 sThreadLocal.set(null); 4009 } 4010 4011 public static final ActivityThread systemMain() { 4012 ActivityThread thread = new ActivityThread(); 4013 thread.attach(true); 4014 return thread; 4015 } 4016 4017 public final void installSystemProviders(List providers) { 4018 if (providers != null) { 4019 installContentProviders(mInitialApplication, 4020 (List<ProviderInfo>)providers); 4021 } 4022 } 4023 4024 public static final void main(String[] args) { 4025 Process.setArgV0("<pre-initialized>"); 4026 4027 Looper.prepareMainLooper(); 4028 4029 ActivityThread thread = new ActivityThread(); 4030 thread.attach(false); 4031 4032 Looper.loop(); 4033 4034 if (Process.supportsProcesses()) { 4035 throw new RuntimeException("Main thread loop unexpectedly exited"); 4036 } 4037 4038 thread.detach(); 4039 String name; 4040 if (thread.mInitialApplication != null) name = thread.mInitialApplication.getPackageName(); 4041 else name = "<unknown>"; 4042 Log.i(TAG, "Main thread of " + name + " is now exiting"); 4043 } 4044} 4045