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