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