深入理解android的UI更新机制
深入理解android的UI更新机制
由问题开始:
如何更新android UI?
可以通过如下方法:
- 在主线程里直接操作UI控件。
- handler.post(Runnable)
- runOnUiThread(Runnable action)
- View.post(Runnable)
- Handler.sendMessage,在Handler handleMessage()方法里执行。
大家基本都知道这些方法,那么为什么要这么做?
我们把几个方法的源码都看一遍吧。
- 主线程,这个好像不能说为什么,他就是可以更新,就是这么任性。其实是有原因的。后面说。
- handler.post(Runnable)
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); }
- runOnUiThread(Runnable action)
public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action); } else { action.run(); } }
- View.post(Runnable)
public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); } // Postpone the runnable until we know on which thread it needs to run. // Assume that the runnable will be successfully placed after attach. getRunQueue().post(action); return true; }
- Handler.sendMessage,在Handler handleMessage()方法里执行。
挨个看完源码,你会发现,其实他们最后的实现都是通过Handler来的。
那现在问题来了,Handler 是什么?怎么工作的?
大家以上会想到 Handler Looper MessageQueue
bala bala 一通。
Handler Looper MessageQueue 这三个东西是什么,这里不去讲了,工作过程网上也有很多很多,但总感觉80%的人是没有正直搞明白其中原理。
还是从提问题来说:
1.UI线程在不断刷新界面,他是怎么做的?是死循环吗?怎么开启的?Activity生命周期是怎么调用的?
2.Looper是一个消息循环,他是怎么循环的,为什么不阻塞主线程?Looper属于主线程吗?
先看Looper的源码吧。比较关键。
/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.os; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.LooperProto; import android.util.Log; import android.util.Printer; import android.util.Slog; import android.util.proto.ProtoOutputStream; public final class Looper { private static final String TAG = "Looper"; static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static Looper sMainLooper; // guarded by Looper.class final MessageQueue mQueue; final Thread mThread; private Printer mLogging; private long mTraceTag; private long mSlowDispatchThresholdMs; public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } } /** * Returns the application's main looper, which lives in the main thread of the application. */ public static Looper getMainLooper() { synchronized (Looper.class) { return sMainLooper; } } public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs; final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); final long end; try { msg.target.dispatchMessage(msg); end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (slowDispatchThresholdMs > 0) { final long time = end - start; if (time > slowDispatchThresholdMs) { Slog.w(TAG, "Dispatch took " + time + "ms on " + Thread.currentThread().getName() + ", h=" + msg.target + " cb=" + msg.callback + " msg=" + msg.what); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); } } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static @Nullable Looper myLooper() { return sThreadLocal.get(); } /** * Return the {@link MessageQueue} object associated with the current * thread. This must be called from a thread running a Looper, or a * NullPointerException will be thrown. */ public static @NonNull MessageQueue myQueue() { return myLooper().mQueue; } private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } /** * Returns true if the current thread is this looper's thread. */ public boolean isCurrentThread() { return Thread.currentThread() == mThread; } public void setMessageLogging(@Nullable Printer printer) { mLogging = printer; } /** {@hide} */ public void setTraceTag(long traceTag) { mTraceTag = traceTag; } /** {@hide} */ public void setSlowDispatchThresholdMs(long slowDispatchThresholdMs) { mSlowDispatchThresholdMs = slowDispatchThresholdMs; } public void quit() { mQueue.quit(false); } public void quitSafely() { mQueue.quit(true); } /** * Gets the Thread associated with this Looper. * * @return The looper's thread. */ public @NonNull Thread getThread() { return mThread; } /** * Gets this looper's message queue. * * @return The looper's message queue. */ public @NonNull MessageQueue getQueue() { return mQueue; } /** * Dumps the state of the looper for debugging purposes. * * @param pw A printer to receive the contents of the dump. * @param prefix A prefix to prepend to each line which is printed. */ public void dump(@NonNull Printer pw, @NonNull String prefix) { pw.println(prefix + toString()); mQueue.dump(pw, prefix + " ", null); } /** * Dumps the state of the looper for debugging purposes. * * @param pw A printer to receive the contents of the dump. * @param prefix A prefix to prepend to each line which is printed. * @param handler Only dump messages for this Handler. * @hide */ public void dump(@NonNull Printer pw, @NonNull String prefix, Handler handler) { pw.println(prefix + toString()); mQueue.dump(pw, prefix + " ", handler); } /** @hide */ public void writeToProto(ProtoOutputStream proto, long fieldId) { final long looperToken = proto.start(fieldId); proto.write(LooperProto.THREAD_NAME, mThread.getName()); proto.write(LooperProto.THREAD_ID, mThread.getId()); proto.write(LooperProto.IDENTITY_HASH_CODE, System.identityHashCode(this)); mQueue.writeToProto(proto, LooperProto.QUEUE); proto.end(looperToken); } @Override public String toString() { return "Looper (" + mThread.getName() + ", tid " + mThread.getId() + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}"; } }
这个类开头注释给了一个HandlerThread的例子,告诉你怎么用这个Looper .
同时会发现构造方法是私有的,不能直接调用。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
分析Looper文章很多;主要内容是:一个线程只能起一个Looper。looper怎么运行起来的。
来看看loop()方法吧。
public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs; final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); final long end; try { msg.target.dispatchMessage(msg); end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (slowDispatchThresholdMs > 0) { final long time = end - start; if (time > slowDispatchThresholdMs) { Slog.w(TAG, "Dispatch took " + time + "ms on " + Thread.currentThread().getName() + ", h=" + msg.target + " cb=" + msg.callback + " msg=" + msg.what); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); } }
最关键的代码如下:
一个列循环,调用queue.next();msg为空时返回。
那么我们的消息队列里面,不是永远都有消息的啊?那怎么不退出呢?
带着这个问题,我们再看看ActivityThread ;

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

queue.next()方法执行的时候如果没有消息,它会阻塞。等待消息到来。所以就解释了之前loop方法里那个for循环为什么不会退出。
在H.handleMessage(msg)方法中,根据接收到不同的msg,执行相应的生命周期。
比如收到msg=H.LAUNCH_ACTIVITY,则调用ActivityThread.handleLaunchActivity()方法,最终会通过反射机制,创建Activity实例,然后再执行Activity.onCreate()等方法;
再比如收到msg=H.PAUSE_ACTIVITY,则调用ActivityThread.handlePauseActivity()方法,最终会执行Activity.onPause()等方法。
Thread thread = new Thread(new Runnable() { @Override public void run() { Looper.prepare(); threadhandler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { super.handleMessage(msg); tvHello = findViewById(R.id.tv_hello); tvHello.setText("thread tv operation"); } }; Looper.loop(); } });
以上代码是可以执行成功的。
但你仔细分析,这代码跟所谓的主线程一点关系也没有。仅仅是一个线程加Looper而矣,怎么就可以了呢?
到此得出结论,能更新UI的并不是主线程的专利,android其实是利用的了handler Looper MessageQueue这套Lunux的机制。
handler Looper MessageQueue关不是专为主线程设计的一套东西。到此我们才能真正理解androidUI的更新机制了。
验证一下结果。看下图
当前线程正在操作控件,但并不是主线程。
在代码中,我打了断点,线程wait了,但程序中的另一个控件progressbar却一直还是在转的。所以通过Looper机制让非UI线程(主线程)去处理一些ui相关代码非常有意义。
其实H类处理事务,也是通Binder起了线程去处理的。详细的可以深入研究源码。
这篇文章本来想一点点引导去分析然后得出结果。发现在时间不允许。过程有点乱。表达得不太好。或许不太准确,有问题欢迎留交流。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)