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