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