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