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