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