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