OSDN Git Service

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