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