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