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