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