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