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