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