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