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