ActivityThread.java revision 829829ca2c1804147dd42b106e5d7f1efe99a1f9
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.proto.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    /** Called from {@link LocalActivityManager}. */
4037    final void performStopActivity(IBinder token, boolean saveState, String reason) {
4038        ActivityClientRecord r = mActivities.get(token);
4039        performStopActivityInner(r, null /* stopInfo */, false /* keepShown */, saveState,
4040                false /* finalStateRequest */, reason);
4041    }
4042
4043    private static final class ProviderRefCount {
4044        public final ContentProviderHolder holder;
4045        public final ProviderClientRecord client;
4046        public int stableCount;
4047        public int unstableCount;
4048
4049        // When this is set, the stable and unstable ref counts are 0 and
4050        // we have a pending operation scheduled to remove the ref count
4051        // from the activity manager.  On the activity manager we are still
4052        // holding an unstable ref, though it is not reflected in the counts
4053        // here.
4054        public boolean removePending;
4055
4056        ProviderRefCount(ContentProviderHolder inHolder,
4057                ProviderClientRecord inClient, int sCount, int uCount) {
4058            holder = inHolder;
4059            client = inClient;
4060            stableCount = sCount;
4061            unstableCount = uCount;
4062        }
4063    }
4064
4065    /**
4066     * Core implementation of stopping an activity.  Note this is a little
4067     * tricky because the server's meaning of stop is slightly different
4068     * than our client -- for the server, stop means to save state and give
4069     * it the result when it is done, but the window may still be visible.
4070     * For the client, we want to call onStop()/onStart() to indicate when
4071     * the activity's UI visibility changes.
4072     * @param r Target activity client record.
4073     * @param info Action that will report activity stop to server.
4074     * @param keepShown Flag indicating whether the activity is still shown.
4075     * @param saveState Flag indicating whether the activity state should be saved.
4076     * @param finalStateRequest Flag indicating if this call is handling final lifecycle state
4077     *                          request for a transaction.
4078     * @param reason Reason for performing this operation.
4079     */
4080    private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown,
4081            boolean saveState, boolean finalStateRequest, String reason) {
4082        if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
4083        if (r != null) {
4084            if (!keepShown && r.stopped) {
4085                if (r.activity.mFinished) {
4086                    // If we are finishing, we won't call onResume() in certain
4087                    // cases.  So here we likewise don't want to call onStop()
4088                    // if the activity isn't resumed.
4089                    return;
4090                }
4091                if (!finalStateRequest) {
4092                    final RuntimeException e = new RuntimeException(
4093                            "Performing stop of activity that is already stopped: "
4094                                    + r.intent.getComponent().toShortString());
4095                    Slog.e(TAG, e.getMessage(), e);
4096                    Slog.e(TAG, r.getStateString());
4097                }
4098            }
4099
4100            // One must first be paused before stopped...
4101            performPauseActivityIfNeeded(r, reason);
4102
4103            if (info != null) {
4104                try {
4105                    // First create a thumbnail for the activity...
4106                    // For now, don't create the thumbnail here; we are
4107                    // doing that by doing a screen snapshot.
4108                    info.setDescription(r.activity.onCreateDescription());
4109                } catch (Exception e) {
4110                    if (!mInstrumentation.onException(r.activity, e)) {
4111                        throw new RuntimeException(
4112                                "Unable to save state of activity "
4113                                + r.intent.getComponent().toShortString()
4114                                + ": " + e.toString(), e);
4115                    }
4116                }
4117            }
4118
4119            if (!keepShown) {
4120                callActivityOnStop(r, saveState, reason);
4121            }
4122        }
4123    }
4124
4125    /**
4126     * Calls {@link Activity#onStop()} and {@link Activity#onSaveInstanceState(Bundle)}, and updates
4127     * the client record's state.
4128     * All calls to stop an activity must be done through this method to make sure that
4129     * {@link Activity#onSaveInstanceState(Bundle)} is also executed in the same call.
4130     */
4131    private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {
4132        // Before P onSaveInstanceState was called before onStop, starting with P it's
4133        // called after. Before Honeycomb state was always saved before onPause.
4134        final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null
4135                && !r.isPreHoneycomb();
4136        final boolean isPreP = r.isPreP();
4137        if (shouldSaveState && isPreP) {
4138            callActivityOnSaveInstanceState(r);
4139        }
4140
4141        try {
4142            r.activity.performStop(false /*preserveWindow*/, reason);
4143        } catch (SuperNotCalledException e) {
4144            throw e;
4145        } catch (Exception e) {
4146            if (!mInstrumentation.onException(r.activity, e)) {
4147                throw new RuntimeException(
4148                        "Unable to stop activity "
4149                                + r.intent.getComponent().toShortString()
4150                                + ": " + e.toString(), e);
4151            }
4152        }
4153        r.setState(ON_STOP);
4154
4155        if (shouldSaveState && !isPreP) {
4156            callActivityOnSaveInstanceState(r);
4157        }
4158    }
4159
4160    private void updateVisibility(ActivityClientRecord r, boolean show) {
4161        View v = r.activity.mDecor;
4162        if (v != null) {
4163            if (show) {
4164                if (!r.activity.mVisibleFromServer) {
4165                    r.activity.mVisibleFromServer = true;
4166                    mNumVisibleActivities++;
4167                    if (r.activity.mVisibleFromClient) {
4168                        r.activity.makeVisible();
4169                    }
4170                }
4171                if (r.newConfig != null) {
4172                    performConfigurationChangedForActivity(r, r.newConfig);
4173                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
4174                            + r.activityInfo.name + " with new config "
4175                            + r.activity.mCurrentConfig);
4176                    r.newConfig = null;
4177                }
4178            } else {
4179                if (r.activity.mVisibleFromServer) {
4180                    r.activity.mVisibleFromServer = false;
4181                    mNumVisibleActivities--;
4182                    v.setVisibility(View.INVISIBLE);
4183                }
4184            }
4185        }
4186    }
4187
4188    @Override
4189    public void handleStopActivity(IBinder token, boolean show, int configChanges,
4190            PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) {
4191        final ActivityClientRecord r = mActivities.get(token);
4192        r.activity.mConfigChangeFlags |= configChanges;
4193
4194        final StopInfo stopInfo = new StopInfo();
4195        performStopActivityInner(r, stopInfo, show, true /* saveState */, finalStateRequest,
4196                reason);
4197
4198        if (localLOGV) Slog.v(
4199            TAG, "Finishing stop of " + r + ": show=" + show
4200            + " win=" + r.window);
4201
4202        updateVisibility(r, show);
4203
4204        // Make sure any pending writes are now committed.
4205        if (!r.isPreHoneycomb()) {
4206            QueuedWork.waitToFinish();
4207        }
4208
4209        stopInfo.setActivity(r);
4210        stopInfo.setState(r.state);
4211        stopInfo.setPersistentState(r.persistentState);
4212        pendingActions.setStopInfo(stopInfo);
4213        mSomeActivitiesChanged = true;
4214    }
4215
4216    /**
4217     * Schedule the call to tell the activity manager we have stopped.  We don't do this
4218     * immediately, because we want to have a chance for any other pending work (in particular
4219     * memory trim requests) to complete before you tell the activity manager to proceed and allow
4220     * us to go fully into the background.
4221     */
4222    @Override
4223    public void reportStop(PendingTransactionActions pendingActions) {
4224        mH.post(pendingActions.getStopInfo());
4225    }
4226
4227    @Override
4228    public void performRestartActivity(IBinder token, boolean start) {
4229        ActivityClientRecord r = mActivities.get(token);
4230        if (r.stopped) {
4231            r.activity.performRestart(start, "performRestartActivity");
4232            if (start) {
4233                r.setState(ON_START);
4234            }
4235        }
4236    }
4237
4238    @Override
4239    public void handleWindowVisibility(IBinder token, boolean show) {
4240        ActivityClientRecord r = mActivities.get(token);
4241
4242        if (r == null) {
4243            Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
4244            return;
4245        }
4246
4247        if (!show && !r.stopped) {
4248            performStopActivityInner(r, null /* stopInfo */, show, false /* saveState */,
4249                    false /* finalStateRequest */, "handleWindowVisibility");
4250        } else if (show && r.stopped) {
4251            // If we are getting ready to gc after going to the background, well
4252            // we are back active so skip it.
4253            unscheduleGcIdler();
4254
4255            r.activity.performRestart(true /* start */, "handleWindowVisibility");
4256            r.setState(ON_START);
4257        }
4258        if (r.activity.mDecor != null) {
4259            if (false) Slog.v(
4260                TAG, "Handle window " + r + " visibility: " + show);
4261            updateVisibility(r, show);
4262        }
4263        mSomeActivitiesChanged = true;
4264    }
4265
4266    // TODO: This method should be changed to use {@link #performStopActivityInner} to perform to
4267    // stop operation on the activity to reduce code duplication and the chance of fixing a bug in
4268    // one place and missing the other.
4269    private void handleSleeping(IBinder token, boolean sleeping) {
4270        ActivityClientRecord r = mActivities.get(token);
4271
4272        if (r == null) {
4273            Log.w(TAG, "handleSleeping: no activity for token " + token);
4274            return;
4275        }
4276
4277        if (sleeping) {
4278            if (!r.stopped && !r.isPreHoneycomb()) {
4279                callActivityOnStop(r, true /* saveState */, "sleeping");
4280            }
4281
4282            // Make sure any pending writes are now committed.
4283            if (!r.isPreHoneycomb()) {
4284                QueuedWork.waitToFinish();
4285            }
4286
4287            // Tell activity manager we slept.
4288            try {
4289                ActivityManager.getService().activitySlept(r.token);
4290            } catch (RemoteException ex) {
4291                throw ex.rethrowFromSystemServer();
4292            }
4293        } else {
4294            if (r.stopped && r.activity.mVisibleFromServer) {
4295                r.activity.performRestart(true /* start */, "handleSleeping");
4296                r.setState(ON_START);
4297            }
4298        }
4299    }
4300
4301    private void handleSetCoreSettings(Bundle coreSettings) {
4302        synchronized (mResourcesManager) {
4303            mCoreSettings = coreSettings;
4304        }
4305        onCoreSettingsChange();
4306    }
4307
4308    private void onCoreSettingsChange() {
4309        boolean debugViewAttributes =
4310                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
4311        if (debugViewAttributes != View.mDebugViewAttributes) {
4312            View.mDebugViewAttributes = debugViewAttributes;
4313
4314            // request all activities to relaunch for the changes to take place
4315            relaunchAllActivities();
4316        }
4317    }
4318
4319    private void relaunchAllActivities() {
4320        for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
4321            final Activity activity = entry.getValue().activity;
4322            if (!activity.mFinished) {
4323                handleRelaunchActivityLocally(entry.getKey());
4324            }
4325        }
4326    }
4327
4328    private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
4329        LoadedApk apk = peekPackageInfo(data.pkg, false);
4330        if (apk != null) {
4331            apk.setCompatibilityInfo(data.info);
4332        }
4333        apk = peekPackageInfo(data.pkg, true);
4334        if (apk != null) {
4335            apk.setCompatibilityInfo(data.info);
4336        }
4337        handleConfigurationChanged(mConfiguration, data.info);
4338        WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
4339    }
4340
4341    private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
4342        final int N = results.size();
4343        for (int i=0; i<N; i++) {
4344            ResultInfo ri = results.get(i);
4345            try {
4346                if (ri.mData != null) {
4347                    ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
4348                    ri.mData.prepareToEnterProcess();
4349                }
4350                if (DEBUG_RESULTS) Slog.v(TAG,
4351                        "Delivering result to activity " + r + " : " + ri);
4352                r.activity.dispatchActivityResult(ri.mResultWho,
4353                        ri.mRequestCode, ri.mResultCode, ri.mData);
4354            } catch (Exception e) {
4355                if (!mInstrumentation.onException(r.activity, e)) {
4356                    throw new RuntimeException(
4357                            "Failure delivering result " + ri + " to activity "
4358                            + r.intent.getComponent().toShortString()
4359                            + ": " + e.toString(), e);
4360                }
4361            }
4362        }
4363    }
4364
4365    @Override
4366    public void handleSendResult(IBinder token, List<ResultInfo> results) {
4367        ActivityClientRecord r = mActivities.get(token);
4368        if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
4369        if (r != null) {
4370            final boolean resumed = !r.paused;
4371            if (!r.activity.mFinished && r.activity.mDecor != null
4372                    && r.hideForNow && resumed) {
4373                // We had hidden the activity because it started another
4374                // one...  we have gotten a result back and we are not
4375                // paused, so make sure our window is visible.
4376                updateVisibility(r, true);
4377            }
4378            if (resumed) {
4379                try {
4380                    // Now we are idle.
4381                    r.activity.mCalled = false;
4382                    r.activity.mTemporaryPause = true;
4383                    mInstrumentation.callActivityOnPause(r.activity);
4384                    if (!r.activity.mCalled) {
4385                        throw new SuperNotCalledException(
4386                            "Activity " + r.intent.getComponent().toShortString()
4387                            + " did not call through to super.onPause()");
4388                    }
4389                } catch (SuperNotCalledException e) {
4390                    throw e;
4391                } catch (Exception e) {
4392                    if (!mInstrumentation.onException(r.activity, e)) {
4393                        throw new RuntimeException(
4394                                "Unable to pause activity "
4395                                + r.intent.getComponent().toShortString()
4396                                + ": " + e.toString(), e);
4397                    }
4398                }
4399            }
4400            checkAndBlockForNetworkAccess();
4401            deliverResults(r, results);
4402            if (resumed) {
4403                r.activity.performResume(false, "handleSendResult");
4404                r.activity.mTemporaryPause = false;
4405            }
4406        }
4407    }
4408
4409    /** Core implementation of activity destroy call. */
4410    ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
4411            int configChanges, boolean getNonConfigInstance, String reason) {
4412        ActivityClientRecord r = mActivities.get(token);
4413        Class<? extends Activity> activityClass = null;
4414        if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
4415        if (r != null) {
4416            activityClass = r.activity.getClass();
4417            r.activity.mConfigChangeFlags |= configChanges;
4418            if (finishing) {
4419                r.activity.mFinished = true;
4420            }
4421
4422            performPauseActivityIfNeeded(r, "destroy");
4423
4424            if (!r.stopped) {
4425                callActivityOnStop(r, false /* saveState */, "destroy");
4426            }
4427            if (getNonConfigInstance) {
4428                try {
4429                    r.lastNonConfigurationInstances
4430                            = r.activity.retainNonConfigurationInstances();
4431                } catch (Exception e) {
4432                    if (!mInstrumentation.onException(r.activity, e)) {
4433                        throw new RuntimeException(
4434                                "Unable to retain activity "
4435                                + r.intent.getComponent().toShortString()
4436                                + ": " + e.toString(), e);
4437                    }
4438                }
4439            }
4440            try {
4441                r.activity.mCalled = false;
4442                mInstrumentation.callActivityOnDestroy(r.activity);
4443                if (!r.activity.mCalled) {
4444                    throw new SuperNotCalledException(
4445                        "Activity " + safeToComponentShortString(r.intent) +
4446                        " did not call through to super.onDestroy()");
4447                }
4448                if (r.window != null) {
4449                    r.window.closeAllPanels();
4450                }
4451            } catch (SuperNotCalledException e) {
4452                throw e;
4453            } catch (Exception e) {
4454                if (!mInstrumentation.onException(r.activity, e)) {
4455                    throw new RuntimeException(
4456                            "Unable to destroy activity " + safeToComponentShortString(r.intent)
4457                            + ": " + e.toString(), e);
4458                }
4459            }
4460            r.setState(ON_DESTROY);
4461        }
4462        mActivities.remove(token);
4463        mRecentDestroyedActivities.add(0, new DestroyedActivityInfo(token.hashCode(), reason));
4464
4465        final int recentDestroyedActivitiesSize = mRecentDestroyedActivities.size();
4466        if (recentDestroyedActivitiesSize > MAX_DESTROYED_ACTIVITIES) {
4467            mRecentDestroyedActivities.remove(recentDestroyedActivitiesSize - 1);
4468        }
4469        StrictMode.decrementExpectedActivityCount(activityClass);
4470        return r;
4471    }
4472
4473    private static String safeToComponentShortString(Intent intent) {
4474        ComponentName component = intent.getComponent();
4475        return component == null ? "[Unknown]" : component.toShortString();
4476    }
4477
4478    @Override
4479    public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
4480            boolean getNonConfigInstance, String reason) {
4481        ActivityClientRecord r = performDestroyActivity(token, finishing,
4482                configChanges, getNonConfigInstance, reason);
4483        if (r != null) {
4484            cleanUpPendingRemoveWindows(r, finishing);
4485            WindowManager wm = r.activity.getWindowManager();
4486            View v = r.activity.mDecor;
4487            if (v != null) {
4488                if (r.activity.mVisibleFromServer) {
4489                    mNumVisibleActivities--;
4490                }
4491                IBinder wtoken = v.getWindowToken();
4492                if (r.activity.mWindowAdded) {
4493                    if (r.mPreserveWindow) {
4494                        // Hold off on removing this until the new activity's
4495                        // window is being added.
4496                        r.mPendingRemoveWindow = r.window;
4497                        r.mPendingRemoveWindowManager = wm;
4498                        // We can only keep the part of the view hierarchy that we control,
4499                        // everything else must be removed, because it might not be able to
4500                        // behave properly when activity is relaunching.
4501                        r.window.clearContentView();
4502                    } else {
4503                        wm.removeViewImmediate(v);
4504                    }
4505                }
4506                if (wtoken != null && r.mPendingRemoveWindow == null) {
4507                    WindowManagerGlobal.getInstance().closeAll(wtoken,
4508                            r.activity.getClass().getName(), "Activity");
4509                } else if (r.mPendingRemoveWindow != null) {
4510                    // We're preserving only one window, others should be closed so app views
4511                    // will be detached before the final tear down. It should be done now because
4512                    // some components (e.g. WebView) rely on detach callbacks to perform receiver
4513                    // unregister and other cleanup.
4514                    WindowManagerGlobal.getInstance().closeAllExceptView(token, v,
4515                            r.activity.getClass().getName(), "Activity");
4516                }
4517                r.activity.mDecor = null;
4518            }
4519            if (r.mPendingRemoveWindow == null) {
4520                // If we are delaying the removal of the activity window, then
4521                // we can't clean up all windows here.  Note that we can't do
4522                // so later either, which means any windows that aren't closed
4523                // by the app will leak.  Well we try to warning them a lot
4524                // about leaking windows, because that is a bug, so if they are
4525                // using this recreate facility then they get to live with leaks.
4526                WindowManagerGlobal.getInstance().closeAll(token,
4527                        r.activity.getClass().getName(), "Activity");
4528            }
4529
4530            // Mocked out contexts won't be participating in the normal
4531            // process lifecycle, but if we're running with a proper
4532            // ApplicationContext we need to have it tear down things
4533            // cleanly.
4534            Context c = r.activity.getBaseContext();
4535            if (c instanceof ContextImpl) {
4536                ((ContextImpl) c).scheduleFinalCleanup(
4537                        r.activity.getClass().getName(), "Activity");
4538            }
4539        }
4540        if (finishing) {
4541            try {
4542                ActivityManager.getService().activityDestroyed(token);
4543            } catch (RemoteException ex) {
4544                throw ex.rethrowFromSystemServer();
4545            }
4546        }
4547        mSomeActivitiesChanged = true;
4548    }
4549
4550    @Override
4551    public ActivityClientRecord prepareRelaunchActivity(IBinder token,
4552            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
4553            int configChanges, MergedConfiguration config, boolean preserveWindow) {
4554        ActivityClientRecord target = null;
4555        boolean scheduleRelaunch = false;
4556
4557        synchronized (mResourcesManager) {
4558            for (int i=0; i<mRelaunchingActivities.size(); i++) {
4559                ActivityClientRecord r = mRelaunchingActivities.get(i);
4560                if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + this + ", trying: " + r);
4561                if (r.token == token) {
4562                    target = r;
4563                    if (pendingResults != null) {
4564                        if (r.pendingResults != null) {
4565                            r.pendingResults.addAll(pendingResults);
4566                        } else {
4567                            r.pendingResults = pendingResults;
4568                        }
4569                    }
4570                    if (pendingNewIntents != null) {
4571                        if (r.pendingIntents != null) {
4572                            r.pendingIntents.addAll(pendingNewIntents);
4573                        } else {
4574                            r.pendingIntents = pendingNewIntents;
4575                        }
4576                    }
4577                    break;
4578                }
4579            }
4580
4581            if (target == null) {
4582                if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null");
4583                target = new ActivityClientRecord();
4584                target.token = token;
4585                target.pendingResults = pendingResults;
4586                target.pendingIntents = pendingNewIntents;
4587                target.mPreserveWindow = preserveWindow;
4588                mRelaunchingActivities.add(target);
4589                scheduleRelaunch = true;
4590            }
4591            target.createdConfig = config.getGlobalConfiguration();
4592            target.overrideConfig = config.getOverrideConfiguration();
4593            target.pendingConfigChanges |= configChanges;
4594        }
4595
4596        return scheduleRelaunch ? target : null;
4597    }
4598
4599    @Override
4600    public void handleRelaunchActivity(ActivityClientRecord tmp,
4601            PendingTransactionActions pendingActions) {
4602        // If we are getting ready to gc after going to the background, well
4603        // we are back active so skip it.
4604        unscheduleGcIdler();
4605        mSomeActivitiesChanged = true;
4606
4607        Configuration changedConfig = null;
4608        int configChanges = 0;
4609
4610        // First: make sure we have the most recent configuration and most
4611        // recent version of the activity, or skip it if some previous call
4612        // had taken a more recent version.
4613        synchronized (mResourcesManager) {
4614            int N = mRelaunchingActivities.size();
4615            IBinder token = tmp.token;
4616            tmp = null;
4617            for (int i=0; i<N; i++) {
4618                ActivityClientRecord r = mRelaunchingActivities.get(i);
4619                if (r.token == token) {
4620                    tmp = r;
4621                    configChanges |= tmp.pendingConfigChanges;
4622                    mRelaunchingActivities.remove(i);
4623                    i--;
4624                    N--;
4625                }
4626            }
4627
4628            if (tmp == null) {
4629                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
4630                return;
4631            }
4632
4633            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
4634                    + tmp.token + " with configChanges=0x"
4635                    + Integer.toHexString(configChanges));
4636
4637            if (mPendingConfiguration != null) {
4638                changedConfig = mPendingConfiguration;
4639                mPendingConfiguration = null;
4640            }
4641        }
4642
4643        if (tmp.createdConfig != null) {
4644            // If the activity manager is passing us its current config,
4645            // assume that is really what we want regardless of what we
4646            // may have pending.
4647            if (mConfiguration == null
4648                    || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
4649                            && mConfiguration.diff(tmp.createdConfig) != 0)) {
4650                if (changedConfig == null
4651                        || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
4652                    changedConfig = tmp.createdConfig;
4653                }
4654            }
4655        }
4656
4657        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
4658                + tmp.token + ": changedConfig=" + changedConfig);
4659
4660        // If there was a pending configuration change, execute it first.
4661        if (changedConfig != null) {
4662            mCurDefaultDisplayDpi = changedConfig.densityDpi;
4663            updateDefaultDensity();
4664            handleConfigurationChanged(changedConfig, null);
4665        }
4666
4667        ActivityClientRecord r = mActivities.get(tmp.token);
4668        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
4669        if (r == null) {
4670            return;
4671        }
4672
4673        r.activity.mConfigChangeFlags |= configChanges;
4674        r.mPreserveWindow = tmp.mPreserveWindow;
4675
4676        r.activity.mChangingConfigurations = true;
4677
4678        // If we are preserving the main window across relaunches we would also like to preserve
4679        // the children. However the client side view system does not support preserving
4680        // the child views so we notify the window manager to expect these windows to
4681        // be replaced and defer requests to destroy or hide them. This way we can achieve
4682        // visual continuity. It's important that we do this here prior to pause and destroy
4683        // as that is when we may hide or remove the child views.
4684        //
4685        // There is another scenario, if we have decided locally to relaunch the app from a
4686        // call to recreate, then none of the windows will be prepared for replacement or
4687        // preserved by the server, so we want to notify it that we are preparing to replace
4688        // everything
4689        try {
4690            if (r.mPreserveWindow) {
4691                WindowManagerGlobal.getWindowSession().prepareToReplaceWindows(
4692                        r.token, true /* childrenOnly */);
4693            }
4694        } catch (RemoteException e) {
4695            throw e.rethrowFromSystemServer();
4696        }
4697
4698        handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
4699                pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
4700
4701        if (pendingActions != null) {
4702            // Only report a successful relaunch to WindowManager.
4703            pendingActions.setReportRelaunchToWindowManager(true);
4704        }
4705    }
4706
4707    /** Performs the activity relaunch locally vs. requesting from system-server. */
4708    void handleRelaunchActivityLocally(IBinder token) {
4709        if (Looper.myLooper() != getLooper()) {
4710            throw new IllegalStateException("Must be called from main thread");
4711        }
4712
4713        final ActivityClientRecord r = mActivities.get(token);
4714        if (r == null) {
4715            return;
4716        }
4717
4718        final int prevState = r.getLifecycleState();
4719
4720        if (prevState < ON_RESUME) {
4721            Log.w(TAG, "Activity needs to be already resumed in other to be relaunched.");
4722            return;
4723        }
4724
4725        // TODO(b/73747058): Investigate converting this to use transaction to relaunch.
4726        handleRelaunchActivityInner(r, 0 /* configChanges */, null /* pendingResults */,
4727                null /* pendingIntents */, null /* pendingActions */, prevState != ON_RESUME,
4728                r.overrideConfig, "handleRelaunchActivityLocally");
4729
4730        // Restore back to the previous state before relaunch if needed.
4731        if (prevState != r.getLifecycleState()) {
4732            mTransactionExecutor.cycleToPath(r, prevState);
4733        }
4734    }
4735
4736    private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
4737            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
4738            PendingTransactionActions pendingActions, boolean startsNotResumed,
4739            Configuration overrideConfig, String reason) {
4740        // Need to ensure state is saved.
4741        if (!r.paused) {
4742            performPauseActivity(r, false, reason, null /* pendingActions */);
4743        }
4744        if (!r.stopped) {
4745            callActivityOnStop(r, true /* saveState */, reason);
4746        }
4747
4748        handleDestroyActivity(r.token, false, configChanges, true, reason);
4749
4750        r.activity = null;
4751        r.window = null;
4752        r.hideForNow = false;
4753        r.nextIdle = null;
4754        // Merge any pending results and pending intents; don't just replace them
4755        if (pendingResults != null) {
4756            if (r.pendingResults == null) {
4757                r.pendingResults = pendingResults;
4758            } else {
4759                r.pendingResults.addAll(pendingResults);
4760            }
4761        }
4762        if (pendingIntents != null) {
4763            if (r.pendingIntents == null) {
4764                r.pendingIntents = pendingIntents;
4765            } else {
4766                r.pendingIntents.addAll(pendingIntents);
4767            }
4768        }
4769        r.startsNotResumed = startsNotResumed;
4770        r.overrideConfig = overrideConfig;
4771
4772        handleLaunchActivity(r, pendingActions);
4773    }
4774
4775    @Override
4776    public void reportRelaunch(IBinder token, PendingTransactionActions pendingActions) {
4777        try {
4778            ActivityManager.getService().activityRelaunched(token);
4779            final ActivityClientRecord r = mActivities.get(token);
4780            if (pendingActions.shouldReportRelaunchToWindowManager() && r != null
4781                    && r.window != null) {
4782                r.window.reportActivityRelaunched();
4783            }
4784        } catch (RemoteException e) {
4785            throw e.rethrowFromSystemServer();
4786        }
4787    }
4788
4789    private void callActivityOnSaveInstanceState(ActivityClientRecord r) {
4790        r.state = new Bundle();
4791        r.state.setAllowFds(false);
4792        if (r.isPersistable()) {
4793            r.persistentState = new PersistableBundle();
4794            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
4795                    r.persistentState);
4796        } else {
4797            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
4798        }
4799    }
4800
4801    ArrayList<ComponentCallbacks2> collectComponentCallbacks(
4802            boolean allActivities, Configuration newConfig) {
4803        ArrayList<ComponentCallbacks2> callbacks
4804                = new ArrayList<ComponentCallbacks2>();
4805
4806        synchronized (mResourcesManager) {
4807            final int NAPP = mAllApplications.size();
4808            for (int i=0; i<NAPP; i++) {
4809                callbacks.add(mAllApplications.get(i));
4810            }
4811            final int NACT = mActivities.size();
4812            for (int i=0; i<NACT; i++) {
4813                ActivityClientRecord ar = mActivities.valueAt(i);
4814                Activity a = ar.activity;
4815                if (a != null) {
4816                    Configuration thisConfig = applyConfigCompatMainThread(
4817                            mCurDefaultDisplayDpi, newConfig,
4818                            ar.packageInfo.getCompatibilityInfo());
4819                    if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
4820                        // If the activity is currently resumed, its configuration
4821                        // needs to change right now.
4822                        callbacks.add(a);
4823                    } else if (thisConfig != null) {
4824                        // Otherwise, we will tell it about the change
4825                        // the next time it is resumed or shown.  Note that
4826                        // the activity manager may, before then, decide the
4827                        // activity needs to be destroyed to handle its new
4828                        // configuration.
4829                        if (DEBUG_CONFIGURATION) {
4830                            Slog.v(TAG, "Setting activity "
4831                                    + ar.activityInfo.name + " newConfig=" + thisConfig);
4832                        }
4833                        ar.newConfig = thisConfig;
4834                    }
4835                }
4836            }
4837            final int NSVC = mServices.size();
4838            for (int i=0; i<NSVC; i++) {
4839                callbacks.add(mServices.valueAt(i));
4840            }
4841        }
4842        synchronized (mProviderMap) {
4843            final int NPRV = mLocalProviders.size();
4844            for (int i=0; i<NPRV; i++) {
4845                callbacks.add(mLocalProviders.valueAt(i).mLocalProvider);
4846            }
4847        }
4848
4849        return callbacks;
4850    }
4851
4852    /**
4853     * Updates the configuration for an Activity. The ActivityClientRecord's
4854     * {@link ActivityClientRecord#overrideConfig} is used to compute the final Configuration for
4855     * that Activity. {@link ActivityClientRecord#tmpConfig} is used as a temporary for delivering
4856     * the updated Configuration.
4857     * @param r ActivityClientRecord representing the Activity.
4858     * @param newBaseConfig The new configuration to use. This may be augmented with
4859     *                      {@link ActivityClientRecord#overrideConfig}.
4860     */
4861    private void performConfigurationChangedForActivity(ActivityClientRecord r,
4862            Configuration newBaseConfig) {
4863        performConfigurationChangedForActivity(r, newBaseConfig,
4864                r.activity.getDisplay().getDisplayId(), false /* movedToDifferentDisplay */);
4865    }
4866
4867    /**
4868     * Updates the configuration for an Activity. The ActivityClientRecord's
4869     * {@link ActivityClientRecord#overrideConfig} is used to compute the final Configuration for
4870     * that Activity. {@link ActivityClientRecord#tmpConfig} is used as a temporary for delivering
4871     * the updated Configuration.
4872     * @param r ActivityClientRecord representing the Activity.
4873     * @param newBaseConfig The new configuration to use. This may be augmented with
4874     *                      {@link ActivityClientRecord#overrideConfig}.
4875     * @param displayId The id of the display where the Activity currently resides.
4876     * @param movedToDifferentDisplay Indicates if the activity was moved to different display.
4877     * @return {@link Configuration} instance sent to client, null if not sent.
4878     */
4879    private Configuration performConfigurationChangedForActivity(ActivityClientRecord r,
4880            Configuration newBaseConfig, int displayId, boolean movedToDifferentDisplay) {
4881        r.tmpConfig.setTo(newBaseConfig);
4882        if (r.overrideConfig != null) {
4883            r.tmpConfig.updateFrom(r.overrideConfig);
4884        }
4885        final Configuration reportedConfig = performActivityConfigurationChanged(r.activity,
4886                r.tmpConfig, r.overrideConfig, displayId, movedToDifferentDisplay);
4887        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
4888        return reportedConfig;
4889    }
4890
4891    /**
4892     * Creates a new Configuration only if override would modify base. Otherwise returns base.
4893     * @param base The base configuration.
4894     * @param override The update to apply to the base configuration. Can be null.
4895     * @return A Configuration representing base with override applied.
4896     */
4897    private static Configuration createNewConfigAndUpdateIfNotNull(@NonNull Configuration base,
4898            @Nullable Configuration override) {
4899        if (override == null) {
4900            return base;
4901        }
4902        Configuration newConfig = new Configuration(base);
4903        newConfig.updateFrom(override);
4904        return newConfig;
4905    }
4906
4907    /**
4908     * Decides whether to update a component's configuration and whether to inform it.
4909     * @param cb The component callback to notify of configuration change.
4910     * @param newConfig The new configuration.
4911     */
4912    private void performConfigurationChanged(ComponentCallbacks2 cb, Configuration newConfig) {
4913        if (!REPORT_TO_ACTIVITY) {
4914            return;
4915        }
4916
4917        // ContextThemeWrappers may override the configuration for that context. We must check and
4918        // apply any overrides defined.
4919        Configuration contextThemeWrapperOverrideConfig = null;
4920        if (cb instanceof ContextThemeWrapper) {
4921            final ContextThemeWrapper contextThemeWrapper = (ContextThemeWrapper) cb;
4922            contextThemeWrapperOverrideConfig = contextThemeWrapper.getOverrideConfiguration();
4923        }
4924
4925        // Apply the ContextThemeWrapper override if necessary.
4926        // NOTE: Make sure the configurations are not modified, as they are treated as immutable
4927        // in many places.
4928        final Configuration configToReport = createNewConfigAndUpdateIfNotNull(
4929                newConfig, contextThemeWrapperOverrideConfig);
4930        cb.onConfigurationChanged(configToReport);
4931    }
4932
4933    /**
4934     * Decides whether to update an Activity's configuration and whether to inform it.
4935     * @param activity The activity to notify of configuration change.
4936     * @param newConfig The new configuration.
4937     * @param amOverrideConfig The override config that differentiates the Activity's configuration
4938     *                         from the base global configuration. This is supplied by
4939     *                         ActivityManager.
4940     * @param displayId Id of the display where activity currently resides.
4941     * @param movedToDifferentDisplay Indicates if the activity was moved to different display.
4942     * @return Configuration sent to client, null if no changes and not moved to different display.
4943     */
4944    private Configuration performActivityConfigurationChanged(Activity activity,
4945            Configuration newConfig, Configuration amOverrideConfig, int displayId,
4946            boolean movedToDifferentDisplay) {
4947        if (activity == null) {
4948            throw new IllegalArgumentException("No activity provided.");
4949        }
4950        final IBinder activityToken = activity.getActivityToken();
4951        if (activityToken == null) {
4952            throw new IllegalArgumentException("Activity token not set. Is the activity attached?");
4953        }
4954
4955        boolean shouldChangeConfig = false;
4956        if (activity.mCurrentConfig == null) {
4957            shouldChangeConfig = true;
4958        } else {
4959            // If the new config is the same as the config this Activity is already running with and
4960            // the override config also didn't change, then don't bother calling
4961            // onConfigurationChanged.
4962            final int diff = activity.mCurrentConfig.diffPublicOnly(newConfig);
4963
4964            if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken,
4965                    amOverrideConfig)) {
4966                // Always send the task-level config changes. For system-level configuration, if
4967                // this activity doesn't handle any of the config changes, then don't bother
4968                // calling onConfigurationChanged as we're going to destroy it.
4969                if (!mUpdatingSystemConfig
4970                        || (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
4971                        || !REPORT_TO_ACTIVITY) {
4972                    shouldChangeConfig = true;
4973                }
4974            }
4975        }
4976        if (!shouldChangeConfig && !movedToDifferentDisplay) {
4977            // Nothing significant, don't proceed with updating and reporting.
4978            return null;
4979        }
4980
4981        // Propagate the configuration change to ResourcesManager and Activity.
4982
4983        // ContextThemeWrappers may override the configuration for that context. We must check and
4984        // apply any overrides defined.
4985        Configuration contextThemeWrapperOverrideConfig = activity.getOverrideConfiguration();
4986
4987        // We only update an Activity's configuration if this is not a global configuration change.
4988        // This must also be done before the callback, or else we violate the contract that the new
4989        // resources are available in ComponentCallbacks2#onConfigurationChanged(Configuration).
4990        // Also apply the ContextThemeWrapper override if necessary.
4991        // NOTE: Make sure the configurations are not modified, as they are treated as immutable in
4992        // many places.
4993        final Configuration finalOverrideConfig = createNewConfigAndUpdateIfNotNull(
4994                amOverrideConfig, contextThemeWrapperOverrideConfig);
4995        mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig,
4996                displayId, movedToDifferentDisplay);
4997
4998        activity.mConfigChangeFlags = 0;
4999        activity.mCurrentConfig = new Configuration(newConfig);
5000
5001        // Apply the ContextThemeWrapper override if necessary.
5002        // NOTE: Make sure the configurations are not modified, as they are treated as immutable
5003        // in many places.
5004        final Configuration configToReport = createNewConfigAndUpdateIfNotNull(newConfig,
5005                contextThemeWrapperOverrideConfig);
5006
5007        if (!REPORT_TO_ACTIVITY) {
5008            // Not configured to report to activity.
5009            return configToReport;
5010        }
5011
5012        if (movedToDifferentDisplay) {
5013            activity.dispatchMovedToDisplay(displayId, configToReport);
5014        }
5015
5016        if (shouldChangeConfig) {
5017            activity.mCalled = false;
5018            activity.onConfigurationChanged(configToReport);
5019            if (!activity.mCalled) {
5020                throw new SuperNotCalledException("Activity " + activity.getLocalClassName() +
5021                                " did not call through to super.onConfigurationChanged()");
5022            }
5023        }
5024
5025        return configToReport;
5026    }
5027
5028    public final void applyConfigurationToResources(Configuration config) {
5029        synchronized (mResourcesManager) {
5030            mResourcesManager.applyConfigurationToResourcesLocked(config, null);
5031        }
5032    }
5033
5034    final Configuration applyCompatConfiguration(int displayDensity) {
5035        Configuration config = mConfiguration;
5036        if (mCompatConfiguration == null) {
5037            mCompatConfiguration = new Configuration();
5038        }
5039        mCompatConfiguration.setTo(mConfiguration);
5040        if (mResourcesManager.applyCompatConfigurationLocked(displayDensity,
5041                mCompatConfiguration)) {
5042            config = mCompatConfiguration;
5043        }
5044        return config;
5045    }
5046
5047    @Override
5048    public void handleConfigurationChanged(Configuration config) {
5049        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
5050        mCurDefaultDisplayDpi = config.densityDpi;
5051        mUpdatingSystemConfig = true;
5052        try {
5053            handleConfigurationChanged(config, null /* compat */);
5054        } finally {
5055            mUpdatingSystemConfig = false;
5056        }
5057        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
5058    }
5059
5060    private void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
5061
5062        int configDiff = 0;
5063
5064        // This flag tracks whether the new configuration is fundamentally equivalent to the
5065        // existing configuration. This is necessary to determine whether non-activity
5066        // callbacks should receive notice when the only changes are related to non-public fields.
5067        // We do not gate calling {@link #performActivityConfigurationChanged} based on this flag
5068        // as that method uses the same check on the activity config override as well.
5069        final boolean equivalent = config != null && mConfiguration != null
5070                && (0 == mConfiguration.diffPublicOnly(config));
5071        final Theme systemTheme = getSystemContext().getTheme();
5072        final Theme systemUiTheme = getSystemUiContext().getTheme();
5073
5074        synchronized (mResourcesManager) {
5075            if (mPendingConfiguration != null) {
5076                if (!mPendingConfiguration.isOtherSeqNewer(config)) {
5077                    config = mPendingConfiguration;
5078                    mCurDefaultDisplayDpi = config.densityDpi;
5079                    updateDefaultDensity();
5080                }
5081                mPendingConfiguration = null;
5082            }
5083
5084            if (config == null) {
5085                return;
5086            }
5087
5088            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
5089                    + config);
5090
5091            mResourcesManager.applyConfigurationToResourcesLocked(config, compat);
5092            updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
5093                    mResourcesManager.getConfiguration().getLocales());
5094
5095            if (mConfiguration == null) {
5096                mConfiguration = new Configuration();
5097            }
5098            if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
5099                return;
5100            }
5101
5102            configDiff = mConfiguration.updateFrom(config);
5103            config = applyCompatConfiguration(mCurDefaultDisplayDpi);
5104
5105            if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
5106                systemTheme.rebase();
5107            }
5108
5109            if ((systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
5110                systemUiTheme.rebase();
5111            }
5112        }
5113
5114        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
5115
5116        freeTextLayoutCachesIfNeeded(configDiff);
5117
5118        if (callbacks != null) {
5119            final int N = callbacks.size();
5120            for (int i=0; i<N; i++) {
5121                ComponentCallbacks2 cb = callbacks.get(i);
5122                if (cb instanceof Activity) {
5123                    // If callback is an Activity - call corresponding method to consider override
5124                    // config and avoid onConfigurationChanged if it hasn't changed.
5125                    Activity a = (Activity) cb;
5126                    performConfigurationChangedForActivity(mActivities.get(a.getActivityToken()),
5127                            config);
5128                } else if (!equivalent) {
5129                    performConfigurationChanged(cb, config);
5130                }
5131            }
5132        }
5133    }
5134
5135    void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
5136        // Updates triggered by package installation go through a package update
5137        // receiver. Here we try to capture ApplicationInfo changes that are
5138        // caused by other sources, such as overlays. That means we want to be as conservative
5139        // about code changes as possible. Take the diff of the old ApplicationInfo and the new
5140        // to see if anything needs to change.
5141        LoadedApk apk;
5142        LoadedApk resApk;
5143        // Update all affected loaded packages with new package information
5144        synchronized (mResourcesManager) {
5145            WeakReference<LoadedApk> ref = mPackages.get(ai.packageName);
5146            apk = ref != null ? ref.get() : null;
5147            ref = mResourcePackages.get(ai.packageName);
5148            resApk = ref != null ? ref.get() : null;
5149        }
5150        if (apk != null) {
5151            final ArrayList<String> oldPaths = new ArrayList<>();
5152            LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths);
5153            apk.updateApplicationInfo(ai, oldPaths);
5154        }
5155        if (resApk != null) {
5156            final ArrayList<String> oldPaths = new ArrayList<>();
5157            LoadedApk.makePaths(this, resApk.getApplicationInfo(), oldPaths);
5158            resApk.updateApplicationInfo(ai, oldPaths);
5159        }
5160        synchronized (mResourcesManager) {
5161            // Update all affected Resources objects to use new ResourcesImpl
5162            mResourcesManager.applyNewResourceDirsLocked(ai.sourceDir, ai.resourceDirs);
5163        }
5164
5165        ApplicationPackageManager.configurationChanged();
5166
5167        // Trigger a regular Configuration change event, only with a different assetsSeq number
5168        // so that we actually call through to all components.
5169        // TODO(adamlesinski): Change this to make use of ActivityManager's upcoming ability to
5170        // store configurations per-process.
5171        Configuration newConfig = new Configuration();
5172        newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
5173        handleConfigurationChanged(newConfig, null);
5174
5175        relaunchAllActivities();
5176    }
5177
5178    static void freeTextLayoutCachesIfNeeded(int configDiff) {
5179        if (configDiff != 0) {
5180            // Ask text layout engine to free its caches if there is a locale change
5181            boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
5182            if (hasLocaleConfigChange) {
5183                Canvas.freeTextLayoutCaches();
5184                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
5185            }
5186        }
5187    }
5188
5189    /**
5190     * Handle new activity configuration and/or move to a different display.
5191     * @param activityToken Target activity token.
5192     * @param overrideConfig Activity override config.
5193     * @param displayId Id of the display where activity was moved to, -1 if there was no move and
5194     *                  value didn't change.
5195     */
5196    @Override
5197    public void handleActivityConfigurationChanged(IBinder activityToken,
5198            Configuration overrideConfig, int displayId) {
5199        ActivityClientRecord r = mActivities.get(activityToken);
5200        // Check input params.
5201        if (r == null || r.activity == null) {
5202            if (DEBUG_CONFIGURATION) Slog.w(TAG, "Not found target activity to report to: " + r);
5203            return;
5204        }
5205        final boolean movedToDifferentDisplay = displayId != INVALID_DISPLAY
5206                && displayId != r.activity.getDisplay().getDisplayId();
5207
5208        // Perform updates.
5209        r.overrideConfig = overrideConfig;
5210        final ViewRootImpl viewRoot = r.activity.mDecor != null
5211            ? r.activity.mDecor.getViewRootImpl() : null;
5212
5213        if (movedToDifferentDisplay) {
5214            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity moved to display, activity:"
5215                    + r.activityInfo.name + ", displayId=" + displayId
5216                    + ", config=" + overrideConfig);
5217
5218            final Configuration reportedConfig = performConfigurationChangedForActivity(r,
5219                    mCompatConfiguration, displayId, true /* movedToDifferentDisplay */);
5220            if (viewRoot != null) {
5221                viewRoot.onMovedToDisplay(displayId, reportedConfig);
5222            }
5223        } else {
5224            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
5225                    + r.activityInfo.name + ", config=" + overrideConfig);
5226            performConfigurationChangedForActivity(r, mCompatConfiguration);
5227        }
5228        // Notify the ViewRootImpl instance about configuration changes. It may have initiated this
5229        // update to make sure that resources are updated before updating itself.
5230        if (viewRoot != null) {
5231            viewRoot.updateConfiguration(displayId);
5232        }
5233        mSomeActivitiesChanged = true;
5234    }
5235
5236    final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
5237        if (start) {
5238            try {
5239                switch (profileType) {
5240                    default:
5241                        mProfiler.setProfiler(profilerInfo);
5242                        mProfiler.startProfiling();
5243                        break;
5244                }
5245            } catch (RuntimeException e) {
5246                Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile
5247                        + " -- can the process access this path?");
5248            } finally {
5249                profilerInfo.closeFd();
5250            }
5251        } else {
5252            switch (profileType) {
5253                default:
5254                    mProfiler.stopProfiling();
5255                    break;
5256            }
5257        }
5258    }
5259
5260    /**
5261     * Public entrypoint to stop profiling. This is required to end profiling when the app crashes,
5262     * so that profiler data won't be lost.
5263     *
5264     * @hide
5265     */
5266    public void stopProfiling() {
5267        if (mProfiler != null) {
5268            mProfiler.stopProfiling();
5269        }
5270    }
5271
5272    static void handleDumpHeap(DumpHeapData dhd) {
5273        if (dhd.runGc) {
5274            System.gc();
5275            System.runFinalization();
5276            System.gc();
5277        }
5278        if (dhd.managed) {
5279            try {
5280                Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
5281            } catch (IOException e) {
5282                Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
5283                        + " -- can the process access this path?");
5284            } finally {
5285                try {
5286                    dhd.fd.close();
5287                } catch (IOException e) {
5288                    Slog.w(TAG, "Failure closing profile fd", e);
5289                }
5290            }
5291        } else if (dhd.mallocInfo) {
5292            Debug.dumpNativeMallocInfo(dhd.fd.getFileDescriptor());
5293        } else {
5294            Debug.dumpNativeHeap(dhd.fd.getFileDescriptor());
5295        }
5296        try {
5297            ActivityManager.getService().dumpHeapFinished(dhd.path);
5298        } catch (RemoteException e) {
5299            throw e.rethrowFromSystemServer();
5300        }
5301    }
5302
5303    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
5304        boolean hasPkgInfo = false;
5305        switch (cmd) {
5306            case ApplicationThreadConstants.PACKAGE_REMOVED:
5307            case ApplicationThreadConstants.PACKAGE_REMOVED_DONT_KILL:
5308            {
5309                final boolean killApp = cmd == ApplicationThreadConstants.PACKAGE_REMOVED;
5310                if (packages == null) {
5311                    break;
5312                }
5313                synchronized (mResourcesManager) {
5314                    for (int i = packages.length - 1; i >= 0; i--) {
5315                        if (!hasPkgInfo) {
5316                            WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
5317                            if (ref != null && ref.get() != null) {
5318                                hasPkgInfo = true;
5319                            } else {
5320                                ref = mResourcePackages.get(packages[i]);
5321                                if (ref != null && ref.get() != null) {
5322                                    hasPkgInfo = true;
5323                                }
5324                            }
5325                        }
5326                        if (killApp) {
5327                            mPackages.remove(packages[i]);
5328                            mResourcePackages.remove(packages[i]);
5329                        }
5330                    }
5331                }
5332                break;
5333            }
5334            case ApplicationThreadConstants.PACKAGE_REPLACED:
5335            {
5336                if (packages == null) {
5337                    break;
5338                }
5339                synchronized (mResourcesManager) {
5340                    for (int i = packages.length - 1; i >= 0; i--) {
5341                        WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
5342                        LoadedApk pkgInfo = ref != null ? ref.get() : null;
5343                        if (pkgInfo != null) {
5344                            hasPkgInfo = true;
5345                        } else {
5346                            ref = mResourcePackages.get(packages[i]);
5347                            pkgInfo = ref != null ? ref.get() : null;
5348                            if (pkgInfo != null) {
5349                                hasPkgInfo = true;
5350                            }
5351                        }
5352                        // If the package is being replaced, yet it still has a valid
5353                        // LoadedApk object, the package was updated with _DONT_KILL.
5354                        // Adjust it's internal references to the application info and
5355                        // resources.
5356                        if (pkgInfo != null) {
5357                            try {
5358                                final String packageName = packages[i];
5359                                final ApplicationInfo aInfo =
5360                                        sPackageManager.getApplicationInfo(
5361                                                packageName,
5362                                                PackageManager.GET_SHARED_LIBRARY_FILES,
5363                                                UserHandle.myUserId());
5364
5365                                if (mActivities.size() > 0) {
5366                                    for (ActivityClientRecord ar : mActivities.values()) {
5367                                        if (ar.activityInfo.applicationInfo.packageName
5368                                                .equals(packageName)) {
5369                                            ar.activityInfo.applicationInfo = aInfo;
5370                                            ar.packageInfo = pkgInfo;
5371                                        }
5372                                    }
5373                                }
5374                                final List<String> oldPaths =
5375                                        sPackageManager.getPreviousCodePaths(packageName);
5376                                pkgInfo.updateApplicationInfo(aInfo, oldPaths);
5377                            } catch (RemoteException e) {
5378                            }
5379                        }
5380                    }
5381                }
5382                break;
5383            }
5384        }
5385        ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasPkgInfo);
5386    }
5387
5388    final void handleLowMemory() {
5389        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
5390
5391        final int N = callbacks.size();
5392        for (int i=0; i<N; i++) {
5393            callbacks.get(i).onLowMemory();
5394        }
5395
5396        // Ask SQLite to free up as much memory as it can, mostly from its page caches.
5397        if (Process.myUid() != Process.SYSTEM_UID) {
5398            int sqliteReleased = SQLiteDatabase.releaseMemory();
5399            EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
5400        }
5401
5402        // Ask graphics to free up as much as possible (font/image caches)
5403        Canvas.freeCaches();
5404
5405        // Ask text layout engine to free also as much as possible
5406        Canvas.freeTextLayoutCaches();
5407
5408        BinderInternal.forceGc("mem");
5409    }
5410
5411    final void handleTrimMemory(int level) {
5412        if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
5413
5414        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
5415
5416        final int N = callbacks.size();
5417        for (int i = 0; i < N; i++) {
5418            callbacks.get(i).onTrimMemory(level);
5419        }
5420
5421        WindowManagerGlobal.getInstance().trimMemory(level);
5422    }
5423
5424    private void setupGraphicsSupport(Context context) {
5425        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setupGraphicsSupport");
5426
5427        // The system package doesn't have real data directories, so don't set up cache paths.
5428        if (!"android".equals(context.getPackageName())) {
5429            // This cache location probably points at credential-encrypted
5430            // storage which may not be accessible yet; assign it anyway instead
5431            // of pointing at device-encrypted storage.
5432            final File cacheDir = context.getCacheDir();
5433            if (cacheDir != null) {
5434                // Provide a usable directory for temporary files
5435                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
5436            } else {
5437                Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "
5438                        + "due to missing cache directory");
5439            }
5440
5441            // Setup a location to store generated/compiled graphics code.
5442            final Context deviceContext = context.createDeviceProtectedStorageContext();
5443            final File codeCacheDir = deviceContext.getCodeCacheDir();
5444            if (codeCacheDir != null) {
5445                try {
5446                    int uid = Process.myUid();
5447                    String[] packages = getPackageManager().getPackagesForUid(uid);
5448                    if (packages != null) {
5449                        ThreadedRenderer.setupDiskCache(codeCacheDir);
5450                        RenderScriptCacheDir.setupDiskCache(codeCacheDir);
5451                    }
5452                } catch (RemoteException e) {
5453                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
5454                    throw e.rethrowFromSystemServer();
5455                }
5456            } else {
5457                Log.w(TAG, "Unable to use shader/script cache: missing code-cache directory");
5458            }
5459        }
5460
5461        GraphicsEnvironment.getInstance().setup(context);
5462        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
5463    }
5464
5465    private void updateDefaultDensity() {
5466        final int densityDpi = mCurDefaultDisplayDpi;
5467        if (!mDensityCompatMode
5468                && densityDpi != Configuration.DENSITY_DPI_UNDEFINED
5469                && densityDpi != DisplayMetrics.DENSITY_DEVICE) {
5470            DisplayMetrics.DENSITY_DEVICE = densityDpi;
5471            Bitmap.setDefaultDensity(densityDpi);
5472        }
5473    }
5474
5475    /**
5476     * Returns the correct library directory for the current ABI.
5477     * <p>
5478     * If we're dealing with a multi-arch application that has both 32 and 64 bit shared
5479     * libraries, we might need to choose the secondary depending on what the current
5480     * runtime's instruction set is.
5481     */
5482    private String getInstrumentationLibrary(ApplicationInfo appInfo, InstrumentationInfo insInfo) {
5483        if (appInfo.primaryCpuAbi != null && appInfo.secondaryCpuAbi != null) {
5484            // Get the instruction set supported by the secondary ABI. In the presence
5485            // of a native bridge this might be different than the one secondary ABI used.
5486            String secondaryIsa =
5487                    VMRuntime.getInstructionSet(appInfo.secondaryCpuAbi);
5488            final String secondaryDexCodeIsa =
5489                    SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
5490            secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
5491
5492            final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
5493            if (runtimeIsa.equals(secondaryIsa)) {
5494                return insInfo.secondaryNativeLibraryDir;
5495            }
5496        }
5497        return insInfo.nativeLibraryDir;
5498    }
5499
5500    /**
5501     * The LocaleList set for the app's resources may have been shuffled so that the preferred
5502     * Locale is at position 0. We must find the index of this preferred Locale in the
5503     * original LocaleList.
5504     */
5505    private void updateLocaleListFromAppContext(Context context, LocaleList newLocaleList) {
5506        final Locale bestLocale = context.getResources().getConfiguration().getLocales().get(0);
5507        final int newLocaleListSize = newLocaleList.size();
5508        for (int i = 0; i < newLocaleListSize; i++) {
5509            if (bestLocale.equals(newLocaleList.get(i))) {
5510                LocaleList.setDefault(newLocaleList, i);
5511                return;
5512            }
5513        }
5514
5515        // The app may have overridden the LocaleList with its own Locale
5516        // (not present in the available list). Push the chosen Locale
5517        // to the front of the list.
5518        LocaleList.setDefault(new LocaleList(bestLocale, newLocaleList));
5519    }
5520
5521    private void handleBindApplication(AppBindData data) {
5522        // Register the UI Thread as a sensitive thread to the runtime.
5523        VMRuntime.registerSensitiveThread();
5524        if (data.trackAllocation) {
5525            DdmVmInternal.enableRecentAllocations(true);
5526        }
5527
5528        // Note when this process has started.
5529        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
5530
5531        mBoundApplication = data;
5532        mConfiguration = new Configuration(data.config);
5533        mCompatConfiguration = new Configuration(data.config);
5534
5535        mProfiler = new Profiler();
5536        String agent = null;
5537        if (data.initProfilerInfo != null) {
5538            mProfiler.profileFile = data.initProfilerInfo.profileFile;
5539            mProfiler.profileFd = data.initProfilerInfo.profileFd;
5540            mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
5541            mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
5542            mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
5543            if (data.initProfilerInfo.attachAgentDuringBind) {
5544                agent = data.initProfilerInfo.agent;
5545            }
5546        }
5547
5548        // send up app name; do this *before* waiting for debugger
5549        Process.setArgV0(data.processName);
5550        android.ddm.DdmHandleAppName.setAppName(data.processName,
5551                                                UserHandle.myUserId());
5552
5553        if (mProfiler.profileFd != null) {
5554            mProfiler.startProfiling();
5555        }
5556
5557        // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
5558        // implementation to use the pool executor.  Normally, we use the
5559        // serialized executor as the default. This has to happen in the
5560        // main thread so the main looper is set right.
5561        if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
5562            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
5563        }
5564
5565        Message.updateCheckRecycle(data.appInfo.targetSdkVersion);
5566
5567        /*
5568         * Before spawning a new process, reset the time zone to be the system time zone.
5569         * This needs to be done because the system time zone could have changed after the
5570         * the spawning of this process. Without doing this this process would have the incorrect
5571         * system time zone.
5572         */
5573        TimeZone.setDefault(null);
5574
5575        /*
5576         * Set the LocaleList. This may change once we create the App Context.
5577         */
5578        LocaleList.setDefault(data.config.getLocales());
5579
5580        synchronized (mResourcesManager) {
5581            /*
5582             * Update the system configuration since its preloaded and might not
5583             * reflect configuration changes. The configuration object passed
5584             * in AppBindData can be safely assumed to be up to date
5585             */
5586            mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
5587            mCurDefaultDisplayDpi = data.config.densityDpi;
5588
5589            // This calls mResourcesManager so keep it within the synchronized block.
5590            applyCompatConfiguration(mCurDefaultDisplayDpi);
5591        }
5592
5593        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
5594
5595        if (agent != null) {
5596            handleAttachAgent(agent, data.info);
5597        }
5598
5599        /**
5600         * Switch this process to density compatibility mode if needed.
5601         */
5602        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
5603                == 0) {
5604            mDensityCompatMode = true;
5605            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
5606        }
5607        updateDefaultDensity();
5608
5609        final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24);
5610        Boolean is24Hr = null;
5611        if (use24HourSetting != null) {
5612            is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE;
5613        }
5614        // null : use locale default for 12/24 hour formatting,
5615        // false : use 12 hour format,
5616        // true : use 24 hour format.
5617        DateFormat.set24HourTimePref(is24Hr);
5618
5619        View.mDebugViewAttributes =
5620                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
5621
5622        StrictMode.initThreadDefaults(data.appInfo);
5623        StrictMode.initVmDefaults(data.appInfo);
5624
5625        // We deprecated Build.SERIAL and only apps that target pre NMR1
5626        // SDK can see it. Since access to the serial is now behind a
5627        // permission we push down the value and here we fix it up
5628        // before any app code has been loaded.
5629        try {
5630            Field field = Build.class.getDeclaredField("SERIAL");
5631            field.setAccessible(true);
5632            field.set(Build.class, data.buildSerial);
5633        } catch (NoSuchFieldException | IllegalAccessException e) {
5634            /* ignore */
5635        }
5636
5637        if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
5638            // XXX should have option to change the port.
5639            Debug.changeDebugPort(8100);
5640            if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
5641                Slog.w(TAG, "Application " + data.info.getPackageName()
5642                      + " is waiting for the debugger on port 8100...");
5643
5644                IActivityManager mgr = ActivityManager.getService();
5645                try {
5646                    mgr.showWaitingForDebugger(mAppThread, true);
5647                } catch (RemoteException ex) {
5648                    throw ex.rethrowFromSystemServer();
5649                }
5650
5651                Debug.waitForDebugger();
5652
5653                try {
5654                    mgr.showWaitingForDebugger(mAppThread, false);
5655                } catch (RemoteException ex) {
5656                    throw ex.rethrowFromSystemServer();
5657                }
5658
5659            } else {
5660                Slog.w(TAG, "Application " + data.info.getPackageName()
5661                      + " can be debugged on port 8100...");
5662            }
5663        }
5664
5665        // Allow application-generated systrace messages if we're debuggable.
5666        boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
5667        Trace.setAppTracingAllowed(isAppDebuggable);
5668        ThreadedRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
5669        if (isAppDebuggable && data.enableBinderTracking) {
5670            Binder.enableTracing();
5671        }
5672
5673        /**
5674         * Initialize the default http proxy in this process for the reasons we set the time zone.
5675         */
5676        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies");
5677        final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
5678        if (b != null) {
5679            // In pre-boot mode (doing initial launch to collect password), not
5680            // all system is up.  This includes the connectivity service, so don't
5681            // crash if we can't get it.
5682            final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
5683            try {
5684                final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
5685                Proxy.setHttpProxySystemProperty(proxyInfo);
5686            } catch (RemoteException e) {
5687                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
5688                throw e.rethrowFromSystemServer();
5689            }
5690        }
5691        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
5692
5693        // Instrumentation info affects the class loader, so load it before
5694        // setting up the app context.
5695        final InstrumentationInfo ii;
5696        if (data.instrumentationName != null) {
5697            try {
5698                ii = new ApplicationPackageManager(null, getPackageManager())
5699                        .getInstrumentationInfo(data.instrumentationName, 0);
5700            } catch (PackageManager.NameNotFoundException e) {
5701                throw new RuntimeException(
5702                        "Unable to find instrumentation info for: " + data.instrumentationName);
5703            }
5704
5705            mInstrumentationPackageName = ii.packageName;
5706            mInstrumentationAppDir = ii.sourceDir;
5707            mInstrumentationSplitAppDirs = ii.splitSourceDirs;
5708            mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
5709            mInstrumentedAppDir = data.info.getAppDir();
5710            mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
5711            mInstrumentedLibDir = data.info.getLibDir();
5712        } else {
5713            ii = null;
5714        }
5715
5716        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
5717        updateLocaleListFromAppContext(appContext,
5718                mResourcesManager.getConfiguration().getLocales());
5719
5720        if (!Process.isIsolated()) {
5721            final int oldMask = StrictMode.allowThreadDiskWritesMask();
5722            try {
5723                setupGraphicsSupport(appContext);
5724            } finally {
5725                StrictMode.setThreadPolicyMask(oldMask);
5726            }
5727        } else {
5728            ThreadedRenderer.setIsolatedProcess(true);
5729        }
5730
5731        // If we use profiles, setup the dex reporter to notify package manager
5732        // of any relevant dex loads. The idle maintenance job will use the information
5733        // reported to optimize the loaded dex files.
5734        // Note that we only need one global reporter per app.
5735        // Make sure we do this before calling onCreate so that we can capture the
5736        // complete application startup.
5737        if (SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
5738            BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
5739        }
5740
5741        // Install the Network Security Config Provider. This must happen before the application
5742        // code is loaded to prevent issues with instances of TLS objects being created before
5743        // the provider is installed.
5744        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "NetworkSecurityConfigProvider.install");
5745        NetworkSecurityConfigProvider.install(appContext);
5746        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
5747
5748        // Continue loading instrumentation.
5749        if (ii != null) {
5750            ApplicationInfo instrApp;
5751            try {
5752                instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
5753                        UserHandle.myUserId());
5754            } catch (RemoteException e) {
5755                instrApp = null;
5756            }
5757            if (instrApp == null) {
5758                instrApp = new ApplicationInfo();
5759            }
5760            ii.copyTo(instrApp);
5761            instrApp.initForUser(UserHandle.myUserId());
5762            final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
5763                    appContext.getClassLoader(), false, true, false);
5764            final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
5765
5766            try {
5767                final ClassLoader cl = instrContext.getClassLoader();
5768                mInstrumentation = (Instrumentation)
5769                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
5770            } catch (Exception e) {
5771                throw new RuntimeException(
5772                    "Unable to instantiate instrumentation "
5773                    + data.instrumentationName + ": " + e.toString(), e);
5774            }
5775
5776            final ComponentName component = new ComponentName(ii.packageName, ii.name);
5777            mInstrumentation.init(this, instrContext, appContext, component,
5778                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
5779
5780            if (mProfiler.profileFile != null && !ii.handleProfiling
5781                    && mProfiler.profileFd == null) {
5782                mProfiler.handlingProfiling = true;
5783                final File file = new File(mProfiler.profileFile);
5784                file.getParentFile().mkdirs();
5785                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
5786            }
5787        } else {
5788            mInstrumentation = new Instrumentation();
5789            mInstrumentation.basicInit(this);
5790        }
5791
5792        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
5793            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
5794        } else {
5795            // Small heap, clamp to the current growth limit and let the heap release
5796            // pages after the growth limit to the non growth limit capacity. b/18387825
5797            dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
5798        }
5799
5800        // Allow disk access during application and provider setup. This could
5801        // block processing ordered broadcasts, but later processing would
5802        // probably end up doing the same disk access.
5803        Application app;
5804        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
5805        final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
5806        try {
5807            // If the app is being launched for full backup or restore, bring it up in
5808            // a restricted environment with the base application class.
5809            app = data.info.makeApplication(data.restrictedBackupMode, null);
5810
5811            // Propagate autofill compat state
5812            app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
5813
5814            mInitialApplication = app;
5815
5816            // don't bring up providers in restricted mode; they may depend on the
5817            // app's custom Application class
5818            if (!data.restrictedBackupMode) {
5819                if (!ArrayUtils.isEmpty(data.providers)) {
5820                    installContentProviders(app, data.providers);
5821                    // For process that contains content providers, we want to
5822                    // ensure that the JIT is enabled "at some point".
5823                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
5824                }
5825            }
5826
5827            // Do this after providers, since instrumentation tests generally start their
5828            // test thread at this point, and we don't want that racing.
5829            try {
5830                mInstrumentation.onCreate(data.instrumentationArgs);
5831            }
5832            catch (Exception e) {
5833                throw new RuntimeException(
5834                    "Exception thrown in onCreate() of "
5835                    + data.instrumentationName + ": " + e.toString(), e);
5836            }
5837            try {
5838                mInstrumentation.callApplicationOnCreate(app);
5839            } catch (Exception e) {
5840                if (!mInstrumentation.onException(app, e)) {
5841                    throw new RuntimeException(
5842                      "Unable to create application " + app.getClass().getName()
5843                      + ": " + e.toString(), e);
5844                }
5845            }
5846        } finally {
5847            // If the app targets < O-MR1, or doesn't change the thread policy
5848            // during startup, clobber the policy to maintain behavior of b/36951662
5849            if (data.appInfo.targetSdkVersion <= Build.VERSION_CODES.O
5850                    || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
5851                StrictMode.setThreadPolicy(savedPolicy);
5852            }
5853        }
5854
5855        // Preload fonts resources
5856        FontsContract.setApplicationContextForResources(appContext);
5857        if (!Process.isIsolated()) {
5858            try {
5859                final ApplicationInfo info =
5860                        getPackageManager().getApplicationInfo(
5861                                data.appInfo.packageName,
5862                                PackageManager.GET_META_DATA /*flags*/,
5863                                UserHandle.myUserId());
5864                if (info.metaData != null) {
5865                    final int preloadedFontsResource = info.metaData.getInt(
5866                            ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
5867                    if (preloadedFontsResource != 0) {
5868                        data.info.getResources().preloadFonts(preloadedFontsResource);
5869                    }
5870                }
5871            } catch (RemoteException e) {
5872                throw e.rethrowFromSystemServer();
5873            }
5874        }
5875    }
5876
5877    /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
5878        IActivityManager am = ActivityManager.getService();
5879        if (mProfiler.profileFile != null && mProfiler.handlingProfiling
5880                && mProfiler.profileFd == null) {
5881            Debug.stopMethodTracing();
5882        }
5883        //Slog.i(TAG, "am: " + ActivityManager.getService()
5884        //      + ", app thr: " + mAppThread);
5885        try {
5886            am.finishInstrumentation(mAppThread, resultCode, results);
5887        } catch (RemoteException ex) {
5888            throw ex.rethrowFromSystemServer();
5889        }
5890    }
5891
5892    private void installContentProviders(
5893            Context context, List<ProviderInfo> providers) {
5894        final ArrayList<ContentProviderHolder> results = new ArrayList<>();
5895
5896        for (ProviderInfo cpi : providers) {
5897            if (DEBUG_PROVIDER) {
5898                StringBuilder buf = new StringBuilder(128);
5899                buf.append("Pub ");
5900                buf.append(cpi.authority);
5901                buf.append(": ");
5902                buf.append(cpi.name);
5903                Log.i(TAG, buf.toString());
5904            }
5905            ContentProviderHolder cph = installProvider(context, null, cpi,
5906                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
5907            if (cph != null) {
5908                cph.noReleaseNeeded = true;
5909                results.add(cph);
5910            }
5911        }
5912
5913        try {
5914            ActivityManager.getService().publishContentProviders(
5915                getApplicationThread(), results);
5916        } catch (RemoteException ex) {
5917            throw ex.rethrowFromSystemServer();
5918        }
5919    }
5920
5921    public final IContentProvider acquireProvider(
5922            Context c, String auth, int userId, boolean stable) {
5923        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
5924        if (provider != null) {
5925            return provider;
5926        }
5927
5928        // There is a possible race here.  Another thread may try to acquire
5929        // the same provider at the same time.  When this happens, we want to ensure
5930        // that the first one wins.
5931        // Note that we cannot hold the lock while acquiring and installing the
5932        // provider since it might take a long time to run and it could also potentially
5933        // be re-entrant in the case where the provider is in the same process.
5934        ContentProviderHolder holder = null;
5935        try {
5936            holder = ActivityManager.getService().getContentProvider(
5937                    getApplicationThread(), auth, userId, stable);
5938        } catch (RemoteException ex) {
5939            throw ex.rethrowFromSystemServer();
5940        }
5941        if (holder == null) {
5942            Slog.e(TAG, "Failed to find provider info for " + auth);
5943            return null;
5944        }
5945
5946        // Install provider will increment the reference count for us, and break
5947        // any ties in the race.
5948        holder = installProvider(c, holder, holder.info,
5949                true /*noisy*/, holder.noReleaseNeeded, stable);
5950        return holder.provider;
5951    }
5952
5953    private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
5954        if (stable) {
5955            prc.stableCount += 1;
5956            if (prc.stableCount == 1) {
5957                // We are acquiring a new stable reference on the provider.
5958                int unstableDelta;
5959                if (prc.removePending) {
5960                    // We have a pending remove operation, which is holding the
5961                    // last unstable reference.  At this point we are converting
5962                    // that unstable reference to our new stable reference.
5963                    unstableDelta = -1;
5964                    // Cancel the removal of the provider.
5965                    if (DEBUG_PROVIDER) {
5966                        Slog.v(TAG, "incProviderRef: stable "
5967                                + "snatched provider from the jaws of death");
5968                    }
5969                    prc.removePending = false;
5970                    // There is a race! It fails to remove the message, which
5971                    // will be handled in completeRemoveProvider().
5972                    mH.removeMessages(H.REMOVE_PROVIDER, prc);
5973                } else {
5974                    unstableDelta = 0;
5975                }
5976                try {
5977                    if (DEBUG_PROVIDER) {
5978                        Slog.v(TAG, "incProviderRef Now stable - "
5979                                + prc.holder.info.name + ": unstableDelta="
5980                                + unstableDelta);
5981                    }
5982                    ActivityManager.getService().refContentProvider(
5983                            prc.holder.connection, 1, unstableDelta);
5984                } catch (RemoteException e) {
5985                    //do nothing content provider object is dead any way
5986                }
5987            }
5988        } else {
5989            prc.unstableCount += 1;
5990            if (prc.unstableCount == 1) {
5991                // We are acquiring a new unstable reference on the provider.
5992                if (prc.removePending) {
5993                    // Oh look, we actually have a remove pending for the
5994                    // provider, which is still holding the last unstable
5995                    // reference.  We just need to cancel that to take new
5996                    // ownership of the reference.
5997                    if (DEBUG_PROVIDER) {
5998                        Slog.v(TAG, "incProviderRef: unstable "
5999                                + "snatched provider from the jaws of death");
6000                    }
6001                    prc.removePending = false;
6002                    mH.removeMessages(H.REMOVE_PROVIDER, prc);
6003                } else {
6004                    // First unstable ref, increment our count in the
6005                    // activity manager.
6006                    try {
6007                        if (DEBUG_PROVIDER) {
6008                            Slog.v(TAG, "incProviderRef: Now unstable - "
6009                                    + prc.holder.info.name);
6010                        }
6011                        ActivityManager.getService().refContentProvider(
6012                                prc.holder.connection, 0, 1);
6013                    } catch (RemoteException e) {
6014                        //do nothing content provider object is dead any way
6015                    }
6016                }
6017            }
6018        }
6019    }
6020
6021    public final IContentProvider acquireExistingProvider(
6022            Context c, String auth, int userId, boolean stable) {
6023        synchronized (mProviderMap) {
6024            final ProviderKey key = new ProviderKey(auth, userId);
6025            final ProviderClientRecord pr = mProviderMap.get(key);
6026            if (pr == null) {
6027                return null;
6028            }
6029
6030            IContentProvider provider = pr.mProvider;
6031            IBinder jBinder = provider.asBinder();
6032            if (!jBinder.isBinderAlive()) {
6033                // The hosting process of the provider has died; we can't
6034                // use this one.
6035                Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
6036                        + ": existing object's process dead");
6037                handleUnstableProviderDiedLocked(jBinder, true);
6038                return null;
6039            }
6040
6041            // Only increment the ref count if we have one.  If we don't then the
6042            // provider is not reference counted and never needs to be released.
6043            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
6044            if (prc != null) {
6045                incProviderRefLocked(prc, stable);
6046            }
6047            return provider;
6048        }
6049    }
6050
6051    public final boolean releaseProvider(IContentProvider provider, boolean stable) {
6052        if (provider == null) {
6053            return false;
6054        }
6055
6056        IBinder jBinder = provider.asBinder();
6057        synchronized (mProviderMap) {
6058            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
6059            if (prc == null) {
6060                // The provider has no ref count, no release is needed.
6061                return false;
6062            }
6063
6064            boolean lastRef = false;
6065            if (stable) {
6066                if (prc.stableCount == 0) {
6067                    if (DEBUG_PROVIDER) Slog.v(TAG,
6068                            "releaseProvider: stable ref count already 0, how?");
6069                    return false;
6070                }
6071                prc.stableCount -= 1;
6072                if (prc.stableCount == 0) {
6073                    // What we do at this point depends on whether there are
6074                    // any unstable refs left: if there are, we just tell the
6075                    // activity manager to decrement its stable count; if there
6076                    // aren't, we need to enqueue this provider to be removed,
6077                    // and convert to holding a single unstable ref while
6078                    // doing so.
6079                    lastRef = prc.unstableCount == 0;
6080                    try {
6081                        if (DEBUG_PROVIDER) {
6082                            Slog.v(TAG, "releaseProvider: No longer stable w/lastRef="
6083                                    + lastRef + " - " + prc.holder.info.name);
6084                        }
6085                        ActivityManager.getService().refContentProvider(
6086                                prc.holder.connection, -1, lastRef ? 1 : 0);
6087                    } catch (RemoteException e) {
6088                        //do nothing content provider object is dead any way
6089                    }
6090                }
6091            } else {
6092                if (prc.unstableCount == 0) {
6093                    if (DEBUG_PROVIDER) Slog.v(TAG,
6094                            "releaseProvider: unstable ref count already 0, how?");
6095                    return false;
6096                }
6097                prc.unstableCount -= 1;
6098                if (prc.unstableCount == 0) {
6099                    // If this is the last reference, we need to enqueue
6100                    // this provider to be removed instead of telling the
6101                    // activity manager to remove it at this point.
6102                    lastRef = prc.stableCount == 0;
6103                    if (!lastRef) {
6104                        try {
6105                            if (DEBUG_PROVIDER) {
6106                                Slog.v(TAG, "releaseProvider: No longer unstable - "
6107                                        + prc.holder.info.name);
6108                            }
6109                            ActivityManager.getService().refContentProvider(
6110                                    prc.holder.connection, 0, -1);
6111                        } catch (RemoteException e) {
6112                            //do nothing content provider object is dead any way
6113                        }
6114                    }
6115                }
6116            }
6117
6118            if (lastRef) {
6119                if (!prc.removePending) {
6120                    // Schedule the actual remove asynchronously, since we don't know the context
6121                    // this will be called in.
6122                    // TODO: it would be nice to post a delayed message, so
6123                    // if we come back and need the same provider quickly
6124                    // we will still have it available.
6125                    if (DEBUG_PROVIDER) {
6126                        Slog.v(TAG, "releaseProvider: Enqueueing pending removal - "
6127                                + prc.holder.info.name);
6128                    }
6129                    prc.removePending = true;
6130                    Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
6131                    mH.sendMessage(msg);
6132                } else {
6133                    Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
6134                }
6135            }
6136            return true;
6137        }
6138    }
6139
6140    final void completeRemoveProvider(ProviderRefCount prc) {
6141        synchronized (mProviderMap) {
6142            if (!prc.removePending) {
6143                // There was a race!  Some other client managed to acquire
6144                // the provider before the removal was completed.
6145                // Abort the removal.  We will do it later.
6146                if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, "
6147                        + "provider still in use");
6148                return;
6149            }
6150
6151            // More complicated race!! Some client managed to acquire the
6152            // provider and release it before the removal was completed.
6153            // Continue the removal, and abort the next remove message.
6154            prc.removePending = false;
6155
6156            final IBinder jBinder = prc.holder.provider.asBinder();
6157            ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
6158            if (existingPrc == prc) {
6159                mProviderRefCountMap.remove(jBinder);
6160            }
6161
6162            for (int i=mProviderMap.size()-1; i>=0; i--) {
6163                ProviderClientRecord pr = mProviderMap.valueAt(i);
6164                IBinder myBinder = pr.mProvider.asBinder();
6165                if (myBinder == jBinder) {
6166                    mProviderMap.removeAt(i);
6167                }
6168            }
6169        }
6170
6171        try {
6172            if (DEBUG_PROVIDER) {
6173                Slog.v(TAG, "removeProvider: Invoking ActivityManagerService."
6174                        + "removeContentProvider(" + prc.holder.info.name + ")");
6175            }
6176            ActivityManager.getService().removeContentProvider(
6177                    prc.holder.connection, false);
6178        } catch (RemoteException e) {
6179            //do nothing content provider object is dead any way
6180        }
6181    }
6182
6183    final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
6184        synchronized (mProviderMap) {
6185            handleUnstableProviderDiedLocked(provider, fromClient);
6186        }
6187    }
6188
6189    final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) {
6190        ProviderRefCount prc = mProviderRefCountMap.get(provider);
6191        if (prc != null) {
6192            if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
6193                    + provider + " " + prc.holder.info.name);
6194            mProviderRefCountMap.remove(provider);
6195            for (int i=mProviderMap.size()-1; i>=0; i--) {
6196                ProviderClientRecord pr = mProviderMap.valueAt(i);
6197                if (pr != null && pr.mProvider.asBinder() == provider) {
6198                    Slog.i(TAG, "Removing dead content provider:" + pr.mProvider.toString());
6199                    mProviderMap.removeAt(i);
6200                }
6201            }
6202
6203            if (fromClient) {
6204                // We found out about this due to execution in our client
6205                // code.  Tell the activity manager about it now, to ensure
6206                // that the next time we go to do anything with the provider
6207                // it knows it is dead (so we don't race with its death
6208                // notification).
6209                try {
6210                    ActivityManager.getService().unstableProviderDied(
6211                            prc.holder.connection);
6212                } catch (RemoteException e) {
6213                    //do nothing content provider object is dead any way
6214                }
6215            }
6216        }
6217    }
6218
6219    final void appNotRespondingViaProvider(IBinder provider) {
6220        synchronized (mProviderMap) {
6221            ProviderRefCount prc = mProviderRefCountMap.get(provider);
6222            if (prc != null) {
6223                try {
6224                    ActivityManager.getService()
6225                            .appNotRespondingViaProvider(prc.holder.connection);
6226                } catch (RemoteException e) {
6227                    throw e.rethrowFromSystemServer();
6228                }
6229            }
6230        }
6231    }
6232
6233    private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
6234            ContentProvider localProvider, ContentProviderHolder holder) {
6235        final String auths[] = holder.info.authority.split(";");
6236        final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
6237
6238        if (provider != null) {
6239            // If this provider is hosted by the core OS and cannot be upgraded,
6240            // then I guess we're okay doing blocking calls to it.
6241            for (String auth : auths) {
6242                switch (auth) {
6243                    case ContactsContract.AUTHORITY:
6244                    case CallLog.AUTHORITY:
6245                    case CallLog.SHADOW_AUTHORITY:
6246                    case BlockedNumberContract.AUTHORITY:
6247                    case CalendarContract.AUTHORITY:
6248                    case Downloads.Impl.AUTHORITY:
6249                    case "telephony":
6250                        Binder.allowBlocking(provider.asBinder());
6251                }
6252            }
6253        }
6254
6255        final ProviderClientRecord pcr = new ProviderClientRecord(
6256                auths, provider, localProvider, holder);
6257        for (String auth : auths) {
6258            final ProviderKey key = new ProviderKey(auth, userId);
6259            final ProviderClientRecord existing = mProviderMap.get(key);
6260            if (existing != null) {
6261                Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
6262                        + " already published as " + auth);
6263            } else {
6264                mProviderMap.put(key, pcr);
6265            }
6266        }
6267        return pcr;
6268    }
6269
6270    /**
6271     * Installs the provider.
6272     *
6273     * Providers that are local to the process or that come from the system server
6274     * may be installed permanently which is indicated by setting noReleaseNeeded to true.
6275     * Other remote providers are reference counted.  The initial reference count
6276     * for all reference counted providers is one.  Providers that are not reference
6277     * counted do not have a reference count (at all).
6278     *
6279     * This method detects when a provider has already been installed.  When this happens,
6280     * it increments the reference count of the existing provider (if appropriate)
6281     * and returns the existing provider.  This can happen due to concurrent
6282     * attempts to acquire the same provider.
6283     */
6284    private ContentProviderHolder installProvider(Context context,
6285            ContentProviderHolder holder, ProviderInfo info,
6286            boolean noisy, boolean noReleaseNeeded, boolean stable) {
6287        ContentProvider localProvider = null;
6288        IContentProvider provider;
6289        if (holder == null || holder.provider == null) {
6290            if (DEBUG_PROVIDER || noisy) {
6291                Slog.d(TAG, "Loading provider " + info.authority + ": "
6292                        + info.name);
6293            }
6294            Context c = null;
6295            ApplicationInfo ai = info.applicationInfo;
6296            if (context.getPackageName().equals(ai.packageName)) {
6297                c = context;
6298            } else if (mInitialApplication != null &&
6299                    mInitialApplication.getPackageName().equals(ai.packageName)) {
6300                c = mInitialApplication;
6301            } else {
6302                try {
6303                    c = context.createPackageContext(ai.packageName,
6304                            Context.CONTEXT_INCLUDE_CODE);
6305                } catch (PackageManager.NameNotFoundException e) {
6306                    // Ignore
6307                }
6308            }
6309            if (c == null) {
6310                Slog.w(TAG, "Unable to get context for package " +
6311                      ai.packageName +
6312                      " while loading content provider " +
6313                      info.name);
6314                return null;
6315            }
6316
6317            if (info.splitName != null) {
6318                try {
6319                    c = c.createContextForSplit(info.splitName);
6320                } catch (NameNotFoundException e) {
6321                    throw new RuntimeException(e);
6322                }
6323            }
6324
6325            try {
6326                final java.lang.ClassLoader cl = c.getClassLoader();
6327                LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
6328                if (packageInfo == null) {
6329                    // System startup case.
6330                    packageInfo = getSystemContext().mPackageInfo;
6331                }
6332                localProvider = packageInfo.getAppFactory()
6333                        .instantiateProvider(cl, info.name);
6334                provider = localProvider.getIContentProvider();
6335                if (provider == null) {
6336                    Slog.e(TAG, "Failed to instantiate class " +
6337                          info.name + " from sourceDir " +
6338                          info.applicationInfo.sourceDir);
6339                    return null;
6340                }
6341                if (DEBUG_PROVIDER) Slog.v(
6342                    TAG, "Instantiating local provider " + info.name);
6343                // XXX Need to create the correct context for this provider.
6344                localProvider.attachInfo(c, info);
6345            } catch (java.lang.Exception e) {
6346                if (!mInstrumentation.onException(null, e)) {
6347                    throw new RuntimeException(
6348                            "Unable to get provider " + info.name
6349                            + ": " + e.toString(), e);
6350                }
6351                return null;
6352            }
6353        } else {
6354            provider = holder.provider;
6355            if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
6356                    + info.name);
6357        }
6358
6359        ContentProviderHolder retHolder;
6360
6361        synchronized (mProviderMap) {
6362            if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
6363                    + " / " + info.name);
6364            IBinder jBinder = provider.asBinder();
6365            if (localProvider != null) {
6366                ComponentName cname = new ComponentName(info.packageName, info.name);
6367                ProviderClientRecord pr = mLocalProvidersByName.get(cname);
6368                if (pr != null) {
6369                    if (DEBUG_PROVIDER) {
6370                        Slog.v(TAG, "installProvider: lost the race, "
6371                                + "using existing local provider");
6372                    }
6373                    provider = pr.mProvider;
6374                } else {
6375                    holder = new ContentProviderHolder(info);
6376                    holder.provider = provider;
6377                    holder.noReleaseNeeded = true;
6378                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
6379                    mLocalProviders.put(jBinder, pr);
6380                    mLocalProvidersByName.put(cname, pr);
6381                }
6382                retHolder = pr.mHolder;
6383            } else {
6384                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
6385                if (prc != null) {
6386                    if (DEBUG_PROVIDER) {
6387                        Slog.v(TAG, "installProvider: lost the race, updating ref count");
6388                    }
6389                    // We need to transfer our new reference to the existing
6390                    // ref count, releasing the old one...  but only if
6391                    // release is needed (that is, it is not running in the
6392                    // system process).
6393                    if (!noReleaseNeeded) {
6394                        incProviderRefLocked(prc, stable);
6395                        try {
6396                            ActivityManager.getService().removeContentProvider(
6397                                    holder.connection, stable);
6398                        } catch (RemoteException e) {
6399                            //do nothing content provider object is dead any way
6400                        }
6401                    }
6402                } else {
6403                    ProviderClientRecord client = installProviderAuthoritiesLocked(
6404                            provider, localProvider, holder);
6405                    if (noReleaseNeeded) {
6406                        prc = new ProviderRefCount(holder, client, 1000, 1000);
6407                    } else {
6408                        prc = stable
6409                                ? new ProviderRefCount(holder, client, 1, 0)
6410                                : new ProviderRefCount(holder, client, 0, 1);
6411                    }
6412                    mProviderRefCountMap.put(jBinder, prc);
6413                }
6414                retHolder = prc.holder;
6415            }
6416        }
6417        return retHolder;
6418    }
6419
6420    private void handleRunIsolatedEntryPoint(String entryPoint, String[] entryPointArgs) {
6421        try {
6422            Method main = Class.forName(entryPoint).getMethod("main", String[].class);
6423            main.invoke(null, new Object[]{entryPointArgs});
6424        } catch (ReflectiveOperationException e) {
6425            throw new AndroidRuntimeException("runIsolatedEntryPoint failed", e);
6426        }
6427        // The process will be empty after this method returns; exit the VM now.
6428        System.exit(0);
6429    }
6430
6431    private void attach(boolean system, long startSeq) {
6432        sCurrentActivityThread = this;
6433        mSystemThread = system;
6434        if (!system) {
6435            ViewRootImpl.addFirstDrawHandler(new Runnable() {
6436                @Override
6437                public void run() {
6438                    ensureJitEnabled();
6439                }
6440            });
6441            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
6442                                                    UserHandle.myUserId());
6443            RuntimeInit.setApplicationObject(mAppThread.asBinder());
6444            final IActivityManager mgr = ActivityManager.getService();
6445            try {
6446                mgr.attachApplication(mAppThread, startSeq);
6447            } catch (RemoteException ex) {
6448                throw ex.rethrowFromSystemServer();
6449            }
6450            // Watch for getting close to heap limit.
6451            BinderInternal.addGcWatcher(new Runnable() {
6452                @Override public void run() {
6453                    if (!mSomeActivitiesChanged) {
6454                        return;
6455                    }
6456                    Runtime runtime = Runtime.getRuntime();
6457                    long dalvikMax = runtime.maxMemory();
6458                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
6459                    if (dalvikUsed > ((3*dalvikMax)/4)) {
6460                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
6461                                + " total=" + (runtime.totalMemory()/1024)
6462                                + " used=" + (dalvikUsed/1024));
6463                        mSomeActivitiesChanged = false;
6464                        try {
6465                            mgr.releaseSomeActivities(mAppThread);
6466                        } catch (RemoteException e) {
6467                            throw e.rethrowFromSystemServer();
6468                        }
6469                    }
6470                }
6471            });
6472        } else {
6473            // Don't set application object here -- if the system crashes,
6474            // we can't display an alert, we just want to die die die.
6475            android.ddm.DdmHandleAppName.setAppName("system_process",
6476                    UserHandle.myUserId());
6477            try {
6478                mInstrumentation = new Instrumentation();
6479                mInstrumentation.basicInit(this);
6480                ContextImpl context = ContextImpl.createAppContext(
6481                        this, getSystemContext().mPackageInfo);
6482                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
6483                mInitialApplication.onCreate();
6484            } catch (Exception e) {
6485                throw new RuntimeException(
6486                        "Unable to instantiate Application():" + e.toString(), e);
6487            }
6488        }
6489
6490        // add dropbox logging to libcore
6491        DropBox.setReporter(new DropBoxReporter());
6492
6493        ViewRootImpl.ConfigChangedCallback configChangedCallback
6494                = (Configuration globalConfig) -> {
6495            synchronized (mResourcesManager) {
6496                // We need to apply this change to the resources immediately, because upon returning
6497                // the view hierarchy will be informed about it.
6498                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
6499                        null /* compat */)) {
6500                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
6501                            mResourcesManager.getConfiguration().getLocales());
6502
6503                    // This actually changed the resources! Tell everyone about it.
6504                    if (mPendingConfiguration == null
6505                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
6506                        mPendingConfiguration = globalConfig;
6507                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
6508                    }
6509                }
6510            }
6511        };
6512        ViewRootImpl.addConfigCallback(configChangedCallback);
6513    }
6514
6515    public static ActivityThread systemMain() {
6516        // The system process on low-memory devices do not get to use hardware
6517        // accelerated drawing, since this can add too much overhead to the
6518        // process.
6519        if (!ActivityManager.isHighEndGfx()) {
6520            ThreadedRenderer.disable(true);
6521        } else {
6522            ThreadedRenderer.enableForegroundTrimming();
6523        }
6524        ActivityThread thread = new ActivityThread();
6525        thread.attach(true, 0);
6526        return thread;
6527    }
6528
6529    public final void installSystemProviders(List<ProviderInfo> providers) {
6530        if (providers != null) {
6531            installContentProviders(mInitialApplication, providers);
6532        }
6533    }
6534
6535    public int getIntCoreSetting(String key, int defaultValue) {
6536        synchronized (mResourcesManager) {
6537            if (mCoreSettings != null) {
6538                return mCoreSettings.getInt(key, defaultValue);
6539            }
6540            return defaultValue;
6541        }
6542    }
6543
6544    private static class EventLoggingReporter implements EventLogger.Reporter {
6545        @Override
6546        public void report (int code, Object... list) {
6547            EventLog.writeEvent(code, list);
6548        }
6549    }
6550
6551    private class DropBoxReporter implements DropBox.Reporter {
6552
6553        private DropBoxManager dropBox;
6554
6555        public DropBoxReporter() {}
6556
6557        @Override
6558        public void addData(String tag, byte[] data, int flags) {
6559            ensureInitialized();
6560            dropBox.addData(tag, data, flags);
6561        }
6562
6563        @Override
6564        public void addText(String tag, String data) {
6565            ensureInitialized();
6566            dropBox.addText(tag, data);
6567        }
6568
6569        private synchronized void ensureInitialized() {
6570            if (dropBox == null) {
6571                dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
6572            }
6573        }
6574    }
6575
6576    public static void main(String[] args) {
6577        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
6578
6579        // CloseGuard defaults to true and can be quite spammy.  We
6580        // disable it here, but selectively enable it later (via
6581        // StrictMode) on debug builds, but using DropBox, not logs.
6582        CloseGuard.setEnabled(false);
6583
6584        Environment.initForCurrentUser();
6585
6586        // Set the reporter for event logging in libcore
6587        EventLogger.setReporter(new EventLoggingReporter());
6588
6589        // Make sure TrustedCertificateStore looks in the right place for CA certificates
6590        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
6591        TrustedCertificateStore.setDefaultUserDirectory(configDir);
6592
6593        Process.setArgV0("<pre-initialized>");
6594
6595        Looper.prepareMainLooper();
6596
6597        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
6598        // It will be in the format "seq=114"
6599        long startSeq = 0;
6600        if (args != null) {
6601            for (int i = args.length - 1; i >= 0; --i) {
6602                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
6603                    startSeq = Long.parseLong(
6604                            args[i].substring(PROC_START_SEQ_IDENT.length()));
6605                }
6606            }
6607        }
6608        ActivityThread thread = new ActivityThread();
6609        thread.attach(false, startSeq);
6610
6611        if (sMainThreadHandler == null) {
6612            sMainThreadHandler = thread.getHandler();
6613        }
6614
6615        if (false) {
6616            Looper.myLooper().setMessageLogging(new
6617                    LogPrinter(Log.DEBUG, "ActivityThread"));
6618        }
6619
6620        // End of event ActivityThreadMain.
6621        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
6622        Looper.loop();
6623
6624        throw new RuntimeException("Main thread loop unexpectedly exited");
6625    }
6626
6627    // ------------------ Regular JNI ------------------------
6628
6629    private native void nDumpGraphicsInfo(FileDescriptor fd);
6630}
6631