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