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