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