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