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