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