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