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