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