ActivityThread.java revision cb383183d722a9ef03ab8b8cb0d0e419efd96598
11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/* 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Copyright (C) 2006 The Android Open Source Project 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Licensed under the Apache License, Version 2.0 (the "License"); 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * you may not use this file except in compliance with the License. 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * You may obtain a copy of the License at 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * http://www.apache.org/licenses/LICENSE-2.0 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Unless required by applicable law or agreed to in writing, software 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * distributed under the License is distributed on an "AS IS" BASIS, 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * See the License for the specific language governing permissions and 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * limitations under the License. 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccipackage android.app; 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.app.backup.BackupAgent; 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.BroadcastReceiver; 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.ComponentCallbacks2; 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.ComponentName; 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.ContentProvider; 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.Context; 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.IContentProvider; 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.Intent; 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.IIntentReceiver; 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.pm.ActivityInfo; 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.pm.ApplicationInfo; 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.pm.IPackageManager; 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.pm.InstrumentationInfo; 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.pm.PackageInfo; 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.pm.PackageManager; 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.pm.PackageManager.NameNotFoundException; 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.pm.ProviderInfo; 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.pm.ServiceInfo; 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.res.AssetManager; 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.res.CompatibilityInfo; 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.res.Configuration; 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.res.Resources; 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.database.sqlite.SQLiteDatabase; 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.database.sqlite.SQLiteDebug; 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.database.sqlite.SQLiteDebug.DbStats; 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.graphics.Bitmap; 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.graphics.Canvas; 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.hardware.display.DisplayManagerGlobal; 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.net.IConnectivityManager; 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.net.Proxy; 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.net.ProxyInfo; 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.net.Uri; 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.opengl.GLUtils; 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.AsyncTask; 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Binder; 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Bundle; 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Debug; 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.DropBoxManager; 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Environment; 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Handler; 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.IBinder; 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Looper; 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Message; 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.MessageQueue; 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.ParcelFileDescriptor; 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.PersistableBundle; 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Process; 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.RemoteException; 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.ServiceManager; 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.StrictMode; 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.SystemClock; 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.SystemProperties; 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Trace; 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.UserHandle; 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.provider.Settings; 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.AndroidRuntimeException; 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.ArrayMap; 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.DisplayMetrics; 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.EventLog; 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.Log; 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.LogPrinter; 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.Pair; 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.PrintWriterPrinter; 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.Slog; 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.SuperNotCalledException; 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.Display; 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.HardwareRenderer; 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.View; 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.ViewDebug; 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.ViewManager; 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.ViewRootImpl; 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.Window; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.WindowManager; 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.WindowManagerGlobal; 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.renderscript.RenderScript; 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.security.AndroidKeyStoreProvider; 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport com.android.internal.app.IVoiceInteractor; 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport com.android.internal.os.BinderInternal; 98import com.android.internal.os.RuntimeInit; 99import com.android.internal.os.SamplingProfilerIntegration; 100import com.android.internal.util.FastPrintWriter; 101import com.android.org.conscrypt.OpenSSLSocketImpl; 102import com.android.org.conscrypt.TrustedCertificateStore; 103import com.google.android.collect.Lists; 104 105import java.io.File; 106import java.io.FileDescriptor; 107import java.io.FileOutputStream; 108import java.io.IOException; 109import java.io.PrintWriter; 110import java.lang.ref.WeakReference; 111import java.net.InetAddress; 112import java.security.Security; 113import java.text.DateFormat; 114import java.util.ArrayList; 115import java.util.List; 116import java.util.Locale; 117import java.util.Map; 118import java.util.Objects; 119import java.util.TimeZone; 120import java.util.regex.Pattern; 121 122import libcore.io.DropBox; 123import libcore.io.EventLogger; 124import libcore.io.IoUtils; 125import libcore.net.event.NetworkEventDispatcher; 126import dalvik.system.CloseGuard; 127import dalvik.system.VMDebug; 128import dalvik.system.VMRuntime; 129 130final class RemoteServiceException extends AndroidRuntimeException { 131 public RemoteServiceException(String msg) { 132 super(msg); 133 } 134} 135 136/** 137 * This manages the execution of the main thread in an 138 * application process, scheduling and executing activities, 139 * broadcasts, and other operations on it as the activity 140 * manager requests. 141 * 142 * {@hide} 143 */ 144public final class ActivityThread { 145 /** @hide */ 146 public static final String TAG = "ActivityThread"; 147 private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565; 148 static final boolean localLOGV = false; 149 static final boolean DEBUG_MESSAGES = false; 150 /** @hide */ 151 public static final boolean DEBUG_BROADCAST = false; 152 private static final boolean DEBUG_RESULTS = false; 153 private static final boolean DEBUG_BACKUP = false; 154 public static final boolean DEBUG_CONFIGURATION = false; 155 private static final boolean DEBUG_SERVICE = false; 156 private static final boolean DEBUG_MEMORY_TRIM = false; 157 private static final boolean DEBUG_PROVIDER = false; 158 private static final long MIN_TIME_BETWEEN_GCS = 5*1000; 159 private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); 160 private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; 161 private static final int LOG_ON_PAUSE_CALLED = 30021; 162 private static final int LOG_ON_RESUME_CALLED = 30022; 163 164 private ContextImpl mSystemContext; 165 166 static IPackageManager sPackageManager; 167 168 final ApplicationThread mAppThread = new ApplicationThread(); 169 final Looper mLooper = Looper.myLooper(); 170 final H mH = new H(); 171 final ArrayMap<IBinder, ActivityClientRecord> mActivities 172 = new ArrayMap<IBinder, ActivityClientRecord>(); 173 // List of new activities (via ActivityRecord.nextIdle) that should 174 // be reported when next we idle. 175 ActivityClientRecord mNewActivities = null; 176 // Number of activities that are currently visible on-screen. 177 int mNumVisibleActivities = 0; 178 final ArrayMap<IBinder, Service> mServices 179 = new ArrayMap<IBinder, Service>(); 180 AppBindData mBoundApplication; 181 Profiler mProfiler; 182 int mCurDefaultDisplayDpi; 183 boolean mDensityCompatMode; 184 Configuration mConfiguration; 185 Configuration mCompatConfiguration; 186 Application mInitialApplication; 187 final ArrayList<Application> mAllApplications 188 = new ArrayList<Application>(); 189 // set of instantiated backup agents, keyed by package name 190 final ArrayMap<String, BackupAgent> mBackupAgents = new ArrayMap<String, BackupAgent>(); 191 /** Reference to singleton {@link ActivityThread} */ 192 private static ActivityThread sCurrentActivityThread; 193 Instrumentation mInstrumentation; 194 String mInstrumentationPackageName = null; 195 String mInstrumentationAppDir = null; 196 String[] mInstrumentationSplitAppDirs = null; 197 String mInstrumentationLibDir = null; 198 String mInstrumentedAppDir = null; 199 String[] mInstrumentedSplitAppDirs = null; 200 String mInstrumentedLibDir = null; 201 boolean mSystemThread = false; 202 boolean mJitEnabled = false; 203 boolean mSomeActivitiesChanged = false; 204 205 // These can be accessed by multiple threads; mPackages is the lock. 206 // XXX For now we keep around information about all packages we have 207 // seen, not removing entries from this map. 208 // NOTE: The activity and window managers need to call in to 209 // ActivityThread to do things like update resource configurations, 210 // which means this lock gets held while the activity and window managers 211 // holds their own lock. Thus you MUST NEVER call back into the activity manager 212 // or window manager or anything that depends on them while holding this lock. 213 final ArrayMap<String, WeakReference<LoadedApk>> mPackages 214 = new ArrayMap<String, WeakReference<LoadedApk>>(); 215 final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages 216 = new ArrayMap<String, WeakReference<LoadedApk>>(); 217 final ArrayList<ActivityClientRecord> mRelaunchingActivities 218 = new ArrayList<ActivityClientRecord>(); 219 Configuration mPendingConfiguration = null; 220 221 private final ResourcesManager mResourcesManager; 222 223 private static final class ProviderKey { 224 final String authority; 225 final int userId; 226 227 public ProviderKey(String authority, int userId) { 228 this.authority = authority; 229 this.userId = userId; 230 } 231 232 @Override 233 public boolean equals(Object o) { 234 if (o instanceof ProviderKey) { 235 final ProviderKey other = (ProviderKey) o; 236 return Objects.equals(authority, other.authority) && userId == other.userId; 237 } 238 return false; 239 } 240 241 @Override 242 public int hashCode() { 243 return ((authority != null) ? authority.hashCode() : 0) ^ userId; 244 } 245 } 246 247 // The lock of mProviderMap protects the following variables. 248 final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap 249 = new ArrayMap<ProviderKey, ProviderClientRecord>(); 250 final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap 251 = new ArrayMap<IBinder, ProviderRefCount>(); 252 final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders 253 = new ArrayMap<IBinder, ProviderClientRecord>(); 254 final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName 255 = new ArrayMap<ComponentName, ProviderClientRecord>(); 256 257 final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners 258 = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>(); 259 260 final GcIdler mGcIdler = new GcIdler(); 261 boolean mGcIdlerScheduled = false; 262 263 static Handler sMainThreadHandler; // set once in main() 264 265 Bundle mCoreSettings = null; 266 267 static final class ActivityClientRecord { 268 IBinder token; 269 int ident; 270 Intent intent; 271 IVoiceInteractor voiceInteractor; 272 Bundle state; 273 PersistableBundle persistentState; 274 Activity activity; 275 Window window; 276 Activity parent; 277 String embeddedID; 278 Activity.NonConfigurationInstances lastNonConfigurationInstances; 279 boolean paused; 280 boolean stopped; 281 boolean hideForNow; 282 Configuration newConfig; 283 Configuration createdConfig; 284 ActivityClientRecord nextIdle; 285 286 ProfilerInfo profilerInfo; 287 288 ActivityInfo activityInfo; 289 CompatibilityInfo compatInfo; 290 LoadedApk packageInfo; 291 292 List<ResultInfo> pendingResults; 293 List<Intent> pendingIntents; 294 295 boolean startsNotResumed; 296 boolean isForward; 297 int pendingConfigChanges; 298 boolean onlyLocalRequest; 299 300 View mPendingRemoveWindow; 301 WindowManager mPendingRemoveWindowManager; 302 303 ActivityClientRecord() { 304 parent = null; 305 embeddedID = null; 306 paused = false; 307 stopped = false; 308 hideForNow = false; 309 nextIdle = null; 310 } 311 312 public boolean isPreHoneycomb() { 313 if (activity != null) { 314 return activity.getApplicationInfo().targetSdkVersion 315 < android.os.Build.VERSION_CODES.HONEYCOMB; 316 } 317 return false; 318 } 319 320 public boolean isPersistable() { 321 return activityInfo.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS; 322 } 323 324 public String toString() { 325 ComponentName componentName = intent != null ? intent.getComponent() : null; 326 return "ActivityRecord{" 327 + Integer.toHexString(System.identityHashCode(this)) 328 + " token=" + token + " " + (componentName == null 329 ? "no component name" : componentName.toShortString()) 330 + "}"; 331 } 332 } 333 334 final class ProviderClientRecord { 335 final String[] mNames; 336 final IContentProvider mProvider; 337 final ContentProvider mLocalProvider; 338 final IActivityManager.ContentProviderHolder mHolder; 339 340 ProviderClientRecord(String[] names, IContentProvider provider, 341 ContentProvider localProvider, 342 IActivityManager.ContentProviderHolder holder) { 343 mNames = names; 344 mProvider = provider; 345 mLocalProvider = localProvider; 346 mHolder = holder; 347 } 348 } 349 350 static final class NewIntentData { 351 List<Intent> intents; 352 IBinder token; 353 public String toString() { 354 return "NewIntentData{intents=" + intents + " token=" + token + "}"; 355 } 356 } 357 358 static final class ReceiverData extends BroadcastReceiver.PendingResult { 359 public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras, 360 boolean ordered, boolean sticky, IBinder token, int sendingUser) { 361 super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, 362 token, sendingUser); 363 this.intent = intent; 364 } 365 366 Intent intent; 367 ActivityInfo info; 368 CompatibilityInfo compatInfo; 369 public String toString() { 370 return "ReceiverData{intent=" + intent + " packageName=" + 371 info.packageName + " resultCode=" + getResultCode() 372 + " resultData=" + getResultData() + " resultExtras=" 373 + getResultExtras(false) + "}"; 374 } 375 } 376 377 static final class CreateBackupAgentData { 378 ApplicationInfo appInfo; 379 CompatibilityInfo compatInfo; 380 int backupMode; 381 public String toString() { 382 return "CreateBackupAgentData{appInfo=" + appInfo 383 + " backupAgent=" + appInfo.backupAgentName 384 + " mode=" + backupMode + "}"; 385 } 386 } 387 388 static final class CreateServiceData { 389 IBinder token; 390 ServiceInfo info; 391 CompatibilityInfo compatInfo; 392 Intent intent; 393 public String toString() { 394 return "CreateServiceData{token=" + token + " className=" 395 + info.name + " packageName=" + info.packageName 396 + " intent=" + intent + "}"; 397 } 398 } 399 400 static final class BindServiceData { 401 IBinder token; 402 Intent intent; 403 boolean rebind; 404 public String toString() { 405 return "BindServiceData{token=" + token + " intent=" + intent + "}"; 406 } 407 } 408 409 static final class ServiceArgsData { 410 IBinder token; 411 boolean taskRemoved; 412 int startId; 413 int flags; 414 Intent args; 415 public String toString() { 416 return "ServiceArgsData{token=" + token + " startId=" + startId 417 + " args=" + args + "}"; 418 } 419 } 420 421 static final class AppBindData { 422 LoadedApk info; 423 String processName; 424 ApplicationInfo appInfo; 425 List<ProviderInfo> providers; 426 ComponentName instrumentationName; 427 Bundle instrumentationArgs; 428 IInstrumentationWatcher instrumentationWatcher; 429 IUiAutomationConnection instrumentationUiAutomationConnection; 430 int debugMode; 431 boolean enableOpenGlTrace; 432 boolean restrictedBackupMode; 433 boolean persistent; 434 Configuration config; 435 CompatibilityInfo compatInfo; 436 437 /** Initial values for {@link Profiler}. */ 438 ProfilerInfo initProfilerInfo; 439 440 public String toString() { 441 return "AppBindData{appInfo=" + appInfo + "}"; 442 } 443 } 444 445 static final class Profiler { 446 String profileFile; 447 ParcelFileDescriptor profileFd; 448 int samplingInterval; 449 boolean autoStopProfiler; 450 boolean profiling; 451 boolean handlingProfiling; 452 public void setProfiler(ProfilerInfo profilerInfo) { 453 ParcelFileDescriptor fd = profilerInfo.profileFd; 454 if (profiling) { 455 if (fd != null) { 456 try { 457 fd.close(); 458 } catch (IOException e) { 459 // Ignore 460 } 461 } 462 return; 463 } 464 if (profileFd != null) { 465 try { 466 profileFd.close(); 467 } catch (IOException e) { 468 // Ignore 469 } 470 } 471 profileFile = profilerInfo.profileFile; 472 profileFd = fd; 473 samplingInterval = profilerInfo.samplingInterval; 474 autoStopProfiler = profilerInfo.autoStopProfiler; 475 } 476 public void startProfiling() { 477 if (profileFd == null || profiling) { 478 return; 479 } 480 try { 481 VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(), 482 8 * 1024 * 1024, 0, samplingInterval != 0, samplingInterval); 483 profiling = true; 484 } catch (RuntimeException e) { 485 Slog.w(TAG, "Profiling failed on path " + profileFile); 486 try { 487 profileFd.close(); 488 profileFd = null; 489 } catch (IOException e2) { 490 Slog.w(TAG, "Failure closing profile fd", e2); 491 } 492 } 493 } 494 public void stopProfiling() { 495 if (profiling) { 496 profiling = false; 497 Debug.stopMethodTracing(); 498 if (profileFd != null) { 499 try { 500 profileFd.close(); 501 } catch (IOException e) { 502 } 503 } 504 profileFd = null; 505 profileFile = null; 506 } 507 } 508 } 509 510 static final class DumpComponentInfo { 511 ParcelFileDescriptor fd; 512 IBinder token; 513 String prefix; 514 String[] args; 515 } 516 517 static final class ResultData { 518 IBinder token; 519 List<ResultInfo> results; 520 public String toString() { 521 return "ResultData{token=" + token + " results" + results + "}"; 522 } 523 } 524 525 static final class ContextCleanupInfo { 526 ContextImpl context; 527 String what; 528 String who; 529 } 530 531 static final class DumpHeapData { 532 String path; 533 ParcelFileDescriptor fd; 534 } 535 536 static final class UpdateCompatibilityData { 537 String pkg; 538 CompatibilityInfo info; 539 } 540 541 static final class RequestAssistContextExtras { 542 IBinder activityToken; 543 IBinder requestToken; 544 int requestType; 545 } 546 547 private native void dumpGraphicsInfo(FileDescriptor fd); 548 549 private class ApplicationThread extends ApplicationThreadNative { 550 private static final String ONE_COUNT_COLUMN = "%21s %8d"; 551 private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d"; 552 private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s"; 553 554 private int mLastProcessState = -1; 555 556 private void updatePendingConfiguration(Configuration config) { 557 synchronized (mResourcesManager) { 558 if (mPendingConfiguration == null || 559 mPendingConfiguration.isOtherSeqNewer(config)) { 560 mPendingConfiguration = config; 561 } 562 } 563 } 564 565 public final void schedulePauseActivity(IBinder token, boolean finished, 566 boolean userLeaving, int configChanges, boolean dontReport) { 567 sendMessage( 568 finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, 569 token, 570 (userLeaving ? 1 : 0) | (dontReport ? 2 : 0), 571 configChanges); 572 } 573 574 public final void scheduleStopActivity(IBinder token, boolean showWindow, 575 int configChanges) { 576 sendMessage( 577 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE, 578 token, 0, configChanges); 579 } 580 581 public final void scheduleWindowVisibility(IBinder token, boolean showWindow) { 582 sendMessage( 583 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW, 584 token); 585 } 586 587 public final void scheduleSleeping(IBinder token, boolean sleeping) { 588 sendMessage(H.SLEEPING, token, sleeping ? 1 : 0); 589 } 590 591 public final void scheduleResumeActivity(IBinder token, int processState, 592 boolean isForward, Bundle resumeArgs) { 593 updateProcessState(processState, false); 594 sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0); 595 } 596 597 public final void scheduleSendResult(IBinder token, List<ResultInfo> results) { 598 ResultData res = new ResultData(); 599 res.token = token; 600 res.results = results; 601 sendMessage(H.SEND_RESULT, res); 602 } 603 604 // we use token to identify this activity without having to send the 605 // activity itself back to the activity manager. (matters more with ipc) 606 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, 607 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, 608 IVoiceInteractor voiceInteractor, int procState, Bundle state, 609 PersistableBundle persistentState, List<ResultInfo> pendingResults, 610 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, 611 ProfilerInfo profilerInfo) { 612 613 updateProcessState(procState, false); 614 615 ActivityClientRecord r = new ActivityClientRecord(); 616 617 r.token = token; 618 r.ident = ident; 619 r.intent = intent; 620 r.voiceInteractor = voiceInteractor; 621 r.activityInfo = info; 622 r.compatInfo = compatInfo; 623 r.state = state; 624 r.persistentState = persistentState; 625 626 r.pendingResults = pendingResults; 627 r.pendingIntents = pendingNewIntents; 628 629 r.startsNotResumed = notResumed; 630 r.isForward = isForward; 631 632 r.profilerInfo = profilerInfo; 633 634 updatePendingConfiguration(curConfig); 635 636 sendMessage(H.LAUNCH_ACTIVITY, r); 637 } 638 639 public final void scheduleRelaunchActivity(IBinder token, 640 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, 641 int configChanges, boolean notResumed, Configuration config) { 642 requestRelaunchActivity(token, pendingResults, pendingNewIntents, 643 configChanges, notResumed, config, true); 644 } 645 646 public final void scheduleNewIntent(List<Intent> intents, IBinder token) { 647 NewIntentData data = new NewIntentData(); 648 data.intents = intents; 649 data.token = token; 650 651 sendMessage(H.NEW_INTENT, data); 652 } 653 654 public final void scheduleDestroyActivity(IBinder token, boolean finishing, 655 int configChanges) { 656 sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0, 657 configChanges); 658 } 659 660 public final void scheduleReceiver(Intent intent, ActivityInfo info, 661 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, 662 boolean sync, int sendingUser, int processState) { 663 updateProcessState(processState, false); 664 ReceiverData r = new ReceiverData(intent, resultCode, data, extras, 665 sync, false, mAppThread.asBinder(), sendingUser); 666 r.info = info; 667 r.compatInfo = compatInfo; 668 sendMessage(H.RECEIVER, r); 669 } 670 671 public final void scheduleCreateBackupAgent(ApplicationInfo app, 672 CompatibilityInfo compatInfo, int backupMode) { 673 CreateBackupAgentData d = new CreateBackupAgentData(); 674 d.appInfo = app; 675 d.compatInfo = compatInfo; 676 d.backupMode = backupMode; 677 678 sendMessage(H.CREATE_BACKUP_AGENT, d); 679 } 680 681 public final void scheduleDestroyBackupAgent(ApplicationInfo app, 682 CompatibilityInfo compatInfo) { 683 CreateBackupAgentData d = new CreateBackupAgentData(); 684 d.appInfo = app; 685 d.compatInfo = compatInfo; 686 687 sendMessage(H.DESTROY_BACKUP_AGENT, d); 688 } 689 690 public final void scheduleCreateService(IBinder token, 691 ServiceInfo info, CompatibilityInfo compatInfo, int processState) { 692 updateProcessState(processState, false); 693 CreateServiceData s = new CreateServiceData(); 694 s.token = token; 695 s.info = info; 696 s.compatInfo = compatInfo; 697 698 sendMessage(H.CREATE_SERVICE, s); 699 } 700 701 public final void scheduleBindService(IBinder token, Intent intent, 702 boolean rebind, int processState) { 703 updateProcessState(processState, false); 704 BindServiceData s = new BindServiceData(); 705 s.token = token; 706 s.intent = intent; 707 s.rebind = rebind; 708 709 if (DEBUG_SERVICE) 710 Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid=" 711 + Binder.getCallingUid() + " pid=" + Binder.getCallingPid()); 712 sendMessage(H.BIND_SERVICE, s); 713 } 714 715 public final void scheduleUnbindService(IBinder token, Intent intent) { 716 BindServiceData s = new BindServiceData(); 717 s.token = token; 718 s.intent = intent; 719 720 sendMessage(H.UNBIND_SERVICE, s); 721 } 722 723 public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId, 724 int flags ,Intent args) { 725 ServiceArgsData s = new ServiceArgsData(); 726 s.token = token; 727 s.taskRemoved = taskRemoved; 728 s.startId = startId; 729 s.flags = flags; 730 s.args = args; 731 732 sendMessage(H.SERVICE_ARGS, s); 733 } 734 735 public final void scheduleStopService(IBinder token) { 736 sendMessage(H.STOP_SERVICE, token); 737 } 738 739 public final void bindApplication(String processName, ApplicationInfo appInfo, 740 List<ProviderInfo> providers, ComponentName instrumentationName, 741 ProfilerInfo profilerInfo, Bundle instrumentationArgs, 742 IInstrumentationWatcher instrumentationWatcher, 743 IUiAutomationConnection instrumentationUiConnection, int debugMode, 744 boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, 745 Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, 746 Bundle coreSettings) { 747 748 if (services != null) { 749 // Setup the service cache in the ServiceManager 750 ServiceManager.initServiceCache(services); 751 } 752 753 setCoreSettings(coreSettings); 754 755 /* 756 * Two possible indications that this package could be 757 * sharing its runtime with other packages: 758 * 759 * 1.) the sharedUserId attribute is set in the manifest, 760 * indicating a request to share a VM with other 761 * packages with the same sharedUserId. 762 * 763 * 2.) the application element of the manifest has an 764 * attribute specifying a non-default process name, 765 * indicating the desire to run in another packages VM. 766 * 767 * If sharing is enabled we do not have a unique application 768 * in a process and therefore cannot rely on the package 769 * name inside the runtime. 770 */ 771 IPackageManager pm = getPackageManager(); 772 android.content.pm.PackageInfo pi = null; 773 try { 774 pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId()); 775 } catch (RemoteException e) { 776 } 777 if (pi != null) { 778 boolean sharedUserIdSet = (pi.sharedUserId != null); 779 boolean processNameNotDefault = 780 (pi.applicationInfo != null && 781 !appInfo.packageName.equals(pi.applicationInfo.processName)); 782 boolean sharable = (sharedUserIdSet || processNameNotDefault); 783 784 // Tell the VMRuntime about the application, unless it is shared 785 // inside a process. 786 if (!sharable) { 787 VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir, 788 appInfo.processName); 789 } 790 } 791 792 AppBindData data = new AppBindData(); 793 data.processName = processName; 794 data.appInfo = appInfo; 795 data.providers = providers; 796 data.instrumentationName = instrumentationName; 797 data.instrumentationArgs = instrumentationArgs; 798 data.instrumentationWatcher = instrumentationWatcher; 799 data.instrumentationUiAutomationConnection = instrumentationUiConnection; 800 data.debugMode = debugMode; 801 data.enableOpenGlTrace = enableOpenGlTrace; 802 data.restrictedBackupMode = isRestrictedBackupMode; 803 data.persistent = persistent; 804 data.config = config; 805 data.compatInfo = compatInfo; 806 data.initProfilerInfo = profilerInfo; 807 sendMessage(H.BIND_APPLICATION, data); 808 } 809 810 public final void scheduleExit() { 811 sendMessage(H.EXIT_APPLICATION, null); 812 } 813 814 public final void scheduleSuicide() { 815 sendMessage(H.SUICIDE, null); 816 } 817 818 public void scheduleConfigurationChanged(Configuration config) { 819 updatePendingConfiguration(config); 820 sendMessage(H.CONFIGURATION_CHANGED, config); 821 } 822 823 public void updateTimeZone() { 824 TimeZone.setDefault(null); 825 } 826 827 public void clearDnsCache() { 828 // a non-standard API to get this to libcore 829 InetAddress.clearDnsCache(); 830 // Allow libcore to perform the necessary actions as it sees fit upon a network 831 // configuration change. 832 NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged(); 833 } 834 835 public void setHttpProxy(String host, String port, String exclList, Uri pacFileUrl) { 836 Proxy.setHttpProxySystemProperty(host, port, exclList, pacFileUrl); 837 } 838 839 public void processInBackground() { 840 mH.removeMessages(H.GC_WHEN_IDLE); 841 mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE)); 842 } 843 844 public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) { 845 DumpComponentInfo data = new DumpComponentInfo(); 846 try { 847 data.fd = ParcelFileDescriptor.dup(fd); 848 data.token = servicetoken; 849 data.args = args; 850 sendMessage(H.DUMP_SERVICE, data, 0, 0, true /*async*/); 851 } catch (IOException e) { 852 Slog.w(TAG, "dumpService failed", e); 853 } 854 } 855 856 // This function exists to make sure all receiver dispatching is 857 // correctly ordered, since these are one-way calls and the binder driver 858 // applies transaction ordering per object for such calls. 859 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, 860 int resultCode, String dataStr, Bundle extras, boolean ordered, 861 boolean sticky, int sendingUser, int processState) throws RemoteException { 862 updateProcessState(processState, false); 863 receiver.performReceive(intent, resultCode, dataStr, extras, ordered, 864 sticky, sendingUser); 865 } 866 867 public void scheduleLowMemory() { 868 sendMessage(H.LOW_MEMORY, null); 869 } 870 871 public void scheduleActivityConfigurationChanged(IBinder token) { 872 sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token); 873 } 874 875 public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) { 876 sendMessage(H.PROFILER_CONTROL, profilerInfo, start ? 1 : 0, profileType); 877 } 878 879 public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) { 880 DumpHeapData dhd = new DumpHeapData(); 881 dhd.path = path; 882 dhd.fd = fd; 883 sendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0, 0, true /*async*/); 884 } 885 886 public void setSchedulingGroup(int group) { 887 // Note: do this immediately, since going into the foreground 888 // should happen regardless of what pending work we have to do 889 // and the activity manager will wait for us to report back that 890 // we are done before sending us to the background. 891 try { 892 Process.setProcessGroup(Process.myPid(), group); 893 } catch (Exception e) { 894 Slog.w(TAG, "Failed setting process group to " + group, e); 895 } 896 } 897 898 public void dispatchPackageBroadcast(int cmd, String[] packages) { 899 sendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd); 900 } 901 902 public void scheduleCrash(String msg) { 903 sendMessage(H.SCHEDULE_CRASH, msg); 904 } 905 906 public void dumpActivity(FileDescriptor fd, IBinder activitytoken, 907 String prefix, String[] args) { 908 DumpComponentInfo data = new DumpComponentInfo(); 909 try { 910 data.fd = ParcelFileDescriptor.dup(fd); 911 data.token = activitytoken; 912 data.prefix = prefix; 913 data.args = args; 914 sendMessage(H.DUMP_ACTIVITY, data, 0, 0, true /*async*/); 915 } catch (IOException e) { 916 Slog.w(TAG, "dumpActivity failed", e); 917 } 918 } 919 920 public void dumpProvider(FileDescriptor fd, IBinder providertoken, 921 String[] args) { 922 DumpComponentInfo data = new DumpComponentInfo(); 923 try { 924 data.fd = ParcelFileDescriptor.dup(fd); 925 data.token = providertoken; 926 data.args = args; 927 sendMessage(H.DUMP_PROVIDER, data, 0, 0, true /*async*/); 928 } catch (IOException e) { 929 Slog.w(TAG, "dumpProvider failed", e); 930 } 931 } 932 933 @Override 934 public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin, 935 boolean dumpFullInfo, boolean dumpDalvik, String[] args) { 936 FileOutputStream fout = new FileOutputStream(fd); 937 PrintWriter pw = new FastPrintWriter(fout); 938 try { 939 dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik); 940 } finally { 941 pw.flush(); 942 } 943 } 944 945 private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin, 946 boolean dumpFullInfo, boolean dumpDalvik) { 947 long nativeMax = Debug.getNativeHeapSize() / 1024; 948 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; 949 long nativeFree = Debug.getNativeHeapFreeSize() / 1024; 950 951 Runtime runtime = Runtime.getRuntime(); 952 953 long dalvikMax = runtime.totalMemory() / 1024; 954 long dalvikFree = runtime.freeMemory() / 1024; 955 long dalvikAllocated = dalvikMax - dalvikFree; 956 long viewInstanceCount = ViewDebug.getViewInstanceCount(); 957 long viewRootInstanceCount = ViewDebug.getViewRootImplCount(); 958 long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class); 959 long activityInstanceCount = Debug.countInstancesOfClass(Activity.class); 960 int globalAssetCount = AssetManager.getGlobalAssetCount(); 961 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount(); 962 int binderLocalObjectCount = Debug.getBinderLocalObjectCount(); 963 int binderProxyObjectCount = Debug.getBinderProxyObjectCount(); 964 int binderDeathObjectCount = Debug.getBinderDeathObjectCount(); 965 long openSslSocketCount = Debug.countInstancesOfClass(OpenSSLSocketImpl.class); 966 SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo(); 967 968 dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, Process.myPid(), 969 (mBoundApplication != null) ? mBoundApplication.processName : "unknown", 970 nativeMax, nativeAllocated, nativeFree, 971 dalvikMax, dalvikAllocated, dalvikFree); 972 973 if (checkin) { 974 // NOTE: if you change anything significant below, also consider changing 975 // ACTIVITY_THREAD_CHECKIN_VERSION. 976 977 // Object counts 978 pw.print(viewInstanceCount); pw.print(','); 979 pw.print(viewRootInstanceCount); pw.print(','); 980 pw.print(appContextInstanceCount); pw.print(','); 981 pw.print(activityInstanceCount); pw.print(','); 982 983 pw.print(globalAssetCount); pw.print(','); 984 pw.print(globalAssetManagerCount); pw.print(','); 985 pw.print(binderLocalObjectCount); pw.print(','); 986 pw.print(binderProxyObjectCount); pw.print(','); 987 988 pw.print(binderDeathObjectCount); pw.print(','); 989 pw.print(openSslSocketCount); pw.print(','); 990 991 // SQL 992 pw.print(stats.memoryUsed / 1024); pw.print(','); 993 pw.print(stats.memoryUsed / 1024); pw.print(','); 994 pw.print(stats.pageCacheOverflow / 1024); pw.print(','); 995 pw.print(stats.largestMemAlloc / 1024); 996 for (int i = 0; i < stats.dbStats.size(); i++) { 997 DbStats dbStats = stats.dbStats.get(i); 998 pw.print(','); pw.print(dbStats.dbName); 999 pw.print(','); pw.print(dbStats.pageSize); 1000 pw.print(','); pw.print(dbStats.dbSize); 1001 pw.print(','); pw.print(dbStats.lookaside); 1002 pw.print(','); pw.print(dbStats.cache); 1003 pw.print(','); pw.print(dbStats.cache); 1004 } 1005 pw.println(); 1006 1007 return; 1008 } 1009 1010 pw.println(" "); 1011 pw.println(" Objects"); 1012 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:", 1013 viewRootInstanceCount); 1014 1015 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount, 1016 "Activities:", activityInstanceCount); 1017 1018 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount, 1019 "AssetManagers:", globalAssetManagerCount); 1020 1021 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount, 1022 "Proxy Binders:", binderProxyObjectCount); 1023 printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount); 1024 1025 printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount); 1026 1027 // SQLite mem info 1028 pw.println(" "); 1029 pw.println(" SQL"); 1030 printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024); 1031 printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:", 1032 stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024); 1033 pw.println(" "); 1034 int N = stats.dbStats.size(); 1035 if (N > 0) { 1036 pw.println(" DATABASES"); 1037 printRow(pw, " %8s %8s %14s %14s %s", "pgsz", "dbsz", "Lookaside(b)", "cache", 1038 "Dbname"); 1039 for (int i = 0; i < N; i++) { 1040 DbStats dbStats = stats.dbStats.get(i); 1041 printRow(pw, DB_INFO_FORMAT, 1042 (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ", 1043 (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ", 1044 (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ", 1045 dbStats.cache, dbStats.dbName); 1046 } 1047 } 1048 1049 // Asset details. 1050 String assetAlloc = AssetManager.getAssetAllocations(); 1051 if (assetAlloc != null) { 1052 pw.println(" "); 1053 pw.println(" Asset Allocations"); 1054 pw.print(assetAlloc); 1055 } 1056 } 1057 1058 @Override 1059 public void dumpGfxInfo(FileDescriptor fd, String[] args) { 1060 dumpGraphicsInfo(fd); 1061 WindowManagerGlobal.getInstance().dumpGfxInfo(fd); 1062 } 1063 1064 @Override 1065 public void dumpDbInfo(FileDescriptor fd, String[] args) { 1066 PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd)); 1067 PrintWriterPrinter printer = new PrintWriterPrinter(pw); 1068 SQLiteDebug.dump(printer, args); 1069 pw.flush(); 1070 } 1071 1072 @Override 1073 public void unstableProviderDied(IBinder provider) { 1074 sendMessage(H.UNSTABLE_PROVIDER_DIED, provider); 1075 } 1076 1077 @Override 1078 public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, 1079 int requestType) { 1080 RequestAssistContextExtras cmd = new RequestAssistContextExtras(); 1081 cmd.activityToken = activityToken; 1082 cmd.requestToken = requestToken; 1083 cmd.requestType = requestType; 1084 sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd); 1085 } 1086 1087 public void setCoreSettings(Bundle coreSettings) { 1088 sendMessage(H.SET_CORE_SETTINGS, coreSettings); 1089 } 1090 1091 public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) { 1092 UpdateCompatibilityData ucd = new UpdateCompatibilityData(); 1093 ucd.pkg = pkg; 1094 ucd.info = info; 1095 sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd); 1096 } 1097 1098 public void scheduleTrimMemory(int level) { 1099 sendMessage(H.TRIM_MEMORY, null, level); 1100 } 1101 1102 public void scheduleTranslucentConversionComplete(IBinder token, boolean drawComplete) { 1103 sendMessage(H.TRANSLUCENT_CONVERSION_COMPLETE, token, drawComplete ? 1 : 0); 1104 } 1105 1106 public void scheduleOnNewActivityOptions(IBinder token, ActivityOptions options) { 1107 sendMessage(H.ON_NEW_ACTIVITY_OPTIONS, 1108 new Pair<IBinder, ActivityOptions>(token, options)); 1109 } 1110 1111 public void setProcessState(int state) { 1112 updateProcessState(state, true); 1113 } 1114 1115 public void updateProcessState(int processState, boolean fromIpc) { 1116 synchronized (this) { 1117 if (mLastProcessState != processState) { 1118 mLastProcessState = processState; 1119 // Update Dalvik state based on ActivityManager.PROCESS_STATE_* constants. 1120 final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0; 1121 final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1; 1122 int dalvikProcessState = DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE; 1123 // TODO: Tune this since things like gmail sync are important background but not jank perceptible. 1124 if (processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { 1125 dalvikProcessState = DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE; 1126 } 1127 VMRuntime.getRuntime().updateProcessState(dalvikProcessState); 1128 if (false) { 1129 Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState 1130 + (fromIpc ? " (from ipc": "")); 1131 } 1132 } 1133 } 1134 } 1135 1136 @Override 1137 public void scheduleInstallProvider(ProviderInfo provider) { 1138 sendMessage(H.INSTALL_PROVIDER, provider); 1139 } 1140 1141 @Override 1142 public final void updateTimePrefs(boolean is24Hour) { 1143 DateFormat.set24HourTimePref(is24Hour); 1144 } 1145 1146 @Override 1147 public void scheduleCancelVisibleBehind(IBinder token) { 1148 sendMessage(H.CANCEL_VISIBLE_BEHIND, token); 1149 } 1150 1151 @Override 1152 public void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean visible) { 1153 sendMessage(H.BACKGROUND_VISIBLE_BEHIND_CHANGED, token, visible ? 1 : 0); 1154 } 1155 1156 public void scheduleEnterAnimationComplete(IBinder token) { 1157 sendMessage(H.ENTER_ANIMATION_COMPLETE, token); 1158 } 1159 } 1160 1161 private class H extends Handler { 1162 public static final int LAUNCH_ACTIVITY = 100; 1163 public static final int PAUSE_ACTIVITY = 101; 1164 public static final int PAUSE_ACTIVITY_FINISHING= 102; 1165 public static final int STOP_ACTIVITY_SHOW = 103; 1166 public static final int STOP_ACTIVITY_HIDE = 104; 1167 public static final int SHOW_WINDOW = 105; 1168 public static final int HIDE_WINDOW = 106; 1169 public static final int RESUME_ACTIVITY = 107; 1170 public static final int SEND_RESULT = 108; 1171 public static final int DESTROY_ACTIVITY = 109; 1172 public static final int BIND_APPLICATION = 110; 1173 public static final int EXIT_APPLICATION = 111; 1174 public static final int NEW_INTENT = 112; 1175 public static final int RECEIVER = 113; 1176 public static final int CREATE_SERVICE = 114; 1177 public static final int SERVICE_ARGS = 115; 1178 public static final int STOP_SERVICE = 116; 1179 1180 public static final int CONFIGURATION_CHANGED = 118; 1181 public static final int CLEAN_UP_CONTEXT = 119; 1182 public static final int GC_WHEN_IDLE = 120; 1183 public static final int BIND_SERVICE = 121; 1184 public static final int UNBIND_SERVICE = 122; 1185 public static final int DUMP_SERVICE = 123; 1186 public static final int LOW_MEMORY = 124; 1187 public static final int ACTIVITY_CONFIGURATION_CHANGED = 125; 1188 public static final int RELAUNCH_ACTIVITY = 126; 1189 public static final int PROFILER_CONTROL = 127; 1190 public static final int CREATE_BACKUP_AGENT = 128; 1191 public static final int DESTROY_BACKUP_AGENT = 129; 1192 public static final int SUICIDE = 130; 1193 public static final int REMOVE_PROVIDER = 131; 1194 public static final int ENABLE_JIT = 132; 1195 public static final int DISPATCH_PACKAGE_BROADCAST = 133; 1196 public static final int SCHEDULE_CRASH = 134; 1197 public static final int DUMP_HEAP = 135; 1198 public static final int DUMP_ACTIVITY = 136; 1199 public static final int SLEEPING = 137; 1200 public static final int SET_CORE_SETTINGS = 138; 1201 public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139; 1202 public static final int TRIM_MEMORY = 140; 1203 public static final int DUMP_PROVIDER = 141; 1204 public static final int UNSTABLE_PROVIDER_DIED = 142; 1205 public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143; 1206 public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144; 1207 public static final int INSTALL_PROVIDER = 145; 1208 public static final int ON_NEW_ACTIVITY_OPTIONS = 146; 1209 public static final int CANCEL_VISIBLE_BEHIND = 147; 1210 public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148; 1211 public static final int ENTER_ANIMATION_COMPLETE = 149; 1212 1213 String codeToString(int code) { 1214 if (DEBUG_MESSAGES) { 1215 switch (code) { 1216 case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY"; 1217 case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY"; 1218 case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING"; 1219 case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW"; 1220 case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE"; 1221 case SHOW_WINDOW: return "SHOW_WINDOW"; 1222 case HIDE_WINDOW: return "HIDE_WINDOW"; 1223 case RESUME_ACTIVITY: return "RESUME_ACTIVITY"; 1224 case SEND_RESULT: return "SEND_RESULT"; 1225 case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY"; 1226 case BIND_APPLICATION: return "BIND_APPLICATION"; 1227 case EXIT_APPLICATION: return "EXIT_APPLICATION"; 1228 case NEW_INTENT: return "NEW_INTENT"; 1229 case RECEIVER: return "RECEIVER"; 1230 case CREATE_SERVICE: return "CREATE_SERVICE"; 1231 case SERVICE_ARGS: return "SERVICE_ARGS"; 1232 case STOP_SERVICE: return "STOP_SERVICE"; 1233 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED"; 1234 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT"; 1235 case GC_WHEN_IDLE: return "GC_WHEN_IDLE"; 1236 case BIND_SERVICE: return "BIND_SERVICE"; 1237 case UNBIND_SERVICE: return "UNBIND_SERVICE"; 1238 case DUMP_SERVICE: return "DUMP_SERVICE"; 1239 case LOW_MEMORY: return "LOW_MEMORY"; 1240 case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED"; 1241 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; 1242 case PROFILER_CONTROL: return "PROFILER_CONTROL"; 1243 case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT"; 1244 case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT"; 1245 case SUICIDE: return "SUICIDE"; 1246 case REMOVE_PROVIDER: return "REMOVE_PROVIDER"; 1247 case ENABLE_JIT: return "ENABLE_JIT"; 1248 case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST"; 1249 case SCHEDULE_CRASH: return "SCHEDULE_CRASH"; 1250 case DUMP_HEAP: return "DUMP_HEAP"; 1251 case DUMP_ACTIVITY: return "DUMP_ACTIVITY"; 1252 case SLEEPING: return "SLEEPING"; 1253 case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS"; 1254 case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO"; 1255 case TRIM_MEMORY: return "TRIM_MEMORY"; 1256 case DUMP_PROVIDER: return "DUMP_PROVIDER"; 1257 case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED"; 1258 case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS"; 1259 case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE"; 1260 case INSTALL_PROVIDER: return "INSTALL_PROVIDER"; 1261 case ON_NEW_ACTIVITY_OPTIONS: return "ON_NEW_ACTIVITY_OPTIONS"; 1262 case CANCEL_VISIBLE_BEHIND: return "CANCEL_VISIBLE_BEHIND"; 1263 case BACKGROUND_VISIBLE_BEHIND_CHANGED: return "BACKGROUND_VISIBLE_BEHIND_CHANGED"; 1264 case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE"; 1265 } 1266 } 1267 return Integer.toString(code); 1268 } 1269 public void handleMessage(Message msg) { 1270 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); 1271 switch (msg.what) { 1272 case LAUNCH_ACTIVITY: { 1273 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); 1274 final ActivityClientRecord r = (ActivityClientRecord) msg.obj; 1275 1276 r.packageInfo = getPackageInfoNoCheck( 1277 r.activityInfo.applicationInfo, r.compatInfo); 1278 handleLaunchActivity(r, null); 1279 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1280 } break; 1281 case RELAUNCH_ACTIVITY: { 1282 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart"); 1283 ActivityClientRecord r = (ActivityClientRecord)msg.obj; 1284 handleRelaunchActivity(r); 1285 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1286 } break; 1287 case PAUSE_ACTIVITY: 1288 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); 1289 handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2, 1290 (msg.arg1&2) != 0); 1291 maybeSnapshot(); 1292 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1293 break; 1294 case PAUSE_ACTIVITY_FINISHING: 1295 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); 1296 handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2, 1297 (msg.arg1&1) != 0); 1298 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1299 break; 1300 case STOP_ACTIVITY_SHOW: 1301 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop"); 1302 handleStopActivity((IBinder)msg.obj, true, msg.arg2); 1303 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1304 break; 1305 case STOP_ACTIVITY_HIDE: 1306 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop"); 1307 handleStopActivity((IBinder)msg.obj, false, msg.arg2); 1308 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1309 break; 1310 case SHOW_WINDOW: 1311 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow"); 1312 handleWindowVisibility((IBinder)msg.obj, true); 1313 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1314 break; 1315 case HIDE_WINDOW: 1316 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow"); 1317 handleWindowVisibility((IBinder)msg.obj, false); 1318 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1319 break; 1320 case RESUME_ACTIVITY: 1321 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume"); 1322 handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true); 1323 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1324 break; 1325 case SEND_RESULT: 1326 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult"); 1327 handleSendResult((ResultData)msg.obj); 1328 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1329 break; 1330 case DESTROY_ACTIVITY: 1331 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy"); 1332 handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0, 1333 msg.arg2, false); 1334 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1335 break; 1336 case BIND_APPLICATION: 1337 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); 1338 AppBindData data = (AppBindData)msg.obj; 1339 handleBindApplication(data); 1340 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1341 break; 1342 case EXIT_APPLICATION: 1343 if (mInitialApplication != null) { 1344 mInitialApplication.onTerminate(); 1345 } 1346 Looper.myLooper().quit(); 1347 break; 1348 case NEW_INTENT: 1349 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent"); 1350 handleNewIntent((NewIntentData)msg.obj); 1351 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1352 break; 1353 case RECEIVER: 1354 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp"); 1355 handleReceiver((ReceiverData)msg.obj); 1356 maybeSnapshot(); 1357 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1358 break; 1359 case CREATE_SERVICE: 1360 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate"); 1361 handleCreateService((CreateServiceData)msg.obj); 1362 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1363 break; 1364 case BIND_SERVICE: 1365 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind"); 1366 handleBindService((BindServiceData)msg.obj); 1367 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1368 break; 1369 case UNBIND_SERVICE: 1370 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind"); 1371 handleUnbindService((BindServiceData)msg.obj); 1372 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1373 break; 1374 case SERVICE_ARGS: 1375 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart"); 1376 handleServiceArgs((ServiceArgsData)msg.obj); 1377 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1378 break; 1379 case STOP_SERVICE: 1380 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop"); 1381 handleStopService((IBinder)msg.obj); 1382 maybeSnapshot(); 1383 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1384 break; 1385 case CONFIGURATION_CHANGED: 1386 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged"); 1387 mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi; 1388 handleConfigurationChanged((Configuration)msg.obj, null); 1389 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1390 break; 1391 case CLEAN_UP_CONTEXT: 1392 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj; 1393 cci.context.performFinalCleanup(cci.who, cci.what); 1394 break; 1395 case GC_WHEN_IDLE: 1396 scheduleGcIdler(); 1397 break; 1398 case DUMP_SERVICE: 1399 handleDumpService((DumpComponentInfo)msg.obj); 1400 break; 1401 case LOW_MEMORY: 1402 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory"); 1403 handleLowMemory(); 1404 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1405 break; 1406 case ACTIVITY_CONFIGURATION_CHANGED: 1407 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged"); 1408 handleActivityConfigurationChanged((IBinder)msg.obj); 1409 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1410 break; 1411 case PROFILER_CONTROL: 1412 handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2); 1413 break; 1414 case CREATE_BACKUP_AGENT: 1415 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent"); 1416 handleCreateBackupAgent((CreateBackupAgentData)msg.obj); 1417 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1418 break; 1419 case DESTROY_BACKUP_AGENT: 1420 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent"); 1421 handleDestroyBackupAgent((CreateBackupAgentData)msg.obj); 1422 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1423 break; 1424 case SUICIDE: 1425 Process.killProcess(Process.myPid()); 1426 break; 1427 case REMOVE_PROVIDER: 1428 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove"); 1429 completeRemoveProvider((ProviderRefCount)msg.obj); 1430 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1431 break; 1432 case ENABLE_JIT: 1433 ensureJitEnabled(); 1434 break; 1435 case DISPATCH_PACKAGE_BROADCAST: 1436 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage"); 1437 handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj); 1438 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1439 break; 1440 case SCHEDULE_CRASH: 1441 throw new RemoteServiceException((String)msg.obj); 1442 case DUMP_HEAP: 1443 handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj); 1444 break; 1445 case DUMP_ACTIVITY: 1446 handleDumpActivity((DumpComponentInfo)msg.obj); 1447 break; 1448 case DUMP_PROVIDER: 1449 handleDumpProvider((DumpComponentInfo)msg.obj); 1450 break; 1451 case SLEEPING: 1452 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping"); 1453 handleSleeping((IBinder)msg.obj, msg.arg1 != 0); 1454 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1455 break; 1456 case SET_CORE_SETTINGS: 1457 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings"); 1458 handleSetCoreSettings((Bundle) msg.obj); 1459 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1460 break; 1461 case UPDATE_PACKAGE_COMPATIBILITY_INFO: 1462 handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj); 1463 break; 1464 case TRIM_MEMORY: 1465 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory"); 1466 handleTrimMemory(msg.arg1); 1467 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1468 break; 1469 case UNSTABLE_PROVIDER_DIED: 1470 handleUnstableProviderDied((IBinder)msg.obj, false); 1471 break; 1472 case REQUEST_ASSIST_CONTEXT_EXTRAS: 1473 handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj); 1474 break; 1475 case TRANSLUCENT_CONVERSION_COMPLETE: 1476 handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1); 1477 break; 1478 case INSTALL_PROVIDER: 1479 handleInstallProvider((ProviderInfo) msg.obj); 1480 break; 1481 case ON_NEW_ACTIVITY_OPTIONS: 1482 Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj; 1483 onNewActivityOptions(pair.first, pair.second); 1484 break; 1485 case CANCEL_VISIBLE_BEHIND: 1486 handleCancelVisibleBehind((IBinder) msg.obj); 1487 break; 1488 case BACKGROUND_VISIBLE_BEHIND_CHANGED: 1489 handleOnBackgroundVisibleBehindChanged((IBinder) msg.obj, msg.arg1 > 0); 1490 break; 1491 case ENTER_ANIMATION_COMPLETE: 1492 handleEnterAnimationComplete((IBinder) msg.obj); 1493 break; 1494 } 1495 if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what)); 1496 } 1497 1498 private void maybeSnapshot() { 1499 if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) { 1500 // convert the *private* ActivityThread.PackageInfo to *public* known 1501 // android.content.pm.PackageInfo 1502 String packageName = mBoundApplication.info.mPackageName; 1503 android.content.pm.PackageInfo packageInfo = null; 1504 try { 1505 Context context = getSystemContext(); 1506 if(context == null) { 1507 Log.e(TAG, "cannot get a valid context"); 1508 return; 1509 } 1510 PackageManager pm = context.getPackageManager(); 1511 if(pm == null) { 1512 Log.e(TAG, "cannot get a valid PackageManager"); 1513 return; 1514 } 1515 packageInfo = pm.getPackageInfo( 1516 packageName, PackageManager.GET_ACTIVITIES); 1517 } catch (NameNotFoundException e) { 1518 Log.e(TAG, "cannot get package info for " + packageName, e); 1519 } 1520 SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo); 1521 } 1522 } 1523 } 1524 1525 private class Idler implements MessageQueue.IdleHandler { 1526 @Override 1527 public final boolean queueIdle() { 1528 ActivityClientRecord a = mNewActivities; 1529 boolean stopProfiling = false; 1530 if (mBoundApplication != null && mProfiler.profileFd != null 1531 && mProfiler.autoStopProfiler) { 1532 stopProfiling = true; 1533 } 1534 if (a != null) { 1535 mNewActivities = null; 1536 IActivityManager am = ActivityManagerNative.getDefault(); 1537 ActivityClientRecord prev; 1538 do { 1539 if (localLOGV) Slog.v( 1540 TAG, "Reporting idle of " + a + 1541 " finished=" + 1542 (a.activity != null && a.activity.mFinished)); 1543 if (a.activity != null && !a.activity.mFinished) { 1544 try { 1545 am.activityIdle(a.token, a.createdConfig, stopProfiling); 1546 a.createdConfig = null; 1547 } catch (RemoteException ex) { 1548 // Ignore 1549 } 1550 } 1551 prev = a; 1552 a = a.nextIdle; 1553 prev.nextIdle = null; 1554 } while (a != null); 1555 } 1556 if (stopProfiling) { 1557 mProfiler.stopProfiling(); 1558 } 1559 ensureJitEnabled(); 1560 return false; 1561 } 1562 } 1563 1564 final class GcIdler implements MessageQueue.IdleHandler { 1565 @Override 1566 public final boolean queueIdle() { 1567 doGcIfNeeded(); 1568 return false; 1569 } 1570 } 1571 1572 public static ActivityThread currentActivityThread() { 1573 return sCurrentActivityThread; 1574 } 1575 1576 public static String currentPackageName() { 1577 ActivityThread am = currentActivityThread(); 1578 return (am != null && am.mBoundApplication != null) 1579 ? am.mBoundApplication.appInfo.packageName : null; 1580 } 1581 1582 public static String currentProcessName() { 1583 ActivityThread am = currentActivityThread(); 1584 return (am != null && am.mBoundApplication != null) 1585 ? am.mBoundApplication.processName : null; 1586 } 1587 1588 public static Application currentApplication() { 1589 ActivityThread am = currentActivityThread(); 1590 return am != null ? am.mInitialApplication : null; 1591 } 1592 1593 public static IPackageManager getPackageManager() { 1594 if (sPackageManager != null) { 1595 //Slog.v("PackageManager", "returning cur default = " + sPackageManager); 1596 return sPackageManager; 1597 } 1598 IBinder b = ServiceManager.getService("package"); 1599 //Slog.v("PackageManager", "default service binder = " + b); 1600 sPackageManager = IPackageManager.Stub.asInterface(b); 1601 //Slog.v("PackageManager", "default service = " + sPackageManager); 1602 return sPackageManager; 1603 } 1604 1605 private Configuration mMainThreadConfig = new Configuration(); 1606 Configuration applyConfigCompatMainThread(int displayDensity, Configuration config, 1607 CompatibilityInfo compat) { 1608 if (config == null) { 1609 return null; 1610 } 1611 if (!compat.supportsScreen()) { 1612 mMainThreadConfig.setTo(config); 1613 config = mMainThreadConfig; 1614 compat.applyToConfiguration(displayDensity, config); 1615 } 1616 return config; 1617 } 1618 1619 /** 1620 * Creates the top level resources for the given package. 1621 */ 1622 Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs, 1623 String[] libDirs, int displayId, Configuration overrideConfiguration, 1624 LoadedApk pkgInfo) { 1625 return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs, 1626 displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(), null); 1627 } 1628 1629 final Handler getHandler() { 1630 return mH; 1631 } 1632 1633 public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, 1634 int flags) { 1635 return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId()); 1636 } 1637 1638 public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, 1639 int flags, int userId) { 1640 synchronized (mResourcesManager) { 1641 WeakReference<LoadedApk> ref; 1642 if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) { 1643 ref = mPackages.get(packageName); 1644 } else { 1645 ref = mResourcePackages.get(packageName); 1646 } 1647 LoadedApk packageInfo = ref != null ? ref.get() : null; 1648 //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo); 1649 //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir 1650 // + ": " + packageInfo.mResources.getAssets().isUpToDate()); 1651 if (packageInfo != null && (packageInfo.mResources == null 1652 || packageInfo.mResources.getAssets().isUpToDate())) { 1653 if (packageInfo.isSecurityViolation() 1654 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) { 1655 throw new SecurityException( 1656 "Requesting code from " + packageName 1657 + " to be run in process " 1658 + mBoundApplication.processName 1659 + "/" + mBoundApplication.appInfo.uid); 1660 } 1661 return packageInfo; 1662 } 1663 } 1664 1665 ApplicationInfo ai = null; 1666 try { 1667 ai = getPackageManager().getApplicationInfo(packageName, 1668 PackageManager.GET_SHARED_LIBRARY_FILES, userId); 1669 } catch (RemoteException e) { 1670 // Ignore 1671 } 1672 1673 if (ai != null) { 1674 return getPackageInfo(ai, compatInfo, flags); 1675 } 1676 1677 return null; 1678 } 1679 1680 public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo, 1681 int flags) { 1682 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0; 1683 boolean securityViolation = includeCode && ai.uid != 0 1684 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null 1685 ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid) 1686 : true); 1687 boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0; 1688 if ((flags&(Context.CONTEXT_INCLUDE_CODE 1689 |Context.CONTEXT_IGNORE_SECURITY)) 1690 == Context.CONTEXT_INCLUDE_CODE) { 1691 if (securityViolation) { 1692 String msg = "Requesting code from " + ai.packageName 1693 + " (with uid " + ai.uid + ")"; 1694 if (mBoundApplication != null) { 1695 msg = msg + " to be run in process " 1696 + mBoundApplication.processName + " (with uid " 1697 + mBoundApplication.appInfo.uid + ")"; 1698 } 1699 throw new SecurityException(msg); 1700 } 1701 } 1702 return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode, 1703 registerPackage); 1704 } 1705 1706 public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, 1707 CompatibilityInfo compatInfo) { 1708 return getPackageInfo(ai, compatInfo, null, false, true, false); 1709 } 1710 1711 public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) { 1712 synchronized (mResourcesManager) { 1713 WeakReference<LoadedApk> ref; 1714 if (includeCode) { 1715 ref = mPackages.get(packageName); 1716 } else { 1717 ref = mResourcePackages.get(packageName); 1718 } 1719 return ref != null ? ref.get() : null; 1720 } 1721 } 1722 1723 private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, 1724 ClassLoader baseLoader, boolean securityViolation, boolean includeCode, 1725 boolean registerPackage) { 1726 synchronized (mResourcesManager) { 1727 WeakReference<LoadedApk> ref; 1728 if (includeCode) { 1729 ref = mPackages.get(aInfo.packageName); 1730 } else { 1731 ref = mResourcePackages.get(aInfo.packageName); 1732 } 1733 LoadedApk packageInfo = ref != null ? ref.get() : null; 1734 if (packageInfo == null || (packageInfo.mResources != null 1735 && !packageInfo.mResources.getAssets().isUpToDate())) { 1736 if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package " 1737 : "Loading resource-only package ") + aInfo.packageName 1738 + " (in " + (mBoundApplication != null 1739 ? mBoundApplication.processName : null) 1740 + ")"); 1741 packageInfo = 1742 new LoadedApk(this, aInfo, compatInfo, baseLoader, 1743 securityViolation, includeCode && 1744 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage); 1745 1746 if (mSystemThread && "android".equals(aInfo.packageName)) { 1747 packageInfo.installSystemApplicationInfo(aInfo, 1748 getSystemContext().mPackageInfo.getClassLoader()); 1749 } 1750 1751 if (includeCode) { 1752 mPackages.put(aInfo.packageName, 1753 new WeakReference<LoadedApk>(packageInfo)); 1754 } else { 1755 mResourcePackages.put(aInfo.packageName, 1756 new WeakReference<LoadedApk>(packageInfo)); 1757 } 1758 } 1759 return packageInfo; 1760 } 1761 } 1762 1763 ActivityThread() { 1764 mResourcesManager = ResourcesManager.getInstance(); 1765 } 1766 1767 public ApplicationThread getApplicationThread() 1768 { 1769 return mAppThread; 1770 } 1771 1772 public Instrumentation getInstrumentation() 1773 { 1774 return mInstrumentation; 1775 } 1776 1777 public boolean isProfiling() { 1778 return mProfiler != null && mProfiler.profileFile != null 1779 && mProfiler.profileFd == null; 1780 } 1781 1782 public String getProfileFilePath() { 1783 return mProfiler.profileFile; 1784 } 1785 1786 public Looper getLooper() { 1787 return mLooper; 1788 } 1789 1790 public Application getApplication() { 1791 return mInitialApplication; 1792 } 1793 1794 public String getProcessName() { 1795 return mBoundApplication.processName; 1796 } 1797 1798 public ContextImpl getSystemContext() { 1799 synchronized (this) { 1800 if (mSystemContext == null) { 1801 mSystemContext = ContextImpl.createSystemContext(this); 1802 } 1803 return mSystemContext; 1804 } 1805 } 1806 1807 public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { 1808 synchronized (this) { 1809 getSystemContext().installSystemApplicationInfo(info, classLoader); 1810 1811 // give ourselves a default profiler 1812 mProfiler = new Profiler(); 1813 } 1814 } 1815 1816 void ensureJitEnabled() { 1817 if (!mJitEnabled) { 1818 mJitEnabled = true; 1819 dalvik.system.VMRuntime.getRuntime().startJitCompilation(); 1820 } 1821 } 1822 1823 void scheduleGcIdler() { 1824 if (!mGcIdlerScheduled) { 1825 mGcIdlerScheduled = true; 1826 Looper.myQueue().addIdleHandler(mGcIdler); 1827 } 1828 mH.removeMessages(H.GC_WHEN_IDLE); 1829 } 1830 1831 void unscheduleGcIdler() { 1832 if (mGcIdlerScheduled) { 1833 mGcIdlerScheduled = false; 1834 Looper.myQueue().removeIdleHandler(mGcIdler); 1835 } 1836 mH.removeMessages(H.GC_WHEN_IDLE); 1837 } 1838 1839 void doGcIfNeeded() { 1840 mGcIdlerScheduled = false; 1841 final long now = SystemClock.uptimeMillis(); 1842 //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime() 1843 // + "m now=" + now); 1844 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) { 1845 //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!"); 1846 BinderInternal.forceGc("bg"); 1847 } 1848 } 1849 1850 private static final String HEAP_FULL_COLUMN 1851 = "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s"; 1852 private static final String HEAP_COLUMN 1853 = "%13s %8s %8s %8s %8s %8s %8s %8s"; 1854 1855 // Formatting for checkin service - update version if row format changes 1856 private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 3; 1857 1858 static void printRow(PrintWriter pw, String format, Object...objs) { 1859 pw.println(String.format(format, objs)); 1860 } 1861 1862 public static void dumpMemInfoTable(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin, 1863 boolean dumpFullInfo, boolean dumpDalvik, int pid, String processName, 1864 long nativeMax, long nativeAllocated, long nativeFree, 1865 long dalvikMax, long dalvikAllocated, long dalvikFree) { 1866 1867 // For checkin, we print one long comma-separated list of values 1868 if (checkin) { 1869 // NOTE: if you change anything significant below, also consider changing 1870 // ACTIVITY_THREAD_CHECKIN_VERSION. 1871 1872 // Header 1873 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(','); 1874 pw.print(pid); pw.print(','); 1875 pw.print(processName); pw.print(','); 1876 1877 // Heap info - max 1878 pw.print(nativeMax); pw.print(','); 1879 pw.print(dalvikMax); pw.print(','); 1880 pw.print("N/A,"); 1881 pw.print(nativeMax + dalvikMax); pw.print(','); 1882 1883 // Heap info - allocated 1884 pw.print(nativeAllocated); pw.print(','); 1885 pw.print(dalvikAllocated); pw.print(','); 1886 pw.print("N/A,"); 1887 pw.print(nativeAllocated + dalvikAllocated); pw.print(','); 1888 1889 // Heap info - free 1890 pw.print(nativeFree); pw.print(','); 1891 pw.print(dalvikFree); pw.print(','); 1892 pw.print("N/A,"); 1893 pw.print(nativeFree + dalvikFree); pw.print(','); 1894 1895 // Heap info - proportional set size 1896 pw.print(memInfo.nativePss); pw.print(','); 1897 pw.print(memInfo.dalvikPss); pw.print(','); 1898 pw.print(memInfo.otherPss); pw.print(','); 1899 pw.print(memInfo.getTotalPss()); pw.print(','); 1900 1901 // Heap info - swappable set size 1902 pw.print(memInfo.nativeSwappablePss); pw.print(','); 1903 pw.print(memInfo.dalvikSwappablePss); pw.print(','); 1904 pw.print(memInfo.otherSwappablePss); pw.print(','); 1905 pw.print(memInfo.getTotalSwappablePss()); pw.print(','); 1906 1907 // Heap info - shared dirty 1908 pw.print(memInfo.nativeSharedDirty); pw.print(','); 1909 pw.print(memInfo.dalvikSharedDirty); pw.print(','); 1910 pw.print(memInfo.otherSharedDirty); pw.print(','); 1911 pw.print(memInfo.getTotalSharedDirty()); pw.print(','); 1912 1913 // Heap info - shared clean 1914 pw.print(memInfo.nativeSharedClean); pw.print(','); 1915 pw.print(memInfo.dalvikSharedClean); pw.print(','); 1916 pw.print(memInfo.otherSharedClean); pw.print(','); 1917 pw.print(memInfo.getTotalSharedClean()); pw.print(','); 1918 1919 // Heap info - private Dirty 1920 pw.print(memInfo.nativePrivateDirty); pw.print(','); 1921 pw.print(memInfo.dalvikPrivateDirty); pw.print(','); 1922 pw.print(memInfo.otherPrivateDirty); pw.print(','); 1923 pw.print(memInfo.getTotalPrivateDirty()); pw.print(','); 1924 1925 // Heap info - private Clean 1926 pw.print(memInfo.nativePrivateClean); pw.print(','); 1927 pw.print(memInfo.dalvikPrivateClean); pw.print(','); 1928 pw.print(memInfo.otherPrivateClean); pw.print(','); 1929 pw.print(memInfo.getTotalPrivateClean()); pw.print(','); 1930 1931 // Heap info - other areas 1932 for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) { 1933 pw.print(Debug.MemoryInfo.getOtherLabel(i)); pw.print(','); 1934 pw.print(memInfo.getOtherPss(i)); pw.print(','); 1935 pw.print(memInfo.getOtherSwappablePss(i)); pw.print(','); 1936 pw.print(memInfo.getOtherSharedDirty(i)); pw.print(','); 1937 pw.print(memInfo.getOtherSharedClean(i)); pw.print(','); 1938 pw.print(memInfo.getOtherPrivateDirty(i)); pw.print(','); 1939 pw.print(memInfo.getOtherPrivateClean(i)); pw.print(','); 1940 } 1941 return; 1942 } 1943 1944 // otherwise, show human-readable format 1945 if (dumpFullInfo) { 1946 printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private", 1947 "Shared", "Private", "Swapped", "Heap", "Heap", "Heap"); 1948 printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "", 1949 "Clean", "Clean", "Dirty", "Size", "Alloc", "Free"); 1950 printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------", 1951 "------", "------", "------", "------", "------", "------"); 1952 printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss, 1953 memInfo.nativeSwappablePss, memInfo.nativeSharedDirty, 1954 memInfo.nativePrivateDirty, memInfo.nativeSharedClean, 1955 memInfo.nativePrivateClean, memInfo.nativeSwappedOut, 1956 nativeMax, nativeAllocated, nativeFree); 1957 printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss, 1958 memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty, 1959 memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean, 1960 memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut, 1961 dalvikMax, dalvikAllocated, dalvikFree); 1962 } else { 1963 printRow(pw, HEAP_COLUMN, "", "Pss", "Private", 1964 "Private", "Swapped", "Heap", "Heap", "Heap"); 1965 printRow(pw, HEAP_COLUMN, "", "Total", "Dirty", 1966 "Clean", "Dirty", "Size", "Alloc", "Free"); 1967 printRow(pw, HEAP_COLUMN, "", "------", "------", "------", 1968 "------", "------", "------", "------", "------"); 1969 printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss, 1970 memInfo.nativePrivateDirty, 1971 memInfo.nativePrivateClean, memInfo.nativeSwappedOut, 1972 nativeMax, nativeAllocated, nativeFree); 1973 printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss, 1974 memInfo.dalvikPrivateDirty, 1975 memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut, 1976 dalvikMax, dalvikAllocated, dalvikFree); 1977 } 1978 1979 int otherPss = memInfo.otherPss; 1980 int otherSwappablePss = memInfo.otherSwappablePss; 1981 int otherSharedDirty = memInfo.otherSharedDirty; 1982 int otherPrivateDirty = memInfo.otherPrivateDirty; 1983 int otherSharedClean = memInfo.otherSharedClean; 1984 int otherPrivateClean = memInfo.otherPrivateClean; 1985 int otherSwappedOut = memInfo.otherSwappedOut; 1986 1987 for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) { 1988 final int myPss = memInfo.getOtherPss(i); 1989 final int mySwappablePss = memInfo.getOtherSwappablePss(i); 1990 final int mySharedDirty = memInfo.getOtherSharedDirty(i); 1991 final int myPrivateDirty = memInfo.getOtherPrivateDirty(i); 1992 final int mySharedClean = memInfo.getOtherSharedClean(i); 1993 final int myPrivateClean = memInfo.getOtherPrivateClean(i); 1994 final int mySwappedOut = memInfo.getOtherSwappedOut(i); 1995 if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0 1996 || mySharedClean != 0 || myPrivateClean != 0 || mySwappedOut != 0) { 1997 if (dumpFullInfo) { 1998 printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i), 1999 myPss, mySwappablePss, mySharedDirty, myPrivateDirty, 2000 mySharedClean, myPrivateClean, mySwappedOut, "", "", ""); 2001 } else { 2002 printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i), 2003 myPss, myPrivateDirty, 2004 myPrivateClean, mySwappedOut, "", "", ""); 2005 } 2006 otherPss -= myPss; 2007 otherSwappablePss -= mySwappablePss; 2008 otherSharedDirty -= mySharedDirty; 2009 otherPrivateDirty -= myPrivateDirty; 2010 otherSharedClean -= mySharedClean; 2011 otherPrivateClean -= myPrivateClean; 2012 otherSwappedOut -= mySwappedOut; 2013 } 2014 } 2015 2016 if (dumpFullInfo) { 2017 printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss, 2018 otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean, 2019 otherSwappedOut, "", "", ""); 2020 printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(), 2021 memInfo.getTotalSwappablePss(), 2022 memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(), 2023 memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(), 2024 memInfo.getTotalSwappedOut(), nativeMax+dalvikMax, 2025 nativeAllocated+dalvikAllocated, nativeFree+dalvikFree); 2026 } else { 2027 printRow(pw, HEAP_COLUMN, "Unknown", otherPss, 2028 otherPrivateDirty, otherPrivateClean, otherSwappedOut, 2029 "", "", ""); 2030 printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(), 2031 memInfo.getTotalPrivateDirty(), 2032 memInfo.getTotalPrivateClean(), 2033 memInfo.getTotalSwappedOut(), 2034 nativeMax+dalvikMax, 2035 nativeAllocated+dalvikAllocated, nativeFree+dalvikFree); 2036 } 2037 2038 if (dumpDalvik) { 2039 pw.println(" "); 2040 pw.println(" Dalvik Details"); 2041 2042 for (int i=Debug.MemoryInfo.NUM_OTHER_STATS; 2043 i<Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS; i++) { 2044 final int myPss = memInfo.getOtherPss(i); 2045 final int mySwappablePss = memInfo.getOtherSwappablePss(i); 2046 final int mySharedDirty = memInfo.getOtherSharedDirty(i); 2047 final int myPrivateDirty = memInfo.getOtherPrivateDirty(i); 2048 final int mySharedClean = memInfo.getOtherSharedClean(i); 2049 final int myPrivateClean = memInfo.getOtherPrivateClean(i); 2050 final int mySwappedOut = memInfo.getOtherSwappedOut(i); 2051 if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0 2052 || mySharedClean != 0 || myPrivateClean != 0) { 2053 if (dumpFullInfo) { 2054 printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i), 2055 myPss, mySwappablePss, mySharedDirty, myPrivateDirty, 2056 mySharedClean, myPrivateClean, mySwappedOut, "", "", ""); 2057 } else { 2058 printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i), 2059 myPss, myPrivateDirty, 2060 myPrivateClean, mySwappedOut, "", "", ""); 2061 } 2062 } 2063 } 2064 } 2065 } 2066 2067 public void registerOnActivityPausedListener(Activity activity, 2068 OnActivityPausedListener listener) { 2069 synchronized (mOnPauseListeners) { 2070 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); 2071 if (list == null) { 2072 list = new ArrayList<OnActivityPausedListener>(); 2073 mOnPauseListeners.put(activity, list); 2074 } 2075 list.add(listener); 2076 } 2077 } 2078 2079 public void unregisterOnActivityPausedListener(Activity activity, 2080 OnActivityPausedListener listener) { 2081 synchronized (mOnPauseListeners) { 2082 ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); 2083 if (list != null) { 2084 list.remove(listener); 2085 } 2086 } 2087 } 2088 2089 public final ActivityInfo resolveActivityInfo(Intent intent) { 2090 ActivityInfo aInfo = intent.resolveActivityInfo( 2091 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES); 2092 if (aInfo == null) { 2093 // Throw an exception. 2094 Instrumentation.checkStartActivityResult( 2095 ActivityManager.START_CLASS_NOT_FOUND, intent); 2096 } 2097 return aInfo; 2098 } 2099 2100 public final Activity startActivityNow(Activity parent, String id, 2101 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state, 2102 Activity.NonConfigurationInstances lastNonConfigurationInstances) { 2103 ActivityClientRecord r = new ActivityClientRecord(); 2104 r.token = token; 2105 r.ident = 0; 2106 r.intent = intent; 2107 r.state = state; 2108 r.parent = parent; 2109 r.embeddedID = id; 2110 r.activityInfo = activityInfo; 2111 r.lastNonConfigurationInstances = lastNonConfigurationInstances; 2112 if (localLOGV) { 2113 ComponentName compname = intent.getComponent(); 2114 String name; 2115 if (compname != null) { 2116 name = compname.toShortString(); 2117 } else { 2118 name = "(Intent " + intent + ").getComponent() returned null"; 2119 } 2120 Slog.v(TAG, "Performing launch: action=" + intent.getAction() 2121 + ", comp=" + name 2122 + ", token=" + token); 2123 } 2124 return performLaunchActivity(r, null); 2125 } 2126 2127 public final Activity getActivity(IBinder token) { 2128 return mActivities.get(token).activity; 2129 } 2130 2131 public final void sendActivityResult( 2132 IBinder token, String id, int requestCode, 2133 int resultCode, Intent data) { 2134 if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id 2135 + " req=" + requestCode + " res=" + resultCode + " data=" + data); 2136 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 2137 list.add(new ResultInfo(id, requestCode, resultCode, data)); 2138 mAppThread.scheduleSendResult(token, list); 2139 } 2140 2141 private void sendMessage(int what, Object obj) { 2142 sendMessage(what, obj, 0, 0, false); 2143 } 2144 2145 private void sendMessage(int what, Object obj, int arg1) { 2146 sendMessage(what, obj, arg1, 0, false); 2147 } 2148 2149 private void sendMessage(int what, Object obj, int arg1, int arg2) { 2150 sendMessage(what, obj, arg1, arg2, false); 2151 } 2152 2153 private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { 2154 if (DEBUG_MESSAGES) Slog.v( 2155 TAG, "SCHEDULE " + what + " " + mH.codeToString(what) 2156 + ": " + arg1 + " / " + obj); 2157 Message msg = Message.obtain(); 2158 msg.what = what; 2159 msg.obj = obj; 2160 msg.arg1 = arg1; 2161 msg.arg2 = arg2; 2162 if (async) { 2163 msg.setAsynchronous(true); 2164 } 2165 mH.sendMessage(msg); 2166 } 2167 2168 final void scheduleContextCleanup(ContextImpl context, String who, 2169 String what) { 2170 ContextCleanupInfo cci = new ContextCleanupInfo(); 2171 cci.context = context; 2172 cci.who = who; 2173 cci.what = what; 2174 sendMessage(H.CLEAN_UP_CONTEXT, cci); 2175 } 2176 2177 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { 2178 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); 2179 2180 ActivityInfo aInfo = r.activityInfo; 2181 if (r.packageInfo == null) { 2182 r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, 2183 Context.CONTEXT_INCLUDE_CODE); 2184 } 2185 2186 ComponentName component = r.intent.getComponent(); 2187 if (component == null) { 2188 component = r.intent.resolveActivity( 2189 mInitialApplication.getPackageManager()); 2190 r.intent.setComponent(component); 2191 } 2192 2193 if (r.activityInfo.targetActivity != null) { 2194 component = new ComponentName(r.activityInfo.packageName, 2195 r.activityInfo.targetActivity); 2196 } 2197 2198 Activity activity = null; 2199 try { 2200 java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); 2201 activity = mInstrumentation.newActivity( 2202 cl, component.getClassName(), r.intent); 2203 StrictMode.incrementExpectedActivityCount(activity.getClass()); 2204 r.intent.setExtrasClassLoader(cl); 2205 r.intent.prepareToEnterProcess(); 2206 if (r.state != null) { 2207 r.state.setClassLoader(cl); 2208 } 2209 } catch (Exception e) { 2210 if (!mInstrumentation.onException(activity, e)) { 2211 throw new RuntimeException( 2212 "Unable to instantiate activity " + component 2213 + ": " + e.toString(), e); 2214 } 2215 } 2216 2217 try { 2218 Application app = r.packageInfo.makeApplication(false, mInstrumentation); 2219 2220 if (localLOGV) Slog.v(TAG, "Performing launch of " + r); 2221 if (localLOGV) Slog.v( 2222 TAG, r + ": app=" + app 2223 + ", appName=" + app.getPackageName() 2224 + ", pkg=" + r.packageInfo.getPackageName() 2225 + ", comp=" + r.intent.getComponent().toShortString() 2226 + ", dir=" + r.packageInfo.getAppDir()); 2227 2228 if (activity != null) { 2229 Context appContext = createBaseContextForActivity(r, activity); 2230 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); 2231 Configuration config = new Configuration(mCompatConfiguration); 2232 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " 2233 + r.activityInfo.name + " with config " + config); 2234 activity.attach(appContext, this, getInstrumentation(), r.token, 2235 r.ident, app, r.intent, r.activityInfo, title, r.parent, 2236 r.embeddedID, r.lastNonConfigurationInstances, config, 2237 r.voiceInteractor); 2238 2239 if (customIntent != null) { 2240 activity.mIntent = customIntent; 2241 } 2242 r.lastNonConfigurationInstances = null; 2243 activity.mStartedActivity = false; 2244 int theme = r.activityInfo.getThemeResource(); 2245 if (theme != 0) { 2246 activity.setTheme(theme); 2247 } 2248 2249 activity.mCalled = false; 2250 if (r.isPersistable()) { 2251 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); 2252 } else { 2253 mInstrumentation.callActivityOnCreate(activity, r.state); 2254 } 2255 if (!activity.mCalled) { 2256 throw new SuperNotCalledException( 2257 "Activity " + r.intent.getComponent().toShortString() + 2258 " did not call through to super.onCreate()"); 2259 } 2260 r.activity = activity; 2261 r.stopped = true; 2262 if (!r.activity.mFinished) { 2263 activity.performStart(); 2264 r.stopped = false; 2265 } 2266 if (!r.activity.mFinished) { 2267 if (r.isPersistable()) { 2268 if (r.state != null || r.persistentState != null) { 2269 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, 2270 r.persistentState); 2271 } 2272 } else if (r.state != null) { 2273 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); 2274 } 2275 } 2276 if (!r.activity.mFinished) { 2277 activity.mCalled = false; 2278 if (r.isPersistable()) { 2279 mInstrumentation.callActivityOnPostCreate(activity, r.state, 2280 r.persistentState); 2281 } else { 2282 mInstrumentation.callActivityOnPostCreate(activity, r.state); 2283 } 2284 if (!activity.mCalled) { 2285 throw new SuperNotCalledException( 2286 "Activity " + r.intent.getComponent().toShortString() + 2287 " did not call through to super.onPostCreate()"); 2288 } 2289 } 2290 } 2291 r.paused = true; 2292 2293 mActivities.put(r.token, r); 2294 2295 } catch (SuperNotCalledException e) { 2296 throw e; 2297 2298 } catch (Exception e) { 2299 if (!mInstrumentation.onException(activity, e)) { 2300 throw new RuntimeException( 2301 "Unable to start activity " + component 2302 + ": " + e.toString(), e); 2303 } 2304 } 2305 2306 return activity; 2307 } 2308 2309 private Context createBaseContextForActivity(ActivityClientRecord r, 2310 final Activity activity) { 2311 ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token); 2312 appContext.setOuterContext(activity); 2313 Context baseContext = appContext; 2314 2315 final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); 2316 try { 2317 IActivityContainer container = 2318 ActivityManagerNative.getDefault().getEnclosingActivityContainer(r.token); 2319 final int displayId = 2320 container == null ? Display.DEFAULT_DISPLAY : container.getDisplayId(); 2321 if (displayId > Display.DEFAULT_DISPLAY) { 2322 Display display = dm.getRealDisplay(displayId, r.token); 2323 baseContext = appContext.createDisplayContext(display); 2324 } 2325 } catch (RemoteException e) { 2326 } 2327 2328 // For debugging purposes, if the activity's package name contains the value of 2329 // the "debug.use-second-display" system property as a substring, then show 2330 // its content on a secondary display if there is one. 2331 String pkgName = SystemProperties.get("debug.second-display.pkg"); 2332 if (pkgName != null && !pkgName.isEmpty() 2333 && r.packageInfo.mPackageName.contains(pkgName)) { 2334 for (int displayId : dm.getDisplayIds()) { 2335 if (displayId != Display.DEFAULT_DISPLAY) { 2336 Display display = dm.getRealDisplay(displayId, r.token); 2337 baseContext = appContext.createDisplayContext(display); 2338 break; 2339 } 2340 } 2341 } 2342 return baseContext; 2343 } 2344 2345 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { 2346 // If we are getting ready to gc after going to the background, well 2347 // we are back active so skip it. 2348 unscheduleGcIdler(); 2349 mSomeActivitiesChanged = true; 2350 2351 if (r.profilerInfo != null) { 2352 mProfiler.setProfiler(r.profilerInfo); 2353 mProfiler.startProfiling(); 2354 } 2355 2356 // Make sure we are running with the most recent config. 2357 handleConfigurationChanged(null, null); 2358 2359 if (localLOGV) Slog.v( 2360 TAG, "Handling launch of " + r); 2361 2362 Activity a = performLaunchActivity(r, customIntent); 2363 2364 if (a != null) { 2365 r.createdConfig = new Configuration(mConfiguration); 2366 Bundle oldState = r.state; 2367 handleResumeActivity(r.token, false, r.isForward, 2368 !r.activity.mFinished && !r.startsNotResumed); 2369 2370 if (!r.activity.mFinished && r.startsNotResumed) { 2371 // The activity manager actually wants this one to start out 2372 // paused, because it needs to be visible but isn't in the 2373 // foreground. We accomplish this by going through the 2374 // normal startup (because activities expect to go through 2375 // onResume() the first time they run, before their window 2376 // is displayed), and then pausing it. However, in this case 2377 // we do -not- need to do the full pause cycle (of freezing 2378 // and such) because the activity manager assumes it can just 2379 // retain the current state it has. 2380 try { 2381 r.activity.mCalled = false; 2382 mInstrumentation.callActivityOnPause(r.activity); 2383 // We need to keep around the original state, in case 2384 // we need to be created again. But we only do this 2385 // for pre-Honeycomb apps, which always save their state 2386 // when pausing, so we can not have them save their state 2387 // when restarting from a paused state. For HC and later, 2388 // we want to (and can) let the state be saved as the normal 2389 // part of stopping the activity. 2390 if (r.isPreHoneycomb()) { 2391 r.state = oldState; 2392 } 2393 if (!r.activity.mCalled) { 2394 throw new SuperNotCalledException( 2395 "Activity " + r.intent.getComponent().toShortString() + 2396 " did not call through to super.onPause()"); 2397 } 2398 2399 } catch (SuperNotCalledException e) { 2400 throw e; 2401 2402 } catch (Exception e) { 2403 if (!mInstrumentation.onException(r.activity, e)) { 2404 throw new RuntimeException( 2405 "Unable to pause activity " 2406 + r.intent.getComponent().toShortString() 2407 + ": " + e.toString(), e); 2408 } 2409 } 2410 r.paused = true; 2411 } 2412 } else { 2413 // If there was an error, for any reason, tell the activity 2414 // manager to stop us. 2415 try { 2416 ActivityManagerNative.getDefault() 2417 .finishActivity(r.token, Activity.RESULT_CANCELED, null, false); 2418 } catch (RemoteException ex) { 2419 // Ignore 2420 } 2421 } 2422 } 2423 2424 private void deliverNewIntents(ActivityClientRecord r, 2425 List<Intent> intents) { 2426 final int N = intents.size(); 2427 for (int i=0; i<N; i++) { 2428 Intent intent = intents.get(i); 2429 intent.setExtrasClassLoader(r.activity.getClassLoader()); 2430 intent.prepareToEnterProcess(); 2431 r.activity.mFragments.noteStateNotSaved(); 2432 mInstrumentation.callActivityOnNewIntent(r.activity, intent); 2433 } 2434 } 2435 2436 public final void performNewIntents(IBinder token, 2437 List<Intent> intents) { 2438 ActivityClientRecord r = mActivities.get(token); 2439 if (r != null) { 2440 final boolean resumed = !r.paused; 2441 if (resumed) { 2442 r.activity.mTemporaryPause = true; 2443 mInstrumentation.callActivityOnPause(r.activity); 2444 } 2445 deliverNewIntents(r, intents); 2446 if (resumed) { 2447 r.activity.performResume(); 2448 r.activity.mTemporaryPause = false; 2449 } 2450 } 2451 } 2452 2453 private void handleNewIntent(NewIntentData data) { 2454 performNewIntents(data.token, data.intents); 2455 } 2456 2457 public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) { 2458 Bundle data = new Bundle(); 2459 ActivityClientRecord r = mActivities.get(cmd.activityToken); 2460 if (r != null) { 2461 r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data); 2462 r.activity.onProvideAssistData(data); 2463 } 2464 if (data.isEmpty()) { 2465 data = null; 2466 } 2467 IActivityManager mgr = ActivityManagerNative.getDefault(); 2468 try { 2469 mgr.reportAssistContextExtras(cmd.requestToken, data); 2470 } catch (RemoteException e) { 2471 } 2472 } 2473 2474 public void handleTranslucentConversionComplete(IBinder token, boolean drawComplete) { 2475 ActivityClientRecord r = mActivities.get(token); 2476 if (r != null) { 2477 r.activity.onTranslucentConversionComplete(drawComplete); 2478 } 2479 } 2480 2481 public void onNewActivityOptions(IBinder token, ActivityOptions options) { 2482 ActivityClientRecord r = mActivities.get(token); 2483 if (r != null) { 2484 r.activity.onNewActivityOptions(options); 2485 } 2486 } 2487 2488 public void handleCancelVisibleBehind(IBinder token) { 2489 ActivityClientRecord r = mActivities.get(token); 2490 if (r != null) { 2491 mSomeActivitiesChanged = true; 2492 final Activity activity = r.activity; 2493 if (activity.mVisibleBehind) { 2494 activity.mCalled = false; 2495 activity.onVisibleBehindCanceled(); 2496 // Tick, tick, tick. The activity has 500 msec to return or it will be destroyed. 2497 if (!activity.mCalled) { 2498 throw new SuperNotCalledException("Activity " + activity.getLocalClassName() + 2499 " did not call through to super.onVisibleBehindCanceled()"); 2500 } 2501 activity.mVisibleBehind = false; 2502 } 2503 } 2504 try { 2505 ActivityManagerNative.getDefault().backgroundResourcesReleased(token); 2506 } catch (RemoteException e) { 2507 } 2508 } 2509 2510 public void handleOnBackgroundVisibleBehindChanged(IBinder token, boolean visible) { 2511 ActivityClientRecord r = mActivities.get(token); 2512 if (r != null) { 2513 r.activity.onBackgroundVisibleBehindChanged(visible); 2514 } 2515 } 2516 2517 public void handleInstallProvider(ProviderInfo info) { 2518 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 2519 try { 2520 installContentProviders(mInitialApplication, Lists.newArrayList(info)); 2521 } finally { 2522 StrictMode.setThreadPolicy(oldPolicy); 2523 } 2524 } 2525 2526 private void handleEnterAnimationComplete(IBinder token) { 2527 ActivityClientRecord r = mActivities.get(token); 2528 if (r != null) { 2529 r.activity.onEnterAnimationComplete(); 2530 } 2531 } 2532 2533 private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>(); 2534 2535 /** 2536 * Return the Intent that's currently being handled by a 2537 * BroadcastReceiver on this thread, or null if none. 2538 * @hide 2539 */ 2540 public static Intent getIntentBeingBroadcast() { 2541 return sCurrentBroadcastIntent.get(); 2542 } 2543 2544 private void handleReceiver(ReceiverData data) { 2545 // If we are getting ready to gc after going to the background, well 2546 // we are back active so skip it. 2547 unscheduleGcIdler(); 2548 2549 String component = data.intent.getComponent().getClassName(); 2550 2551 LoadedApk packageInfo = getPackageInfoNoCheck( 2552 data.info.applicationInfo, data.compatInfo); 2553 2554 IActivityManager mgr = ActivityManagerNative.getDefault(); 2555 2556 BroadcastReceiver receiver; 2557 try { 2558 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2559 data.intent.setExtrasClassLoader(cl); 2560 data.intent.prepareToEnterProcess(); 2561 data.setExtrasClassLoader(cl); 2562 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); 2563 } catch (Exception e) { 2564 if (DEBUG_BROADCAST) Slog.i(TAG, 2565 "Finishing failed broadcast to " + data.intent.getComponent()); 2566 data.sendFinished(mgr); 2567 throw new RuntimeException( 2568 "Unable to instantiate receiver " + component 2569 + ": " + e.toString(), e); 2570 } 2571 2572 try { 2573 Application app = packageInfo.makeApplication(false, mInstrumentation); 2574 2575 if (localLOGV) Slog.v( 2576 TAG, "Performing receive of " + data.intent 2577 + ": app=" + app 2578 + ", appName=" + app.getPackageName() 2579 + ", pkg=" + packageInfo.getPackageName() 2580 + ", comp=" + data.intent.getComponent().toShortString() 2581 + ", dir=" + packageInfo.getAppDir()); 2582 2583 ContextImpl context = (ContextImpl)app.getBaseContext(); 2584 sCurrentBroadcastIntent.set(data.intent); 2585 receiver.setPendingResult(data); 2586 receiver.onReceive(context.getReceiverRestrictedContext(), 2587 data.intent); 2588 } catch (Exception e) { 2589 if (DEBUG_BROADCAST) Slog.i(TAG, 2590 "Finishing failed broadcast to " + data.intent.getComponent()); 2591 data.sendFinished(mgr); 2592 if (!mInstrumentation.onException(receiver, e)) { 2593 throw new RuntimeException( 2594 "Unable to start receiver " + component 2595 + ": " + e.toString(), e); 2596 } 2597 } finally { 2598 sCurrentBroadcastIntent.set(null); 2599 } 2600 2601 if (receiver.getPendingResult() != null) { 2602 data.finish(); 2603 } 2604 } 2605 2606 // Instantiate a BackupAgent and tell it that it's alive 2607 private void handleCreateBackupAgent(CreateBackupAgentData data) { 2608 if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data); 2609 2610 // Sanity check the requested target package's uid against ours 2611 try { 2612 PackageInfo requestedPackage = getPackageManager().getPackageInfo( 2613 data.appInfo.packageName, 0, UserHandle.myUserId()); 2614 if (requestedPackage.applicationInfo.uid != Process.myUid()) { 2615 Slog.w(TAG, "Asked to instantiate non-matching package " 2616 + data.appInfo.packageName); 2617 return; 2618 } 2619 } catch (RemoteException e) { 2620 Slog.e(TAG, "Can't reach package manager", e); 2621 return; 2622 } 2623 2624 // no longer idle; we have backup work to do 2625 unscheduleGcIdler(); 2626 2627 // instantiate the BackupAgent class named in the manifest 2628 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 2629 String packageName = packageInfo.mPackageName; 2630 if (packageName == null) { 2631 Slog.d(TAG, "Asked to create backup agent for nonexistent package"); 2632 return; 2633 } 2634 2635 String classname = data.appInfo.backupAgentName; 2636 // full backup operation but no app-supplied agent? use the default implementation 2637 if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL 2638 || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) { 2639 classname = "android.app.backup.FullBackupAgent"; 2640 } 2641 2642 try { 2643 IBinder binder = null; 2644 BackupAgent agent = mBackupAgents.get(packageName); 2645 if (agent != null) { 2646 // reusing the existing instance 2647 if (DEBUG_BACKUP) { 2648 Slog.v(TAG, "Reusing existing agent instance"); 2649 } 2650 binder = agent.onBind(); 2651 } else { 2652 try { 2653 if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname); 2654 2655 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2656 agent = (BackupAgent) cl.loadClass(classname).newInstance(); 2657 2658 // set up the agent's context 2659 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); 2660 context.setOuterContext(agent); 2661 agent.attach(context); 2662 2663 agent.onCreate(); 2664 binder = agent.onBind(); 2665 mBackupAgents.put(packageName, agent); 2666 } catch (Exception e) { 2667 // If this is during restore, fail silently; otherwise go 2668 // ahead and let the user see the crash. 2669 Slog.e(TAG, "Agent threw during creation: " + e); 2670 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE 2671 && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) { 2672 throw e; 2673 } 2674 // falling through with 'binder' still null 2675 } 2676 } 2677 2678 // tell the OS that we're live now 2679 try { 2680 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder); 2681 } catch (RemoteException e) { 2682 // nothing to do. 2683 } 2684 } catch (Exception e) { 2685 throw new RuntimeException("Unable to create BackupAgent " 2686 + classname + ": " + e.toString(), e); 2687 } 2688 } 2689 2690 // Tear down a BackupAgent 2691 private void handleDestroyBackupAgent(CreateBackupAgentData data) { 2692 if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data); 2693 2694 LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 2695 String packageName = packageInfo.mPackageName; 2696 BackupAgent agent = mBackupAgents.get(packageName); 2697 if (agent != null) { 2698 try { 2699 agent.onDestroy(); 2700 } catch (Exception e) { 2701 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo); 2702 e.printStackTrace(); 2703 } 2704 mBackupAgents.remove(packageName); 2705 } else { 2706 Slog.w(TAG, "Attempt to destroy unknown backup agent " + data); 2707 } 2708 } 2709 2710 private void handleCreateService(CreateServiceData data) { 2711 // If we are getting ready to gc after going to the background, well 2712 // we are back active so skip it. 2713 unscheduleGcIdler(); 2714 2715 LoadedApk packageInfo = getPackageInfoNoCheck( 2716 data.info.applicationInfo, data.compatInfo); 2717 Service service = null; 2718 try { 2719 java.lang.ClassLoader cl = packageInfo.getClassLoader(); 2720 service = (Service) cl.loadClass(data.info.name).newInstance(); 2721 } catch (Exception e) { 2722 if (!mInstrumentation.onException(service, e)) { 2723 throw new RuntimeException( 2724 "Unable to instantiate service " + data.info.name 2725 + ": " + e.toString(), e); 2726 } 2727 } 2728 2729 try { 2730 if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); 2731 2732 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); 2733 context.setOuterContext(service); 2734 2735 Application app = packageInfo.makeApplication(false, mInstrumentation); 2736 service.attach(context, this, data.info.name, data.token, app, 2737 ActivityManagerNative.getDefault()); 2738 service.onCreate(); 2739 mServices.put(data.token, service); 2740 try { 2741 ActivityManagerNative.getDefault().serviceDoneExecuting( 2742 data.token, 0, 0, 0); 2743 } catch (RemoteException e) { 2744 // nothing to do. 2745 } 2746 } catch (Exception e) { 2747 if (!mInstrumentation.onException(service, e)) { 2748 throw new RuntimeException( 2749 "Unable to create service " + data.info.name 2750 + ": " + e.toString(), e); 2751 } 2752 } 2753 } 2754 2755 private void handleBindService(BindServiceData data) { 2756 Service s = mServices.get(data.token); 2757 if (DEBUG_SERVICE) 2758 Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind); 2759 if (s != null) { 2760 try { 2761 data.intent.setExtrasClassLoader(s.getClassLoader()); 2762 data.intent.prepareToEnterProcess(); 2763 try { 2764 if (!data.rebind) { 2765 IBinder binder = s.onBind(data.intent); 2766 ActivityManagerNative.getDefault().publishService( 2767 data.token, data.intent, binder); 2768 } else { 2769 s.onRebind(data.intent); 2770 ActivityManagerNative.getDefault().serviceDoneExecuting( 2771 data.token, 0, 0, 0); 2772 } 2773 ensureJitEnabled(); 2774 } catch (RemoteException ex) { 2775 } 2776 } catch (Exception e) { 2777 if (!mInstrumentation.onException(s, e)) { 2778 throw new RuntimeException( 2779 "Unable to bind to service " + s 2780 + " with " + data.intent + ": " + e.toString(), e); 2781 } 2782 } 2783 } 2784 } 2785 2786 private void handleUnbindService(BindServiceData data) { 2787 Service s = mServices.get(data.token); 2788 if (s != null) { 2789 try { 2790 data.intent.setExtrasClassLoader(s.getClassLoader()); 2791 data.intent.prepareToEnterProcess(); 2792 boolean doRebind = s.onUnbind(data.intent); 2793 try { 2794 if (doRebind) { 2795 ActivityManagerNative.getDefault().unbindFinished( 2796 data.token, data.intent, doRebind); 2797 } else { 2798 ActivityManagerNative.getDefault().serviceDoneExecuting( 2799 data.token, 0, 0, 0); 2800 } 2801 } catch (RemoteException ex) { 2802 } 2803 } catch (Exception e) { 2804 if (!mInstrumentation.onException(s, e)) { 2805 throw new RuntimeException( 2806 "Unable to unbind to service " + s 2807 + " with " + data.intent + ": " + e.toString(), e); 2808 } 2809 } 2810 } 2811 } 2812 2813 private void handleDumpService(DumpComponentInfo info) { 2814 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 2815 try { 2816 Service s = mServices.get(info.token); 2817 if (s != null) { 2818 PrintWriter pw = new FastPrintWriter(new FileOutputStream( 2819 info.fd.getFileDescriptor())); 2820 s.dump(info.fd.getFileDescriptor(), pw, info.args); 2821 pw.flush(); 2822 } 2823 } finally { 2824 IoUtils.closeQuietly(info.fd); 2825 StrictMode.setThreadPolicy(oldPolicy); 2826 } 2827 } 2828 2829 private void handleDumpActivity(DumpComponentInfo info) { 2830 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 2831 try { 2832 ActivityClientRecord r = mActivities.get(info.token); 2833 if (r != null && r.activity != null) { 2834 PrintWriter pw = new FastPrintWriter(new FileOutputStream( 2835 info.fd.getFileDescriptor())); 2836 r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args); 2837 pw.flush(); 2838 } 2839 } finally { 2840 IoUtils.closeQuietly(info.fd); 2841 StrictMode.setThreadPolicy(oldPolicy); 2842 } 2843 } 2844 2845 private void handleDumpProvider(DumpComponentInfo info) { 2846 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 2847 try { 2848 ProviderClientRecord r = mLocalProviders.get(info.token); 2849 if (r != null && r.mLocalProvider != null) { 2850 PrintWriter pw = new FastPrintWriter(new FileOutputStream( 2851 info.fd.getFileDescriptor())); 2852 r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args); 2853 pw.flush(); 2854 } 2855 } finally { 2856 IoUtils.closeQuietly(info.fd); 2857 StrictMode.setThreadPolicy(oldPolicy); 2858 } 2859 } 2860 2861 private void handleServiceArgs(ServiceArgsData data) { 2862 Service s = mServices.get(data.token); 2863 if (s != null) { 2864 try { 2865 if (data.args != null) { 2866 data.args.setExtrasClassLoader(s.getClassLoader()); 2867 data.args.prepareToEnterProcess(); 2868 } 2869 int res; 2870 if (!data.taskRemoved) { 2871 res = s.onStartCommand(data.args, data.flags, data.startId); 2872 } else { 2873 s.onTaskRemoved(data.args); 2874 res = Service.START_TASK_REMOVED_COMPLETE; 2875 } 2876 2877 QueuedWork.waitToFinish(); 2878 2879 try { 2880 ActivityManagerNative.getDefault().serviceDoneExecuting( 2881 data.token, 1, data.startId, res); 2882 } catch (RemoteException e) { 2883 // nothing to do. 2884 } 2885 ensureJitEnabled(); 2886 } catch (Exception e) { 2887 if (!mInstrumentation.onException(s, e)) { 2888 throw new RuntimeException( 2889 "Unable to start service " + s 2890 + " with " + data.args + ": " + e.toString(), e); 2891 } 2892 } 2893 } 2894 } 2895 2896 private void handleStopService(IBinder token) { 2897 Service s = mServices.remove(token); 2898 if (s != null) { 2899 try { 2900 if (localLOGV) Slog.v(TAG, "Destroying service " + s); 2901 s.onDestroy(); 2902 Context context = s.getBaseContext(); 2903 if (context instanceof ContextImpl) { 2904 final String who = s.getClassName(); 2905 ((ContextImpl) context).scheduleFinalCleanup(who, "Service"); 2906 } 2907 2908 QueuedWork.waitToFinish(); 2909 2910 try { 2911 ActivityManagerNative.getDefault().serviceDoneExecuting( 2912 token, 0, 0, 0); 2913 } catch (RemoteException e) { 2914 // nothing to do. 2915 } 2916 } catch (Exception e) { 2917 if (!mInstrumentation.onException(s, e)) { 2918 throw new RuntimeException( 2919 "Unable to stop service " + s 2920 + ": " + e.toString(), e); 2921 } 2922 } 2923 } 2924 //Slog.i(TAG, "Running services: " + mServices); 2925 } 2926 2927 public final ActivityClientRecord performResumeActivity(IBinder token, 2928 boolean clearHide) { 2929 ActivityClientRecord r = mActivities.get(token); 2930 if (localLOGV) Slog.v(TAG, "Performing resume of " + r 2931 + " finished=" + r.activity.mFinished); 2932 if (r != null && !r.activity.mFinished) { 2933 if (clearHide) { 2934 r.hideForNow = false; 2935 r.activity.mStartedActivity = false; 2936 } 2937 try { 2938 r.activity.mFragments.noteStateNotSaved(); 2939 if (r.pendingIntents != null) { 2940 deliverNewIntents(r, r.pendingIntents); 2941 r.pendingIntents = null; 2942 } 2943 if (r.pendingResults != null) { 2944 deliverResults(r, r.pendingResults); 2945 r.pendingResults = null; 2946 } 2947 r.activity.performResume(); 2948 2949 EventLog.writeEvent(LOG_ON_RESUME_CALLED, 2950 UserHandle.myUserId(), r.activity.getComponentName().getClassName()); 2951 2952 r.paused = false; 2953 r.stopped = false; 2954 r.state = null; 2955 r.persistentState = null; 2956 } catch (Exception e) { 2957 if (!mInstrumentation.onException(r.activity, e)) { 2958 throw new RuntimeException( 2959 "Unable to resume activity " 2960 + r.intent.getComponent().toShortString() 2961 + ": " + e.toString(), e); 2962 } 2963 } 2964 } 2965 return r; 2966 } 2967 2968 static final void cleanUpPendingRemoveWindows(ActivityClientRecord r) { 2969 if (r.mPendingRemoveWindow != null) { 2970 r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow); 2971 IBinder wtoken = r.mPendingRemoveWindow.getWindowToken(); 2972 if (wtoken != null) { 2973 WindowManagerGlobal.getInstance().closeAll(wtoken, 2974 r.activity.getClass().getName(), "Activity"); 2975 } 2976 } 2977 r.mPendingRemoveWindow = null; 2978 r.mPendingRemoveWindowManager = null; 2979 } 2980 2981 final void handleResumeActivity(IBinder token, 2982 boolean clearHide, boolean isForward, boolean reallyResume) { 2983 // If we are getting ready to gc after going to the background, well 2984 // we are back active so skip it. 2985 unscheduleGcIdler(); 2986 mSomeActivitiesChanged = true; 2987 2988 // TODO Push resumeArgs into the activity for consideration 2989 ActivityClientRecord r = performResumeActivity(token, clearHide); 2990 2991 if (r != null) { 2992 final Activity a = r.activity; 2993 2994 if (localLOGV) Slog.v( 2995 TAG, "Resume " + r + " started activity: " + 2996 a.mStartedActivity + ", hideForNow: " + r.hideForNow 2997 + ", finished: " + a.mFinished); 2998 2999 final int forwardBit = isForward ? 3000 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0; 3001 3002 // If the window hasn't yet been added to the window manager, 3003 // and this guy didn't finish itself or start another activity, 3004 // then go ahead and add the window. 3005 boolean willBeVisible = !a.mStartedActivity; 3006 if (!willBeVisible) { 3007 try { 3008 willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible( 3009 a.getActivityToken()); 3010 } catch (RemoteException e) { 3011 } 3012 } 3013 if (r.window == null && !a.mFinished && willBeVisible) { 3014 r.window = r.activity.getWindow(); 3015 View decor = r.window.getDecorView(); 3016 decor.setVisibility(View.INVISIBLE); 3017 ViewManager wm = a.getWindowManager(); 3018 WindowManager.LayoutParams l = r.window.getAttributes(); 3019 a.mDecor = decor; 3020 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 3021 l.softInputMode |= forwardBit; 3022 if (a.mVisibleFromClient) { 3023 a.mWindowAdded = true; 3024 wm.addView(decor, l); 3025 } 3026 3027 // If the window has already been added, but during resume 3028 // we started another activity, then don't yet make the 3029 // window visible. 3030 } else if (!willBeVisible) { 3031 if (localLOGV) Slog.v( 3032 TAG, "Launch " + r + " mStartedActivity set"); 3033 r.hideForNow = true; 3034 } 3035 3036 // Get rid of anything left hanging around. 3037 cleanUpPendingRemoveWindows(r); 3038 3039 // The window is now visible if it has been added, we are not 3040 // simply finishing, and we are not starting another activity. 3041 if (!r.activity.mFinished && willBeVisible 3042 && r.activity.mDecor != null && !r.hideForNow) { 3043 if (r.newConfig != null) { 3044 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity " 3045 + r.activityInfo.name + " with newConfig " + r.newConfig); 3046 performConfigurationChanged(r.activity, r.newConfig); 3047 freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig)); 3048 r.newConfig = null; 3049 } 3050 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" 3051 + isForward); 3052 WindowManager.LayoutParams l = r.window.getAttributes(); 3053 if ((l.softInputMode 3054 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) 3055 != forwardBit) { 3056 l.softInputMode = (l.softInputMode 3057 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)) 3058 | forwardBit; 3059 if (r.activity.mVisibleFromClient) { 3060 ViewManager wm = a.getWindowManager(); 3061 View decor = r.window.getDecorView(); 3062 wm.updateViewLayout(decor, l); 3063 } 3064 } 3065 r.activity.mVisibleFromServer = true; 3066 mNumVisibleActivities++; 3067 if (r.activity.mVisibleFromClient) { 3068 r.activity.makeVisible(); 3069 } 3070 } 3071 3072 if (!r.onlyLocalRequest) { 3073 r.nextIdle = mNewActivities; 3074 mNewActivities = r; 3075 if (localLOGV) Slog.v( 3076 TAG, "Scheduling idle handler for " + r); 3077 Looper.myQueue().addIdleHandler(new Idler()); 3078 } 3079 r.onlyLocalRequest = false; 3080 3081 // Tell the activity manager we have resumed. 3082 if (reallyResume) { 3083 try { 3084 ActivityManagerNative.getDefault().activityResumed(token); 3085 } catch (RemoteException ex) { 3086 } 3087 } 3088 3089 } else { 3090 // If an exception was thrown when trying to resume, then 3091 // just end this activity. 3092 try { 3093 ActivityManagerNative.getDefault() 3094 .finishActivity(token, Activity.RESULT_CANCELED, null, false); 3095 } catch (RemoteException ex) { 3096 } 3097 } 3098 } 3099 3100 private int mThumbnailWidth = -1; 3101 private int mThumbnailHeight = -1; 3102 private Bitmap mAvailThumbnailBitmap = null; 3103 private Canvas mThumbnailCanvas = null; 3104 3105 private Bitmap createThumbnailBitmap(ActivityClientRecord r) { 3106 Bitmap thumbnail = mAvailThumbnailBitmap; 3107 try { 3108 if (thumbnail == null) { 3109 int w = mThumbnailWidth; 3110 int h; 3111 if (w < 0) { 3112 Resources res = r.activity.getResources(); 3113 int wId = com.android.internal.R.dimen.thumbnail_width; 3114 int hId = com.android.internal.R.dimen.thumbnail_height; 3115 mThumbnailWidth = w = res.getDimensionPixelSize(wId); 3116 mThumbnailHeight = h = res.getDimensionPixelSize(hId); 3117 } else { 3118 h = mThumbnailHeight; 3119 } 3120 3121 // On platforms where we don't want thumbnails, set dims to (0,0) 3122 if ((w > 0) && (h > 0)) { 3123 thumbnail = Bitmap.createBitmap(r.activity.getResources().getDisplayMetrics(), 3124 w, h, THUMBNAIL_FORMAT); 3125 thumbnail.eraseColor(0); 3126 } 3127 } 3128 3129 if (thumbnail != null) { 3130 Canvas cv = mThumbnailCanvas; 3131 if (cv == null) { 3132 mThumbnailCanvas = cv = new Canvas(); 3133 } 3134 3135 cv.setBitmap(thumbnail); 3136 if (!r.activity.onCreateThumbnail(thumbnail, cv)) { 3137 mAvailThumbnailBitmap = thumbnail; 3138 thumbnail = null; 3139 } 3140 cv.setBitmap(null); 3141 } 3142 3143 } catch (Exception e) { 3144 if (!mInstrumentation.onException(r.activity, e)) { 3145 throw new RuntimeException( 3146 "Unable to create thumbnail of " 3147 + r.intent.getComponent().toShortString() 3148 + ": " + e.toString(), e); 3149 } 3150 thumbnail = null; 3151 } 3152 3153 return thumbnail; 3154 } 3155 3156 private void handlePauseActivity(IBinder token, boolean finished, 3157 boolean userLeaving, int configChanges, boolean dontReport) { 3158 ActivityClientRecord r = mActivities.get(token); 3159 if (r != null) { 3160 //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); 3161 if (userLeaving) { 3162 performUserLeavingActivity(r); 3163 } 3164 3165 r.activity.mConfigChangeFlags |= configChanges; 3166 performPauseActivity(token, finished, r.isPreHoneycomb()); 3167 3168 // Make sure any pending writes are now committed. 3169 if (r.isPreHoneycomb()) { 3170 QueuedWork.waitToFinish(); 3171 } 3172 3173 // Tell the activity manager we have paused. 3174 if (!dontReport) { 3175 try { 3176 ActivityManagerNative.getDefault().activityPaused(token); 3177 } catch (RemoteException ex) { 3178 } 3179 } 3180 mSomeActivitiesChanged = true; 3181 } 3182 } 3183 3184 final void performUserLeavingActivity(ActivityClientRecord r) { 3185 mInstrumentation.callActivityOnUserLeaving(r.activity); 3186 } 3187 3188 final Bundle performPauseActivity(IBinder token, boolean finished, 3189 boolean saveState) { 3190 ActivityClientRecord r = mActivities.get(token); 3191 return r != null ? performPauseActivity(r, finished, saveState) : null; 3192 } 3193 3194 final Bundle performPauseActivity(ActivityClientRecord r, boolean finished, 3195 boolean saveState) { 3196 if (r.paused) { 3197 if (r.activity.mFinished) { 3198 // If we are finishing, we won't call onResume() in certain cases. 3199 // So here we likewise don't want to call onPause() if the activity 3200 // isn't resumed. 3201 return null; 3202 } 3203 RuntimeException e = new RuntimeException( 3204 "Performing pause of activity that is not resumed: " 3205 + r.intent.getComponent().toShortString()); 3206 Slog.e(TAG, e.getMessage(), e); 3207 } 3208 if (finished) { 3209 r.activity.mFinished = true; 3210 } 3211 try { 3212 // Next have the activity save its current state and managed dialogs... 3213 if (!r.activity.mFinished && saveState) { 3214 callCallActivityOnSaveInstanceState(r); 3215 } 3216 // Now we are idle. 3217 r.activity.mCalled = false; 3218 mInstrumentation.callActivityOnPause(r.activity); 3219 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(), 3220 r.activity.getComponentName().getClassName()); 3221 if (!r.activity.mCalled) { 3222 throw new SuperNotCalledException( 3223 "Activity " + r.intent.getComponent().toShortString() + 3224 " did not call through to super.onPause()"); 3225 } 3226 3227 } catch (SuperNotCalledException e) { 3228 throw e; 3229 3230 } catch (Exception e) { 3231 if (!mInstrumentation.onException(r.activity, e)) { 3232 throw new RuntimeException( 3233 "Unable to pause activity " 3234 + r.intent.getComponent().toShortString() 3235 + ": " + e.toString(), e); 3236 } 3237 } 3238 r.paused = true; 3239 3240 // Notify any outstanding on paused listeners 3241 ArrayList<OnActivityPausedListener> listeners; 3242 synchronized (mOnPauseListeners) { 3243 listeners = mOnPauseListeners.remove(r.activity); 3244 } 3245 int size = (listeners != null ? listeners.size() : 0); 3246 for (int i = 0; i < size; i++) { 3247 listeners.get(i).onPaused(r.activity); 3248 } 3249 3250 return !r.activity.mFinished && saveState ? r.state : null; 3251 } 3252 3253 final void performStopActivity(IBinder token, boolean saveState) { 3254 ActivityClientRecord r = mActivities.get(token); 3255 performStopActivityInner(r, null, false, saveState); 3256 } 3257 3258 private static class StopInfo implements Runnable { 3259 ActivityClientRecord activity; 3260 Bundle state; 3261 PersistableBundle persistentState; 3262 CharSequence description; 3263 3264 @Override public void run() { 3265 // Tell activity manager we have been stopped. 3266 try { 3267 if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity); 3268 ActivityManagerNative.getDefault().activityStopped( 3269 activity.token, state, persistentState, description); 3270 } catch (RemoteException ex) { 3271 } 3272 } 3273 } 3274 3275 private static final class ProviderRefCount { 3276 public final IActivityManager.ContentProviderHolder holder; 3277 public final ProviderClientRecord client; 3278 public int stableCount; 3279 public int unstableCount; 3280 3281 // When this is set, the stable and unstable ref counts are 0 and 3282 // we have a pending operation scheduled to remove the ref count 3283 // from the activity manager. On the activity manager we are still 3284 // holding an unstable ref, though it is not reflected in the counts 3285 // here. 3286 public boolean removePending; 3287 3288 ProviderRefCount(IActivityManager.ContentProviderHolder inHolder, 3289 ProviderClientRecord inClient, int sCount, int uCount) { 3290 holder = inHolder; 3291 client = inClient; 3292 stableCount = sCount; 3293 unstableCount = uCount; 3294 } 3295 } 3296 3297 /** 3298 * Core implementation of stopping an activity. Note this is a little 3299 * tricky because the server's meaning of stop is slightly different 3300 * than our client -- for the server, stop means to save state and give 3301 * it the result when it is done, but the window may still be visible. 3302 * For the client, we want to call onStop()/onStart() to indicate when 3303 * the activity's UI visibillity changes. 3304 */ 3305 private void performStopActivityInner(ActivityClientRecord r, 3306 StopInfo info, boolean keepShown, boolean saveState) { 3307 if (localLOGV) Slog.v(TAG, "Performing stop of " + r); 3308 if (r != null) { 3309 if (!keepShown && r.stopped) { 3310 if (r.activity.mFinished) { 3311 // If we are finishing, we won't call onResume() in certain 3312 // cases. So here we likewise don't want to call onStop() 3313 // if the activity isn't resumed. 3314 return; 3315 } 3316 RuntimeException e = new RuntimeException( 3317 "Performing stop of activity that is not resumed: " 3318 + r.intent.getComponent().toShortString()); 3319 Slog.e(TAG, e.getMessage(), e); 3320 } 3321 3322 if (info != null) { 3323 try { 3324 // First create a thumbnail for the activity... 3325 // For now, don't create the thumbnail here; we are 3326 // doing that by doing a screen snapshot. 3327 info.description = r.activity.onCreateDescription(); 3328 } catch (Exception e) { 3329 if (!mInstrumentation.onException(r.activity, e)) { 3330 throw new RuntimeException( 3331 "Unable to save state of activity " 3332 + r.intent.getComponent().toShortString() 3333 + ": " + e.toString(), e); 3334 } 3335 } 3336 } 3337 3338 // Next have the activity save its current state and managed dialogs... 3339 if (!r.activity.mFinished && saveState) { 3340 if (r.state == null) { 3341 callCallActivityOnSaveInstanceState(r); 3342 } 3343 } 3344 3345 if (!keepShown) { 3346 try { 3347 // Now we are idle. 3348 r.activity.performStop(); 3349 } catch (Exception e) { 3350 if (!mInstrumentation.onException(r.activity, e)) { 3351 throw new RuntimeException( 3352 "Unable to stop activity " 3353 + r.intent.getComponent().toShortString() 3354 + ": " + e.toString(), e); 3355 } 3356 } 3357 r.stopped = true; 3358 } 3359 3360 r.paused = true; 3361 } 3362 } 3363 3364 private void updateVisibility(ActivityClientRecord r, boolean show) { 3365 View v = r.activity.mDecor; 3366 if (v != null) { 3367 if (show) { 3368 if (!r.activity.mVisibleFromServer) { 3369 r.activity.mVisibleFromServer = true; 3370 mNumVisibleActivities++; 3371 if (r.activity.mVisibleFromClient) { 3372 r.activity.makeVisible(); 3373 } 3374 } 3375 if (r.newConfig != null) { 3376 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis " 3377 + r.activityInfo.name + " with new config " + r.newConfig); 3378 performConfigurationChanged(r.activity, r.newConfig); 3379 freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig)); 3380 r.newConfig = null; 3381 } 3382 } else { 3383 if (r.activity.mVisibleFromServer) { 3384 r.activity.mVisibleFromServer = false; 3385 mNumVisibleActivities--; 3386 v.setVisibility(View.INVISIBLE); 3387 } 3388 } 3389 } 3390 } 3391 3392 private void handleStopActivity(IBinder token, boolean show, int configChanges) { 3393 ActivityClientRecord r = mActivities.get(token); 3394 r.activity.mConfigChangeFlags |= configChanges; 3395 3396 StopInfo info = new StopInfo(); 3397 performStopActivityInner(r, info, show, true); 3398 3399 if (localLOGV) Slog.v( 3400 TAG, "Finishing stop of " + r + ": show=" + show 3401 + " win=" + r.window); 3402 3403 updateVisibility(r, show); 3404 3405 // Make sure any pending writes are now committed. 3406 if (!r.isPreHoneycomb()) { 3407 QueuedWork.waitToFinish(); 3408 } 3409 3410 // Schedule the call to tell the activity manager we have 3411 // stopped. We don't do this immediately, because we want to 3412 // have a chance for any other pending work (in particular memory 3413 // trim requests) to complete before you tell the activity 3414 // manager to proceed and allow us to go fully into the background. 3415 info.activity = r; 3416 info.state = r.state; 3417 info.persistentState = r.persistentState; 3418 mH.post(info); 3419 mSomeActivitiesChanged = true; 3420 } 3421 3422 final void performRestartActivity(IBinder token) { 3423 ActivityClientRecord r = mActivities.get(token); 3424 if (r.stopped) { 3425 r.activity.performRestart(); 3426 r.stopped = false; 3427 } 3428 } 3429 3430 private void handleWindowVisibility(IBinder token, boolean show) { 3431 ActivityClientRecord r = mActivities.get(token); 3432 3433 if (r == null) { 3434 Log.w(TAG, "handleWindowVisibility: no activity for token " + token); 3435 return; 3436 } 3437 3438 if (!show && !r.stopped) { 3439 performStopActivityInner(r, null, show, false); 3440 } else if (show && r.stopped) { 3441 // If we are getting ready to gc after going to the background, well 3442 // we are back active so skip it. 3443 unscheduleGcIdler(); 3444 3445 r.activity.performRestart(); 3446 r.stopped = false; 3447 } 3448 if (r.activity.mDecor != null) { 3449 if (false) Slog.v( 3450 TAG, "Handle window " + r + " visibility: " + show); 3451 updateVisibility(r, show); 3452 } 3453 mSomeActivitiesChanged = true; 3454 } 3455 3456 private void handleSleeping(IBinder token, boolean sleeping) { 3457 ActivityClientRecord r = mActivities.get(token); 3458 3459 if (r == null) { 3460 Log.w(TAG, "handleSleeping: no activity for token " + token); 3461 return; 3462 } 3463 3464 if (sleeping) { 3465 if (!r.stopped && !r.isPreHoneycomb()) { 3466 try { 3467 // Now we are idle. 3468 r.activity.performStop(); 3469 } catch (Exception e) { 3470 if (!mInstrumentation.onException(r.activity, e)) { 3471 throw new RuntimeException( 3472 "Unable to stop activity " 3473 + r.intent.getComponent().toShortString() 3474 + ": " + e.toString(), e); 3475 } 3476 } 3477 r.stopped = true; 3478 } 3479 3480 // Make sure any pending writes are now committed. 3481 if (!r.isPreHoneycomb()) { 3482 QueuedWork.waitToFinish(); 3483 } 3484 3485 // Tell activity manager we slept. 3486 try { 3487 ActivityManagerNative.getDefault().activitySlept(r.token); 3488 } catch (RemoteException ex) { 3489 } 3490 } else { 3491 if (r.stopped && r.activity.mVisibleFromServer) { 3492 r.activity.performRestart(); 3493 r.stopped = false; 3494 } 3495 } 3496 } 3497 3498 private void handleSetCoreSettings(Bundle coreSettings) { 3499 synchronized (mResourcesManager) { 3500 mCoreSettings = coreSettings; 3501 } 3502 onCoreSettingsChange(); 3503 } 3504 3505 private void onCoreSettingsChange() { 3506 boolean debugViewAttributes = 3507 mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; 3508 if (debugViewAttributes != View.mDebugViewAttributes) { 3509 View.mDebugViewAttributes = debugViewAttributes; 3510 3511 // request all activities to relaunch for the changes to take place 3512 for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) { 3513 requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, false); 3514 } 3515 } 3516 } 3517 3518 private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) { 3519 LoadedApk apk = peekPackageInfo(data.pkg, false); 3520 if (apk != null) { 3521 apk.setCompatibilityInfo(data.info); 3522 } 3523 apk = peekPackageInfo(data.pkg, true); 3524 if (apk != null) { 3525 apk.setCompatibilityInfo(data.info); 3526 } 3527 handleConfigurationChanged(mConfiguration, data.info); 3528 WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration); 3529 } 3530 3531 private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) { 3532 final int N = results.size(); 3533 for (int i=0; i<N; i++) { 3534 ResultInfo ri = results.get(i); 3535 try { 3536 if (ri.mData != null) { 3537 ri.mData.setExtrasClassLoader(r.activity.getClassLoader()); 3538 ri.mData.prepareToEnterProcess(); 3539 } 3540 if (DEBUG_RESULTS) Slog.v(TAG, 3541 "Delivering result to activity " + r + " : " + ri); 3542 r.activity.dispatchActivityResult(ri.mResultWho, 3543 ri.mRequestCode, ri.mResultCode, ri.mData); 3544 } catch (Exception e) { 3545 if (!mInstrumentation.onException(r.activity, e)) { 3546 throw new RuntimeException( 3547 "Failure delivering result " + ri + " to activity " 3548 + r.intent.getComponent().toShortString() 3549 + ": " + e.toString(), e); 3550 } 3551 } 3552 } 3553 } 3554 3555 private void handleSendResult(ResultData res) { 3556 ActivityClientRecord r = mActivities.get(res.token); 3557 if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r); 3558 if (r != null) { 3559 final boolean resumed = !r.paused; 3560 if (!r.activity.mFinished && r.activity.mDecor != null 3561 && r.hideForNow && resumed) { 3562 // We had hidden the activity because it started another 3563 // one... we have gotten a result back and we are not 3564 // paused, so make sure our window is visible. 3565 updateVisibility(r, true); 3566 } 3567 if (resumed) { 3568 try { 3569 // Now we are idle. 3570 r.activity.mCalled = false; 3571 r.activity.mTemporaryPause = true; 3572 mInstrumentation.callActivityOnPause(r.activity); 3573 if (!r.activity.mCalled) { 3574 throw new SuperNotCalledException( 3575 "Activity " + r.intent.getComponent().toShortString() 3576 + " did not call through to super.onPause()"); 3577 } 3578 } catch (SuperNotCalledException e) { 3579 throw e; 3580 } catch (Exception e) { 3581 if (!mInstrumentation.onException(r.activity, e)) { 3582 throw new RuntimeException( 3583 "Unable to pause activity " 3584 + r.intent.getComponent().toShortString() 3585 + ": " + e.toString(), e); 3586 } 3587 } 3588 } 3589 deliverResults(r, res.results); 3590 if (resumed) { 3591 r.activity.performResume(); 3592 r.activity.mTemporaryPause = false; 3593 } 3594 } 3595 } 3596 3597 public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) { 3598 return performDestroyActivity(token, finishing, 0, false); 3599 } 3600 3601 private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, 3602 int configChanges, boolean getNonConfigInstance) { 3603 ActivityClientRecord r = mActivities.get(token); 3604 Class<? extends Activity> activityClass = null; 3605 if (localLOGV) Slog.v(TAG, "Performing finish of " + r); 3606 if (r != null) { 3607 activityClass = r.activity.getClass(); 3608 r.activity.mConfigChangeFlags |= configChanges; 3609 if (finishing) { 3610 r.activity.mFinished = true; 3611 } 3612 if (!r.paused) { 3613 try { 3614 r.activity.mCalled = false; 3615 mInstrumentation.callActivityOnPause(r.activity); 3616 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(), 3617 r.activity.getComponentName().getClassName()); 3618 if (!r.activity.mCalled) { 3619 throw new SuperNotCalledException( 3620 "Activity " + safeToComponentShortString(r.intent) 3621 + " did not call through to super.onPause()"); 3622 } 3623 } catch (SuperNotCalledException e) { 3624 throw e; 3625 } catch (Exception e) { 3626 if (!mInstrumentation.onException(r.activity, e)) { 3627 throw new RuntimeException( 3628 "Unable to pause activity " 3629 + safeToComponentShortString(r.intent) 3630 + ": " + e.toString(), e); 3631 } 3632 } 3633 r.paused = true; 3634 } 3635 if (!r.stopped) { 3636 try { 3637 r.activity.performStop(); 3638 } catch (SuperNotCalledException e) { 3639 throw e; 3640 } catch (Exception e) { 3641 if (!mInstrumentation.onException(r.activity, e)) { 3642 throw new RuntimeException( 3643 "Unable to stop activity " 3644 + safeToComponentShortString(r.intent) 3645 + ": " + e.toString(), e); 3646 } 3647 } 3648 r.stopped = true; 3649 } 3650 if (getNonConfigInstance) { 3651 try { 3652 r.lastNonConfigurationInstances 3653 = r.activity.retainNonConfigurationInstances(); 3654 } catch (Exception e) { 3655 if (!mInstrumentation.onException(r.activity, e)) { 3656 throw new RuntimeException( 3657 "Unable to retain activity " 3658 + r.intent.getComponent().toShortString() 3659 + ": " + e.toString(), e); 3660 } 3661 } 3662 } 3663 try { 3664 r.activity.mCalled = false; 3665 mInstrumentation.callActivityOnDestroy(r.activity); 3666 if (!r.activity.mCalled) { 3667 throw new SuperNotCalledException( 3668 "Activity " + safeToComponentShortString(r.intent) + 3669 " did not call through to super.onDestroy()"); 3670 } 3671 if (r.window != null) { 3672 r.window.closeAllPanels(); 3673 } 3674 } catch (SuperNotCalledException e) { 3675 throw e; 3676 } catch (Exception e) { 3677 if (!mInstrumentation.onException(r.activity, e)) { 3678 throw new RuntimeException( 3679 "Unable to destroy activity " + safeToComponentShortString(r.intent) 3680 + ": " + e.toString(), e); 3681 } 3682 } 3683 } 3684 mActivities.remove(token); 3685 StrictMode.decrementExpectedActivityCount(activityClass); 3686 return r; 3687 } 3688 3689 private static String safeToComponentShortString(Intent intent) { 3690 ComponentName component = intent.getComponent(); 3691 return component == null ? "[Unknown]" : component.toShortString(); 3692 } 3693 3694 private void handleDestroyActivity(IBinder token, boolean finishing, 3695 int configChanges, boolean getNonConfigInstance) { 3696 ActivityClientRecord r = performDestroyActivity(token, finishing, 3697 configChanges, getNonConfigInstance); 3698 if (r != null) { 3699 cleanUpPendingRemoveWindows(r); 3700 WindowManager wm = r.activity.getWindowManager(); 3701 View v = r.activity.mDecor; 3702 if (v != null) { 3703 if (r.activity.mVisibleFromServer) { 3704 mNumVisibleActivities--; 3705 } 3706 IBinder wtoken = v.getWindowToken(); 3707 if (r.activity.mWindowAdded) { 3708 if (r.onlyLocalRequest) { 3709 // Hold off on removing this until the new activity's 3710 // window is being added. 3711 r.mPendingRemoveWindow = v; 3712 r.mPendingRemoveWindowManager = wm; 3713 } else { 3714 wm.removeViewImmediate(v); 3715 } 3716 } 3717 if (wtoken != null && r.mPendingRemoveWindow == null) { 3718 WindowManagerGlobal.getInstance().closeAll(wtoken, 3719 r.activity.getClass().getName(), "Activity"); 3720 } 3721 r.activity.mDecor = null; 3722 } 3723 if (r.mPendingRemoveWindow == null) { 3724 // If we are delaying the removal of the activity window, then 3725 // we can't clean up all windows here. Note that we can't do 3726 // so later either, which means any windows that aren't closed 3727 // by the app will leak. Well we try to warning them a lot 3728 // about leaking windows, because that is a bug, so if they are 3729 // using this recreate facility then they get to live with leaks. 3730 WindowManagerGlobal.getInstance().closeAll(token, 3731 r.activity.getClass().getName(), "Activity"); 3732 } 3733 3734 // Mocked out contexts won't be participating in the normal 3735 // process lifecycle, but if we're running with a proper 3736 // ApplicationContext we need to have it tear down things 3737 // cleanly. 3738 Context c = r.activity.getBaseContext(); 3739 if (c instanceof ContextImpl) { 3740 ((ContextImpl) c).scheduleFinalCleanup( 3741 r.activity.getClass().getName(), "Activity"); 3742 } 3743 } 3744 if (finishing) { 3745 try { 3746 ActivityManagerNative.getDefault().activityDestroyed(token); 3747 } catch (RemoteException ex) { 3748 // If the system process has died, it's game over for everyone. 3749 } 3750 } 3751 mSomeActivitiesChanged = true; 3752 } 3753 3754 public final void requestRelaunchActivity(IBinder token, 3755 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, 3756 int configChanges, boolean notResumed, Configuration config, 3757 boolean fromServer) { 3758 ActivityClientRecord target = null; 3759 3760 synchronized (mResourcesManager) { 3761 for (int i=0; i<mRelaunchingActivities.size(); i++) { 3762 ActivityClientRecord r = mRelaunchingActivities.get(i); 3763 if (r.token == token) { 3764 target = r; 3765 if (pendingResults != null) { 3766 if (r.pendingResults != null) { 3767 r.pendingResults.addAll(pendingResults); 3768 } else { 3769 r.pendingResults = pendingResults; 3770 } 3771 } 3772 if (pendingNewIntents != null) { 3773 if (r.pendingIntents != null) { 3774 r.pendingIntents.addAll(pendingNewIntents); 3775 } else { 3776 r.pendingIntents = pendingNewIntents; 3777 } 3778 } 3779 break; 3780 } 3781 } 3782 3783 if (target == null) { 3784 target = new ActivityClientRecord(); 3785 target.token = token; 3786 target.pendingResults = pendingResults; 3787 target.pendingIntents = pendingNewIntents; 3788 if (!fromServer) { 3789 ActivityClientRecord existing = mActivities.get(token); 3790 if (existing != null) { 3791 target.startsNotResumed = existing.paused; 3792 } 3793 target.onlyLocalRequest = true; 3794 } 3795 mRelaunchingActivities.add(target); 3796 sendMessage(H.RELAUNCH_ACTIVITY, target); 3797 } 3798 3799 if (fromServer) { 3800 target.startsNotResumed = notResumed; 3801 target.onlyLocalRequest = false; 3802 } 3803 if (config != null) { 3804 target.createdConfig = config; 3805 } 3806 target.pendingConfigChanges |= configChanges; 3807 } 3808 } 3809 3810 private void handleRelaunchActivity(ActivityClientRecord tmp) { 3811 // If we are getting ready to gc after going to the background, well 3812 // we are back active so skip it. 3813 unscheduleGcIdler(); 3814 mSomeActivitiesChanged = true; 3815 3816 Configuration changedConfig = null; 3817 int configChanges = 0; 3818 3819 // First: make sure we have the most recent configuration and most 3820 // recent version of the activity, or skip it if some previous call 3821 // had taken a more recent version. 3822 synchronized (mResourcesManager) { 3823 int N = mRelaunchingActivities.size(); 3824 IBinder token = tmp.token; 3825 tmp = null; 3826 for (int i=0; i<N; i++) { 3827 ActivityClientRecord r = mRelaunchingActivities.get(i); 3828 if (r.token == token) { 3829 tmp = r; 3830 configChanges |= tmp.pendingConfigChanges; 3831 mRelaunchingActivities.remove(i); 3832 i--; 3833 N--; 3834 } 3835 } 3836 3837 if (tmp == null) { 3838 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!"); 3839 return; 3840 } 3841 3842 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity " 3843 + tmp.token + " with configChanges=0x" 3844 + Integer.toHexString(configChanges)); 3845 3846 if (mPendingConfiguration != null) { 3847 changedConfig = mPendingConfiguration; 3848 mPendingConfiguration = null; 3849 } 3850 } 3851 3852 if (tmp.createdConfig != null) { 3853 // If the activity manager is passing us its current config, 3854 // assume that is really what we want regardless of what we 3855 // may have pending. 3856 if (mConfiguration == null 3857 || (tmp.createdConfig.isOtherSeqNewer(mConfiguration) 3858 && mConfiguration.diff(tmp.createdConfig) != 0)) { 3859 if (changedConfig == null 3860 || tmp.createdConfig.isOtherSeqNewer(changedConfig)) { 3861 changedConfig = tmp.createdConfig; 3862 } 3863 } 3864 } 3865 3866 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity " 3867 + tmp.token + ": changedConfig=" + changedConfig); 3868 3869 // If there was a pending configuration change, execute it first. 3870 if (changedConfig != null) { 3871 mCurDefaultDisplayDpi = changedConfig.densityDpi; 3872 updateDefaultDensity(); 3873 handleConfigurationChanged(changedConfig, null); 3874 } 3875 3876 ActivityClientRecord r = mActivities.get(tmp.token); 3877 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r); 3878 if (r == null) { 3879 return; 3880 } 3881 3882 r.activity.mConfigChangeFlags |= configChanges; 3883 r.onlyLocalRequest = tmp.onlyLocalRequest; 3884 Intent currentIntent = r.activity.mIntent; 3885 3886 r.activity.mChangingConfigurations = true; 3887 3888 // Need to ensure state is saved. 3889 if (!r.paused) { 3890 performPauseActivity(r.token, false, r.isPreHoneycomb()); 3891 } 3892 if (r.state == null && !r.stopped && !r.isPreHoneycomb()) { 3893 callCallActivityOnSaveInstanceState(r); 3894 } 3895 3896 handleDestroyActivity(r.token, false, configChanges, true); 3897 3898 r.activity = null; 3899 r.window = null; 3900 r.hideForNow = false; 3901 r.nextIdle = null; 3902 // Merge any pending results and pending intents; don't just replace them 3903 if (tmp.pendingResults != null) { 3904 if (r.pendingResults == null) { 3905 r.pendingResults = tmp.pendingResults; 3906 } else { 3907 r.pendingResults.addAll(tmp.pendingResults); 3908 } 3909 } 3910 if (tmp.pendingIntents != null) { 3911 if (r.pendingIntents == null) { 3912 r.pendingIntents = tmp.pendingIntents; 3913 } else { 3914 r.pendingIntents.addAll(tmp.pendingIntents); 3915 } 3916 } 3917 r.startsNotResumed = tmp.startsNotResumed; 3918 3919 handleLaunchActivity(r, currentIntent); 3920 } 3921 3922 private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) { 3923 r.state = new Bundle(); 3924 r.state.setAllowFds(false); 3925 if (r.isPersistable()) { 3926 r.persistentState = new PersistableBundle(); 3927 mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state, 3928 r.persistentState); 3929 } else { 3930 mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state); 3931 } 3932 } 3933 3934 ArrayList<ComponentCallbacks2> collectComponentCallbacks( 3935 boolean allActivities, Configuration newConfig) { 3936 ArrayList<ComponentCallbacks2> callbacks 3937 = new ArrayList<ComponentCallbacks2>(); 3938 3939 synchronized (mResourcesManager) { 3940 final int NAPP = mAllApplications.size(); 3941 for (int i=0; i<NAPP; i++) { 3942 callbacks.add(mAllApplications.get(i)); 3943 } 3944 final int NACT = mActivities.size(); 3945 for (int i=0; i<NACT; i++) { 3946 ActivityClientRecord ar = mActivities.valueAt(i); 3947 Activity a = ar.activity; 3948 if (a != null) { 3949 Configuration thisConfig = applyConfigCompatMainThread( 3950 mCurDefaultDisplayDpi, newConfig, 3951 ar.packageInfo.getCompatibilityInfo()); 3952 if (!ar.activity.mFinished && (allActivities || !ar.paused)) { 3953 // If the activity is currently resumed, its configuration 3954 // needs to change right now. 3955 callbacks.add(a); 3956 } else if (thisConfig != null) { 3957 // Otherwise, we will tell it about the change 3958 // the next time it is resumed or shown. Note that 3959 // the activity manager may, before then, decide the 3960 // activity needs to be destroyed to handle its new 3961 // configuration. 3962 if (DEBUG_CONFIGURATION) { 3963 Slog.v(TAG, "Setting activity " 3964 + ar.activityInfo.name + " newConfig=" + thisConfig); 3965 } 3966 ar.newConfig = thisConfig; 3967 } 3968 } 3969 } 3970 final int NSVC = mServices.size(); 3971 for (int i=0; i<NSVC; i++) { 3972 callbacks.add(mServices.valueAt(i)); 3973 } 3974 } 3975 synchronized (mProviderMap) { 3976 final int NPRV = mLocalProviders.size(); 3977 for (int i=0; i<NPRV; i++) { 3978 callbacks.add(mLocalProviders.valueAt(i).mLocalProvider); 3979 } 3980 } 3981 3982 return callbacks; 3983 } 3984 3985 private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) { 3986 // Only for Activity objects, check that they actually call up to their 3987 // superclass implementation. ComponentCallbacks2 is an interface, so 3988 // we check the runtime type and act accordingly. 3989 Activity activity = (cb instanceof Activity) ? (Activity) cb : null; 3990 if (activity != null) { 3991 activity.mCalled = false; 3992 } 3993 3994 boolean shouldChangeConfig = false; 3995 if ((activity == null) || (activity.mCurrentConfig == null)) { 3996 shouldChangeConfig = true; 3997 } else { 3998 3999 // If the new config is the same as the config this Activity 4000 // is already running with then don't bother calling 4001 // onConfigurationChanged 4002 int diff = activity.mCurrentConfig.diff(config); 4003 if (diff != 0) { 4004 // If this activity doesn't handle any of the config changes 4005 // then don't bother calling onConfigurationChanged as we're 4006 // going to destroy it. 4007 if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) { 4008 shouldChangeConfig = true; 4009 } 4010 } 4011 } 4012 4013 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb 4014 + ": shouldChangeConfig=" + shouldChangeConfig); 4015 if (shouldChangeConfig) { 4016 cb.onConfigurationChanged(config); 4017 4018 if (activity != null) { 4019 if (!activity.mCalled) { 4020 throw new SuperNotCalledException( 4021 "Activity " + activity.getLocalClassName() + 4022 " did not call through to super.onConfigurationChanged()"); 4023 } 4024 activity.mConfigChangeFlags = 0; 4025 activity.mCurrentConfig = new Configuration(config); 4026 } 4027 } 4028 } 4029 4030 public final void applyConfigurationToResources(Configuration config) { 4031 synchronized (mResourcesManager) { 4032 mResourcesManager.applyConfigurationToResourcesLocked(config, null); 4033 } 4034 } 4035 4036 final Configuration applyCompatConfiguration(int displayDensity) { 4037 Configuration config = mConfiguration; 4038 if (mCompatConfiguration == null) { 4039 mCompatConfiguration = new Configuration(); 4040 } 4041 mCompatConfiguration.setTo(mConfiguration); 4042 if (mResourcesManager.applyCompatConfiguration(displayDensity, mCompatConfiguration)) { 4043 config = mCompatConfiguration; 4044 } 4045 return config; 4046 } 4047 4048 final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) { 4049 4050 int configDiff = 0; 4051 4052 synchronized (mResourcesManager) { 4053 if (mPendingConfiguration != null) { 4054 if (!mPendingConfiguration.isOtherSeqNewer(config)) { 4055 config = mPendingConfiguration; 4056 mCurDefaultDisplayDpi = config.densityDpi; 4057 updateDefaultDensity(); 4058 } 4059 mPendingConfiguration = null; 4060 } 4061 4062 if (config == null) { 4063 return; 4064 } 4065 4066 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: " 4067 + config); 4068 4069 mResourcesManager.applyConfigurationToResourcesLocked(config, compat); 4070 4071 if (mConfiguration == null) { 4072 mConfiguration = new Configuration(); 4073 } 4074 if (!mConfiguration.isOtherSeqNewer(config) && compat == null) { 4075 return; 4076 } 4077 configDiff = mConfiguration.diff(config); 4078 mConfiguration.updateFrom(config); 4079 config = applyCompatConfiguration(mCurDefaultDisplayDpi); 4080 } 4081 4082 ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config); 4083 4084 freeTextLayoutCachesIfNeeded(configDiff); 4085 4086 if (callbacks != null) { 4087 final int N = callbacks.size(); 4088 for (int i=0; i<N; i++) { 4089 performConfigurationChanged(callbacks.get(i), config); 4090 } 4091 } 4092 } 4093 4094 static void freeTextLayoutCachesIfNeeded(int configDiff) { 4095 if (configDiff != 0) { 4096 // Ask text layout engine to free its caches if there is a locale change 4097 boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0); 4098 if (hasLocaleConfigChange) { 4099 Canvas.freeTextLayoutCaches(); 4100 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches"); 4101 } 4102 } 4103 } 4104 4105 final void handleActivityConfigurationChanged(IBinder token) { 4106 ActivityClientRecord r = mActivities.get(token); 4107 if (r == null || r.activity == null) { 4108 return; 4109 } 4110 4111 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: " 4112 + r.activityInfo.name); 4113 4114 performConfigurationChanged(r.activity, mCompatConfiguration); 4115 4116 freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration)); 4117 4118 mSomeActivitiesChanged = true; 4119 } 4120 4121 final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) { 4122 if (start) { 4123 try { 4124 switch (profileType) { 4125 default: 4126 mProfiler.setProfiler(profilerInfo); 4127 mProfiler.startProfiling(); 4128 break; 4129 } 4130 } catch (RuntimeException e) { 4131 Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile 4132 + " -- can the process access this path?"); 4133 } finally { 4134 try { 4135 profilerInfo.profileFd.close(); 4136 } catch (IOException e) { 4137 Slog.w(TAG, "Failure closing profile fd", e); 4138 } 4139 } 4140 } else { 4141 switch (profileType) { 4142 default: 4143 mProfiler.stopProfiling(); 4144 break; 4145 } 4146 } 4147 } 4148 4149 static final void handleDumpHeap(boolean managed, DumpHeapData dhd) { 4150 if (managed) { 4151 try { 4152 Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor()); 4153 } catch (IOException e) { 4154 Slog.w(TAG, "Managed heap dump failed on path " + dhd.path 4155 + " -- can the process access this path?"); 4156 } finally { 4157 try { 4158 dhd.fd.close(); 4159 } catch (IOException e) { 4160 Slog.w(TAG, "Failure closing profile fd", e); 4161 } 4162 } 4163 } else { 4164 Debug.dumpNativeHeap(dhd.fd.getFileDescriptor()); 4165 } 4166 } 4167 4168 final void handleDispatchPackageBroadcast(int cmd, String[] packages) { 4169 boolean hasPkgInfo = false; 4170 if (packages != null) { 4171 for (int i=packages.length-1; i>=0; i--) { 4172 //Slog.i(TAG, "Cleaning old package: " + packages[i]); 4173 if (!hasPkgInfo) { 4174 WeakReference<LoadedApk> ref; 4175 ref = mPackages.get(packages[i]); 4176 if (ref != null && ref.get() != null) { 4177 hasPkgInfo = true; 4178 } else { 4179 ref = mResourcePackages.get(packages[i]); 4180 if (ref != null && ref.get() != null) { 4181 hasPkgInfo = true; 4182 } 4183 } 4184 } 4185 mPackages.remove(packages[i]); 4186 mResourcePackages.remove(packages[i]); 4187 } 4188 } 4189 ApplicationPackageManager.handlePackageBroadcast(cmd, packages, 4190 hasPkgInfo); 4191 } 4192 4193 final void handleLowMemory() { 4194 ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null); 4195 4196 final int N = callbacks.size(); 4197 for (int i=0; i<N; i++) { 4198 callbacks.get(i).onLowMemory(); 4199 } 4200 4201 // Ask SQLite to free up as much memory as it can, mostly from its page caches. 4202 if (Process.myUid() != Process.SYSTEM_UID) { 4203 int sqliteReleased = SQLiteDatabase.releaseMemory(); 4204 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); 4205 } 4206 4207 // Ask graphics to free up as much as possible (font/image caches) 4208 Canvas.freeCaches(); 4209 4210 // Ask text layout engine to free also as much as possible 4211 Canvas.freeTextLayoutCaches(); 4212 4213 BinderInternal.forceGc("mem"); 4214 } 4215 4216 final void handleTrimMemory(int level) { 4217 if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level); 4218 4219 ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null); 4220 4221 final int N = callbacks.size(); 4222 for (int i = 0; i < N; i++) { 4223 callbacks.get(i).onTrimMemory(level); 4224 } 4225 4226 WindowManagerGlobal.getInstance().trimMemory(level); 4227 } 4228 4229 private void setupGraphicsSupport(LoadedApk info, File cacheDir) { 4230 if (Process.isIsolated()) { 4231 // Isolated processes aren't going to do UI. 4232 return; 4233 } 4234 try { 4235 int uid = Process.myUid(); 4236 String[] packages = getPackageManager().getPackagesForUid(uid); 4237 4238 // If there are several packages in this application we won't 4239 // initialize the graphics disk caches 4240 if (packages != null && packages.length == 1) { 4241 HardwareRenderer.setupDiskCache(cacheDir); 4242 RenderScript.setupDiskCache(cacheDir); 4243 } 4244 } catch (RemoteException e) { 4245 // Ignore 4246 } 4247 } 4248 4249 private void updateDefaultDensity() { 4250 if (mCurDefaultDisplayDpi != Configuration.DENSITY_DPI_UNDEFINED 4251 && mCurDefaultDisplayDpi != DisplayMetrics.DENSITY_DEVICE 4252 && !mDensityCompatMode) { 4253 Slog.i(TAG, "Switching default density from " 4254 + DisplayMetrics.DENSITY_DEVICE + " to " 4255 + mCurDefaultDisplayDpi); 4256 DisplayMetrics.DENSITY_DEVICE = mCurDefaultDisplayDpi; 4257 Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); 4258 } 4259 } 4260 4261 private void handleBindApplication(AppBindData data) { 4262 mBoundApplication = data; 4263 mConfiguration = new Configuration(data.config); 4264 mCompatConfiguration = new Configuration(data.config); 4265 4266 mProfiler = new Profiler(); 4267 if (data.initProfilerInfo != null) { 4268 mProfiler.profileFile = data.initProfilerInfo.profileFile; 4269 mProfiler.profileFd = data.initProfilerInfo.profileFd; 4270 mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval; 4271 mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler; 4272 } 4273 4274 // send up app name; do this *before* waiting for debugger 4275 Process.setArgV0(data.processName); 4276 android.ddm.DdmHandleAppName.setAppName(data.processName, 4277 UserHandle.myUserId()); 4278 4279 if (data.persistent) { 4280 // Persistent processes on low-memory devices do not get to 4281 // use hardware accelerated drawing, since this can add too much 4282 // overhead to the process. 4283 if (!ActivityManager.isHighEndGfx()) { 4284 HardwareRenderer.disable(false); 4285 } 4286 } 4287 4288 if (mProfiler.profileFd != null) { 4289 mProfiler.startProfiling(); 4290 } 4291 4292 // If the app is Honeycomb MR1 or earlier, switch its AsyncTask 4293 // implementation to use the pool executor. Normally, we use the 4294 // serialized executor as the default. This has to happen in the 4295 // main thread so the main looper is set right. 4296 if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { 4297 AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 4298 } 4299 4300 Message.updateCheckRecycle(data.appInfo.targetSdkVersion); 4301 4302 /* 4303 * Before spawning a new process, reset the time zone to be the system time zone. 4304 * This needs to be done because the system time zone could have changed after the 4305 * the spawning of this process. Without doing this this process would have the incorrect 4306 * system time zone. 4307 */ 4308 TimeZone.setDefault(null); 4309 4310 /* 4311 * Initialize the default locale in this process for the reasons we set the time zone. 4312 */ 4313 Locale.setDefault(data.config.locale); 4314 4315 /* 4316 * Update the system configuration since its preloaded and might not 4317 * reflect configuration changes. The configuration object passed 4318 * in AppBindData can be safely assumed to be up to date 4319 */ 4320 mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo); 4321 mCurDefaultDisplayDpi = data.config.densityDpi; 4322 applyCompatConfiguration(mCurDefaultDisplayDpi); 4323 4324 data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 4325 4326 /** 4327 * Switch this process to density compatibility mode if needed. 4328 */ 4329 if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) 4330 == 0) { 4331 mDensityCompatMode = true; 4332 Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); 4333 } 4334 updateDefaultDensity(); 4335 4336 final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); 4337 if (!Process.isIsolated()) { 4338 final File cacheDir = appContext.getCacheDir(); 4339 4340 if (cacheDir != null) { 4341 // Provide a usable directory for temporary files 4342 System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath()); 4343 4344 setupGraphicsSupport(data.info, cacheDir); 4345 } else { 4346 Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory"); 4347 } 4348 } 4349 4350 4351 final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24)); 4352 DateFormat.set24HourTimePref(is24Hr); 4353 4354 View.mDebugViewAttributes = 4355 mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; 4356 4357 /** 4358 * For system applications on userdebug/eng builds, log stack 4359 * traces of disk and network access to dropbox for analysis. 4360 */ 4361 if ((data.appInfo.flags & 4362 (ApplicationInfo.FLAG_SYSTEM | 4363 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) { 4364 StrictMode.conditionallyEnableDebugLogging(); 4365 } 4366 4367 /** 4368 * For apps targetting SDK Honeycomb or later, we don't allow 4369 * network usage on the main event loop / UI thread. 4370 * 4371 * Note to those grepping: this is what ultimately throws 4372 * NetworkOnMainThreadException ... 4373 */ 4374 if (data.appInfo.targetSdkVersion > 9) { 4375 StrictMode.enableDeathOnNetwork(); 4376 } 4377 4378 if (data.debugMode != IApplicationThread.DEBUG_OFF) { 4379 // XXX should have option to change the port. 4380 Debug.changeDebugPort(8100); 4381 if (data.debugMode == IApplicationThread.DEBUG_WAIT) { 4382 Slog.w(TAG, "Application " + data.info.getPackageName() 4383 + " is waiting for the debugger on port 8100..."); 4384 4385 IActivityManager mgr = ActivityManagerNative.getDefault(); 4386 try { 4387 mgr.showWaitingForDebugger(mAppThread, true); 4388 } catch (RemoteException ex) { 4389 } 4390 4391 Debug.waitForDebugger(); 4392 4393 try { 4394 mgr.showWaitingForDebugger(mAppThread, false); 4395 } catch (RemoteException ex) { 4396 } 4397 4398 } else { 4399 Slog.w(TAG, "Application " + data.info.getPackageName() 4400 + " can be debugged on port 8100..."); 4401 } 4402 } 4403 4404 // Enable OpenGL tracing if required 4405 if (data.enableOpenGlTrace) { 4406 GLUtils.setTracingLevel(1); 4407 } 4408 4409 // Allow application-generated systrace messages if we're debuggable. 4410 boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0; 4411 Trace.setAppTracingAllowed(appTracingAllowed); 4412 4413 /** 4414 * Initialize the default http proxy in this process for the reasons we set the time zone. 4415 */ 4416 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); 4417 if (b != null) { 4418 // In pre-boot mode (doing initial launch to collect password), not 4419 // all system is up. This includes the connectivity service, so don't 4420 // crash if we can't get it. 4421 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); 4422 try { 4423 ProxyInfo proxyInfo = service.getProxy(); 4424 Proxy.setHttpProxySystemProperty(proxyInfo); 4425 } catch (RemoteException e) {} 4426 } 4427 4428 if (data.instrumentationName != null) { 4429 InstrumentationInfo ii = null; 4430 try { 4431 ii = appContext.getPackageManager(). 4432 getInstrumentationInfo(data.instrumentationName, 0); 4433 } catch (PackageManager.NameNotFoundException e) { 4434 } 4435 if (ii == null) { 4436 throw new RuntimeException( 4437 "Unable to find instrumentation info for: " 4438 + data.instrumentationName); 4439 } 4440 4441 mInstrumentationPackageName = ii.packageName; 4442 mInstrumentationAppDir = ii.sourceDir; 4443 mInstrumentationSplitAppDirs = ii.splitSourceDirs; 4444 mInstrumentationLibDir = ii.nativeLibraryDir; 4445 mInstrumentedAppDir = data.info.getAppDir(); 4446 mInstrumentedSplitAppDirs = data.info.getSplitAppDirs(); 4447 mInstrumentedLibDir = data.info.getLibDir(); 4448 4449 ApplicationInfo instrApp = new ApplicationInfo(); 4450 instrApp.packageName = ii.packageName; 4451 instrApp.sourceDir = ii.sourceDir; 4452 instrApp.publicSourceDir = ii.publicSourceDir; 4453 instrApp.splitSourceDirs = ii.splitSourceDirs; 4454 instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs; 4455 instrApp.dataDir = ii.dataDir; 4456 instrApp.nativeLibraryDir = ii.nativeLibraryDir; 4457 LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, 4458 appContext.getClassLoader(), false, true, false); 4459 ContextImpl instrContext = ContextImpl.createAppContext(this, pi); 4460 4461 try { 4462 java.lang.ClassLoader cl = instrContext.getClassLoader(); 4463 mInstrumentation = (Instrumentation) 4464 cl.loadClass(data.instrumentationName.getClassName()).newInstance(); 4465 } catch (Exception e) { 4466 throw new RuntimeException( 4467 "Unable to instantiate instrumentation " 4468 + data.instrumentationName + ": " + e.toString(), e); 4469 } 4470 4471 mInstrumentation.init(this, instrContext, appContext, 4472 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher, 4473 data.instrumentationUiAutomationConnection); 4474 4475 if (mProfiler.profileFile != null && !ii.handleProfiling 4476 && mProfiler.profileFd == null) { 4477 mProfiler.handlingProfiling = true; 4478 File file = new File(mProfiler.profileFile); 4479 file.getParentFile().mkdirs(); 4480 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 4481 } 4482 4483 } else { 4484 mInstrumentation = new Instrumentation(); 4485 } 4486 4487 if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { 4488 dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); 4489 } 4490 4491 // Allow disk access during application and provider setup. This could 4492 // block processing ordered broadcasts, but later processing would 4493 // probably end up doing the same disk access. 4494 final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); 4495 try { 4496 // If the app is being launched for full backup or restore, bring it up in 4497 // a restricted environment with the base application class. 4498 Application app = data.info.makeApplication(data.restrictedBackupMode, null); 4499 mInitialApplication = app; 4500 4501 // don't bring up providers in restricted mode; they may depend on the 4502 // app's custom Application class 4503 if (!data.restrictedBackupMode) { 4504 List<ProviderInfo> providers = data.providers; 4505 if (providers != null) { 4506 installContentProviders(app, providers); 4507 // For process that contains content providers, we want to 4508 // ensure that the JIT is enabled "at some point". 4509 mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); 4510 } 4511 } 4512 4513 // Do this after providers, since instrumentation tests generally start their 4514 // test thread at this point, and we don't want that racing. 4515 try { 4516 mInstrumentation.onCreate(data.instrumentationArgs); 4517 } 4518 catch (Exception e) { 4519 throw new RuntimeException( 4520 "Exception thrown in onCreate() of " 4521 + data.instrumentationName + ": " + e.toString(), e); 4522 } 4523 4524 try { 4525 mInstrumentation.callApplicationOnCreate(app); 4526 } catch (Exception e) { 4527 if (!mInstrumentation.onException(app, e)) { 4528 throw new RuntimeException( 4529 "Unable to create application " + app.getClass().getName() 4530 + ": " + e.toString(), e); 4531 } 4532 } 4533 } finally { 4534 StrictMode.setThreadPolicy(savedPolicy); 4535 } 4536 } 4537 4538 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) { 4539 IActivityManager am = ActivityManagerNative.getDefault(); 4540 if (mProfiler.profileFile != null && mProfiler.handlingProfiling 4541 && mProfiler.profileFd == null) { 4542 Debug.stopMethodTracing(); 4543 } 4544 //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault() 4545 // + ", app thr: " + mAppThread); 4546 try { 4547 am.finishInstrumentation(mAppThread, resultCode, results); 4548 } catch (RemoteException ex) { 4549 } 4550 } 4551 4552 private void installContentProviders( 4553 Context context, List<ProviderInfo> providers) { 4554 final ArrayList<IActivityManager.ContentProviderHolder> results = 4555 new ArrayList<IActivityManager.ContentProviderHolder>(); 4556 4557 for (ProviderInfo cpi : providers) { 4558 if (DEBUG_PROVIDER) { 4559 StringBuilder buf = new StringBuilder(128); 4560 buf.append("Pub "); 4561 buf.append(cpi.authority); 4562 buf.append(": "); 4563 buf.append(cpi.name); 4564 Log.i(TAG, buf.toString()); 4565 } 4566 IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi, 4567 false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/); 4568 if (cph != null) { 4569 cph.noReleaseNeeded = true; 4570 results.add(cph); 4571 } 4572 } 4573 4574 try { 4575 ActivityManagerNative.getDefault().publishContentProviders( 4576 getApplicationThread(), results); 4577 } catch (RemoteException ex) { 4578 } 4579 } 4580 4581 public final IContentProvider acquireProvider( 4582 Context c, String auth, int userId, boolean stable) { 4583 final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); 4584 if (provider != null) { 4585 return provider; 4586 } 4587 4588 // There is a possible race here. Another thread may try to acquire 4589 // the same provider at the same time. When this happens, we want to ensure 4590 // that the first one wins. 4591 // Note that we cannot hold the lock while acquiring and installing the 4592 // provider since it might take a long time to run and it could also potentially 4593 // be re-entrant in the case where the provider is in the same process. 4594 IActivityManager.ContentProviderHolder holder = null; 4595 try { 4596 holder = ActivityManagerNative.getDefault().getContentProvider( 4597 getApplicationThread(), auth, userId, stable); 4598 } catch (RemoteException ex) { 4599 } 4600 if (holder == null) { 4601 Slog.e(TAG, "Failed to find provider info for " + auth); 4602 return null; 4603 } 4604 4605 // Install provider will increment the reference count for us, and break 4606 // any ties in the race. 4607 holder = installProvider(c, holder, holder.info, 4608 true /*noisy*/, holder.noReleaseNeeded, stable); 4609 return holder.provider; 4610 } 4611 4612 private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) { 4613 if (stable) { 4614 prc.stableCount += 1; 4615 if (prc.stableCount == 1) { 4616 // We are acquiring a new stable reference on the provider. 4617 int unstableDelta; 4618 if (prc.removePending) { 4619 // We have a pending remove operation, which is holding the 4620 // last unstable reference. At this point we are converting 4621 // that unstable reference to our new stable reference. 4622 unstableDelta = -1; 4623 // Cancel the removal of the provider. 4624 if (DEBUG_PROVIDER) { 4625 Slog.v(TAG, "incProviderRef: stable " 4626 + "snatched provider from the jaws of death"); 4627 } 4628 prc.removePending = false; 4629 // There is a race! It fails to remove the message, which 4630 // will be handled in completeRemoveProvider(). 4631 mH.removeMessages(H.REMOVE_PROVIDER, prc); 4632 } else { 4633 unstableDelta = 0; 4634 } 4635 try { 4636 if (DEBUG_PROVIDER) { 4637 Slog.v(TAG, "incProviderRef Now stable - " 4638 + prc.holder.info.name + ": unstableDelta=" 4639 + unstableDelta); 4640 } 4641 ActivityManagerNative.getDefault().refContentProvider( 4642 prc.holder.connection, 1, unstableDelta); 4643 } catch (RemoteException e) { 4644 //do nothing content provider object is dead any way 4645 } 4646 } 4647 } else { 4648 prc.unstableCount += 1; 4649 if (prc.unstableCount == 1) { 4650 // We are acquiring a new unstable reference on the provider. 4651 if (prc.removePending) { 4652 // Oh look, we actually have a remove pending for the 4653 // provider, which is still holding the last unstable 4654 // reference. We just need to cancel that to take new 4655 // ownership of the reference. 4656 if (DEBUG_PROVIDER) { 4657 Slog.v(TAG, "incProviderRef: unstable " 4658 + "snatched provider from the jaws of death"); 4659 } 4660 prc.removePending = false; 4661 mH.removeMessages(H.REMOVE_PROVIDER, prc); 4662 } else { 4663 // First unstable ref, increment our count in the 4664 // activity manager. 4665 try { 4666 if (DEBUG_PROVIDER) { 4667 Slog.v(TAG, "incProviderRef: Now unstable - " 4668 + prc.holder.info.name); 4669 } 4670 ActivityManagerNative.getDefault().refContentProvider( 4671 prc.holder.connection, 0, 1); 4672 } catch (RemoteException e) { 4673 //do nothing content provider object is dead any way 4674 } 4675 } 4676 } 4677 } 4678 } 4679 4680 public final IContentProvider acquireExistingProvider( 4681 Context c, String auth, int userId, boolean stable) { 4682 synchronized (mProviderMap) { 4683 final ProviderKey key = new ProviderKey(auth, userId); 4684 final ProviderClientRecord pr = mProviderMap.get(key); 4685 if (pr == null) { 4686 return null; 4687 } 4688 4689 IContentProvider provider = pr.mProvider; 4690 IBinder jBinder = provider.asBinder(); 4691 if (!jBinder.isBinderAlive()) { 4692 // The hosting process of the provider has died; we can't 4693 // use this one. 4694 Log.i(TAG, "Acquiring provider " + auth + " for user " + userId 4695 + ": existing object's process dead"); 4696 handleUnstableProviderDiedLocked(jBinder, true); 4697 return null; 4698 } 4699 4700 // Only increment the ref count if we have one. If we don't then the 4701 // provider is not reference counted and never needs to be released. 4702 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 4703 if (prc != null) { 4704 incProviderRefLocked(prc, stable); 4705 } 4706 return provider; 4707 } 4708 } 4709 4710 public final boolean releaseProvider(IContentProvider provider, boolean stable) { 4711 if (provider == null) { 4712 return false; 4713 } 4714 4715 IBinder jBinder = provider.asBinder(); 4716 synchronized (mProviderMap) { 4717 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 4718 if (prc == null) { 4719 // The provider has no ref count, no release is needed. 4720 return false; 4721 } 4722 4723 boolean lastRef = false; 4724 if (stable) { 4725 if (prc.stableCount == 0) { 4726 if (DEBUG_PROVIDER) Slog.v(TAG, 4727 "releaseProvider: stable ref count already 0, how?"); 4728 return false; 4729 } 4730 prc.stableCount -= 1; 4731 if (prc.stableCount == 0) { 4732 // What we do at this point depends on whether there are 4733 // any unstable refs left: if there are, we just tell the 4734 // activity manager to decrement its stable count; if there 4735 // aren't, we need to enqueue this provider to be removed, 4736 // and convert to holding a single unstable ref while 4737 // doing so. 4738 lastRef = prc.unstableCount == 0; 4739 try { 4740 if (DEBUG_PROVIDER) { 4741 Slog.v(TAG, "releaseProvider: No longer stable w/lastRef=" 4742 + lastRef + " - " + prc.holder.info.name); 4743 } 4744 ActivityManagerNative.getDefault().refContentProvider( 4745 prc.holder.connection, -1, lastRef ? 1 : 0); 4746 } catch (RemoteException e) { 4747 //do nothing content provider object is dead any way 4748 } 4749 } 4750 } else { 4751 if (prc.unstableCount == 0) { 4752 if (DEBUG_PROVIDER) Slog.v(TAG, 4753 "releaseProvider: unstable ref count already 0, how?"); 4754 return false; 4755 } 4756 prc.unstableCount -= 1; 4757 if (prc.unstableCount == 0) { 4758 // If this is the last reference, we need to enqueue 4759 // this provider to be removed instead of telling the 4760 // activity manager to remove it at this point. 4761 lastRef = prc.stableCount == 0; 4762 if (!lastRef) { 4763 try { 4764 if (DEBUG_PROVIDER) { 4765 Slog.v(TAG, "releaseProvider: No longer unstable - " 4766 + prc.holder.info.name); 4767 } 4768 ActivityManagerNative.getDefault().refContentProvider( 4769 prc.holder.connection, 0, -1); 4770 } catch (RemoteException e) { 4771 //do nothing content provider object is dead any way 4772 } 4773 } 4774 } 4775 } 4776 4777 if (lastRef) { 4778 if (!prc.removePending) { 4779 // Schedule the actual remove asynchronously, since we don't know the context 4780 // this will be called in. 4781 // TODO: it would be nice to post a delayed message, so 4782 // if we come back and need the same provider quickly 4783 // we will still have it available. 4784 if (DEBUG_PROVIDER) { 4785 Slog.v(TAG, "releaseProvider: Enqueueing pending removal - " 4786 + prc.holder.info.name); 4787 } 4788 prc.removePending = true; 4789 Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc); 4790 mH.sendMessage(msg); 4791 } else { 4792 Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name); 4793 } 4794 } 4795 return true; 4796 } 4797 } 4798 4799 final void completeRemoveProvider(ProviderRefCount prc) { 4800 synchronized (mProviderMap) { 4801 if (!prc.removePending) { 4802 // There was a race! Some other client managed to acquire 4803 // the provider before the removal was completed. 4804 // Abort the removal. We will do it later. 4805 if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, " 4806 + "provider still in use"); 4807 return; 4808 } 4809 4810 // More complicated race!! Some client managed to acquire the 4811 // provider and release it before the removal was completed. 4812 // Continue the removal, and abort the next remove message. 4813 prc.removePending = false; 4814 4815 final IBinder jBinder = prc.holder.provider.asBinder(); 4816 ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder); 4817 if (existingPrc == prc) { 4818 mProviderRefCountMap.remove(jBinder); 4819 } 4820 4821 for (int i=mProviderMap.size()-1; i>=0; i--) { 4822 ProviderClientRecord pr = mProviderMap.valueAt(i); 4823 IBinder myBinder = pr.mProvider.asBinder(); 4824 if (myBinder == jBinder) { 4825 mProviderMap.removeAt(i); 4826 } 4827 } 4828 } 4829 4830 try { 4831 if (DEBUG_PROVIDER) { 4832 Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative." 4833 + "removeContentProvider(" + prc.holder.info.name + ")"); 4834 } 4835 ActivityManagerNative.getDefault().removeContentProvider( 4836 prc.holder.connection, false); 4837 } catch (RemoteException e) { 4838 //do nothing content provider object is dead any way 4839 } 4840 } 4841 4842 final void handleUnstableProviderDied(IBinder provider, boolean fromClient) { 4843 synchronized (mProviderMap) { 4844 handleUnstableProviderDiedLocked(provider, fromClient); 4845 } 4846 } 4847 4848 final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) { 4849 ProviderRefCount prc = mProviderRefCountMap.get(provider); 4850 if (prc != null) { 4851 if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider " 4852 + provider + " " + prc.holder.info.name); 4853 mProviderRefCountMap.remove(provider); 4854 for (int i=mProviderMap.size()-1; i>=0; i--) { 4855 ProviderClientRecord pr = mProviderMap.valueAt(i); 4856 if (pr != null && pr.mProvider.asBinder() == provider) { 4857 Slog.i(TAG, "Removing dead content provider:" + pr.mProvider.toString()); 4858 mProviderMap.removeAt(i); 4859 } 4860 } 4861 4862 if (fromClient) { 4863 // We found out about this due to execution in our client 4864 // code. Tell the activity manager about it now, to ensure 4865 // that the next time we go to do anything with the provider 4866 // it knows it is dead (so we don't race with its death 4867 // notification). 4868 try { 4869 ActivityManagerNative.getDefault().unstableProviderDied( 4870 prc.holder.connection); 4871 } catch (RemoteException e) { 4872 //do nothing content provider object is dead any way 4873 } 4874 } 4875 } 4876 } 4877 4878 final void appNotRespondingViaProvider(IBinder provider) { 4879 synchronized (mProviderMap) { 4880 ProviderRefCount prc = mProviderRefCountMap.get(provider); 4881 if (prc != null) { 4882 try { 4883 ActivityManagerNative.getDefault() 4884 .appNotRespondingViaProvider(prc.holder.connection); 4885 } catch (RemoteException e) { 4886 } 4887 } 4888 } 4889 } 4890 4891 private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider, 4892 ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) { 4893 final String auths[] = PATTERN_SEMICOLON.split(holder.info.authority); 4894 final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid); 4895 4896 final ProviderClientRecord pcr = new ProviderClientRecord( 4897 auths, provider, localProvider, holder); 4898 for (String auth : auths) { 4899 final ProviderKey key = new ProviderKey(auth, userId); 4900 final ProviderClientRecord existing = mProviderMap.get(key); 4901 if (existing != null) { 4902 Slog.w(TAG, "Content provider " + pcr.mHolder.info.name 4903 + " already published as " + auth); 4904 } else { 4905 mProviderMap.put(key, pcr); 4906 } 4907 } 4908 return pcr; 4909 } 4910 4911 /** 4912 * Installs the provider. 4913 * 4914 * Providers that are local to the process or that come from the system server 4915 * may be installed permanently which is indicated by setting noReleaseNeeded to true. 4916 * Other remote providers are reference counted. The initial reference count 4917 * for all reference counted providers is one. Providers that are not reference 4918 * counted do not have a reference count (at all). 4919 * 4920 * This method detects when a provider has already been installed. When this happens, 4921 * it increments the reference count of the existing provider (if appropriate) 4922 * and returns the existing provider. This can happen due to concurrent 4923 * attempts to acquire the same provider. 4924 */ 4925 private IActivityManager.ContentProviderHolder installProvider(Context context, 4926 IActivityManager.ContentProviderHolder holder, ProviderInfo info, 4927 boolean noisy, boolean noReleaseNeeded, boolean stable) { 4928 ContentProvider localProvider = null; 4929 IContentProvider provider; 4930 if (holder == null || holder.provider == null) { 4931 if (DEBUG_PROVIDER || noisy) { 4932 Slog.d(TAG, "Loading provider " + info.authority + ": " 4933 + info.name); 4934 } 4935 Context c = null; 4936 ApplicationInfo ai = info.applicationInfo; 4937 if (context.getPackageName().equals(ai.packageName)) { 4938 c = context; 4939 } else if (mInitialApplication != null && 4940 mInitialApplication.getPackageName().equals(ai.packageName)) { 4941 c = mInitialApplication; 4942 } else { 4943 try { 4944 c = context.createPackageContext(ai.packageName, 4945 Context.CONTEXT_INCLUDE_CODE); 4946 } catch (PackageManager.NameNotFoundException e) { 4947 // Ignore 4948 } 4949 } 4950 if (c == null) { 4951 Slog.w(TAG, "Unable to get context for package " + 4952 ai.packageName + 4953 " while loading content provider " + 4954 info.name); 4955 return null; 4956 } 4957 try { 4958 final java.lang.ClassLoader cl = c.getClassLoader(); 4959 localProvider = (ContentProvider)cl. 4960 loadClass(info.name).newInstance(); 4961 provider = localProvider.getIContentProvider(); 4962 if (provider == null) { 4963 Slog.e(TAG, "Failed to instantiate class " + 4964 info.name + " from sourceDir " + 4965 info.applicationInfo.sourceDir); 4966 return null; 4967 } 4968 if (DEBUG_PROVIDER) Slog.v( 4969 TAG, "Instantiating local provider " + info.name); 4970 // XXX Need to create the correct context for this provider. 4971 localProvider.attachInfo(c, info); 4972 } catch (java.lang.Exception e) { 4973 if (!mInstrumentation.onException(null, e)) { 4974 throw new RuntimeException( 4975 "Unable to get provider " + info.name 4976 + ": " + e.toString(), e); 4977 } 4978 return null; 4979 } 4980 } else { 4981 provider = holder.provider; 4982 if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": " 4983 + info.name); 4984 } 4985 4986 IActivityManager.ContentProviderHolder retHolder; 4987 4988 synchronized (mProviderMap) { 4989 if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider 4990 + " / " + info.name); 4991 IBinder jBinder = provider.asBinder(); 4992 if (localProvider != null) { 4993 ComponentName cname = new ComponentName(info.packageName, info.name); 4994 ProviderClientRecord pr = mLocalProvidersByName.get(cname); 4995 if (pr != null) { 4996 if (DEBUG_PROVIDER) { 4997 Slog.v(TAG, "installProvider: lost the race, " 4998 + "using existing local provider"); 4999 } 5000 provider = pr.mProvider; 5001 } else { 5002 holder = new IActivityManager.ContentProviderHolder(info); 5003 holder.provider = provider; 5004 holder.noReleaseNeeded = true; 5005 pr = installProviderAuthoritiesLocked(provider, localProvider, holder); 5006 mLocalProviders.put(jBinder, pr); 5007 mLocalProvidersByName.put(cname, pr); 5008 } 5009 retHolder = pr.mHolder; 5010 } else { 5011 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 5012 if (prc != null) { 5013 if (DEBUG_PROVIDER) { 5014 Slog.v(TAG, "installProvider: lost the race, updating ref count"); 5015 } 5016 // We need to transfer our new reference to the existing 5017 // ref count, releasing the old one... but only if 5018 // release is needed (that is, it is not running in the 5019 // system process). 5020 if (!noReleaseNeeded) { 5021 incProviderRefLocked(prc, stable); 5022 try { 5023 ActivityManagerNative.getDefault().removeContentProvider( 5024 holder.connection, stable); 5025 } catch (RemoteException e) { 5026 //do nothing content provider object is dead any way 5027 } 5028 } 5029 } else { 5030 ProviderClientRecord client = installProviderAuthoritiesLocked( 5031 provider, localProvider, holder); 5032 if (noReleaseNeeded) { 5033 prc = new ProviderRefCount(holder, client, 1000, 1000); 5034 } else { 5035 prc = stable 5036 ? new ProviderRefCount(holder, client, 1, 0) 5037 : new ProviderRefCount(holder, client, 0, 1); 5038 } 5039 mProviderRefCountMap.put(jBinder, prc); 5040 } 5041 retHolder = prc.holder; 5042 } 5043 } 5044 5045 return retHolder; 5046 } 5047 5048 private void attach(boolean system) { 5049 sCurrentActivityThread = this; 5050 mSystemThread = system; 5051 if (!system) { 5052 ViewRootImpl.addFirstDrawHandler(new Runnable() { 5053 @Override 5054 public void run() { 5055 ensureJitEnabled(); 5056 } 5057 }); 5058 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", 5059 UserHandle.myUserId()); 5060 RuntimeInit.setApplicationObject(mAppThread.asBinder()); 5061 final IActivityManager mgr = ActivityManagerNative.getDefault(); 5062 try { 5063 mgr.attachApplication(mAppThread); 5064 } catch (RemoteException ex) { 5065 // Ignore 5066 } 5067 // Watch for getting close to heap limit. 5068 BinderInternal.addGcWatcher(new Runnable() { 5069 @Override public void run() { 5070 if (!mSomeActivitiesChanged) { 5071 return; 5072 } 5073 Runtime runtime = Runtime.getRuntime(); 5074 long dalvikMax = runtime.maxMemory(); 5075 long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); 5076 if (dalvikUsed > ((3*dalvikMax)/4)) { 5077 if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) 5078 + " total=" + (runtime.totalMemory()/1024) 5079 + " used=" + (dalvikUsed/1024)); 5080 mSomeActivitiesChanged = false; 5081 try { 5082 mgr.releaseSomeActivities(mAppThread); 5083 } catch (RemoteException e) { 5084 } 5085 } 5086 } 5087 }); 5088 } else { 5089 // Don't set application object here -- if the system crashes, 5090 // we can't display an alert, we just want to die die die. 5091 android.ddm.DdmHandleAppName.setAppName("system_process", 5092 UserHandle.myUserId()); 5093 try { 5094 mInstrumentation = new Instrumentation(); 5095 ContextImpl context = ContextImpl.createAppContext( 5096 this, getSystemContext().mPackageInfo); 5097 mInitialApplication = context.mPackageInfo.makeApplication(true, null); 5098 mInitialApplication.onCreate(); 5099 } catch (Exception e) { 5100 throw new RuntimeException( 5101 "Unable to instantiate Application():" + e.toString(), e); 5102 } 5103 } 5104 5105 // add dropbox logging to libcore 5106 DropBox.setReporter(new DropBoxReporter()); 5107 5108 ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { 5109 @Override 5110 public void onConfigurationChanged(Configuration newConfig) { 5111 synchronized (mResourcesManager) { 5112 // We need to apply this change to the resources 5113 // immediately, because upon returning the view 5114 // hierarchy will be informed about it. 5115 if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) { 5116 // This actually changed the resources! Tell 5117 // everyone about it. 5118 if (mPendingConfiguration == null || 5119 mPendingConfiguration.isOtherSeqNewer(newConfig)) { 5120 mPendingConfiguration = newConfig; 5121 5122 sendMessage(H.CONFIGURATION_CHANGED, newConfig); 5123 } 5124 } 5125 } 5126 } 5127 @Override 5128 public void onLowMemory() { 5129 } 5130 @Override 5131 public void onTrimMemory(int level) { 5132 } 5133 }); 5134 } 5135 5136 public static ActivityThread systemMain() { 5137 // The system process on low-memory devices do not get to use hardware 5138 // accelerated drawing, since this can add too much overhead to the 5139 // process. 5140 if (!ActivityManager.isHighEndGfx()) { 5141 HardwareRenderer.disable(true); 5142 } else { 5143 HardwareRenderer.enableForegroundTrimming(); 5144 } 5145 ActivityThread thread = new ActivityThread(); 5146 thread.attach(true); 5147 return thread; 5148 } 5149 5150 public final void installSystemProviders(List<ProviderInfo> providers) { 5151 if (providers != null) { 5152 installContentProviders(mInitialApplication, providers); 5153 } 5154 } 5155 5156 public int getIntCoreSetting(String key, int defaultValue) { 5157 synchronized (mResourcesManager) { 5158 if (mCoreSettings != null) { 5159 return mCoreSettings.getInt(key, defaultValue); 5160 } 5161 return defaultValue; 5162 } 5163 } 5164 5165 private static class EventLoggingReporter implements EventLogger.Reporter { 5166 @Override 5167 public void report (int code, Object... list) { 5168 EventLog.writeEvent(code, list); 5169 } 5170 } 5171 5172 private class DropBoxReporter implements DropBox.Reporter { 5173 5174 private DropBoxManager dropBox; 5175 5176 public DropBoxReporter() { 5177 dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE); 5178 } 5179 5180 @Override 5181 public void addData(String tag, byte[] data, int flags) { 5182 dropBox.addData(tag, data, flags); 5183 } 5184 5185 @Override 5186 public void addText(String tag, String data) { 5187 dropBox.addText(tag, data); 5188 } 5189 } 5190 5191 public static void main(String[] args) { 5192 SamplingProfilerIntegration.start(); 5193 5194 // CloseGuard defaults to true and can be quite spammy. We 5195 // disable it here, but selectively enable it later (via 5196 // StrictMode) on debug builds, but using DropBox, not logs. 5197 CloseGuard.setEnabled(false); 5198 5199 Environment.initForCurrentUser(); 5200 5201 // Set the reporter for event logging in libcore 5202 EventLogger.setReporter(new EventLoggingReporter()); 5203 5204 Security.addProvider(new AndroidKeyStoreProvider()); 5205 5206 // Make sure TrustedCertificateStore looks in the right place for CA certificates 5207 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); 5208 TrustedCertificateStore.setDefaultUserDirectory(configDir); 5209 5210 Process.setArgV0("<pre-initialized>"); 5211 5212 Looper.prepareMainLooper(); 5213 5214 ActivityThread thread = new ActivityThread(); 5215 thread.attach(false); 5216 5217 if (sMainThreadHandler == null) { 5218 sMainThreadHandler = thread.getHandler(); 5219 } 5220 5221 AsyncTask.init(); 5222 5223 if (false) { 5224 Looper.myLooper().setMessageLogging(new 5225 LogPrinter(Log.DEBUG, "ActivityThread")); 5226 } 5227 5228 Looper.loop(); 5229 5230 throw new RuntimeException("Main thread loop unexpectedly exited"); 5231 } 5232} 5233