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