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