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