• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ComponentCallbacks;
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.PackageManager;
33 import android.content.pm.ProviderInfo;
34 import android.content.pm.ServiceInfo;
35 import android.content.res.AssetManager;
36 import android.content.res.CompatibilityInfo;
37 import android.content.res.Configuration;
38 import android.content.res.Resources;
39 import android.database.sqlite.SQLiteDatabase;
40 import android.database.sqlite.SQLiteDebug;
41 import android.database.sqlite.SQLiteDebug.DbStats;
42 import android.graphics.Bitmap;
43 import android.graphics.Canvas;
44 import android.os.Build;
45 import android.os.Bundle;
46 import android.os.Debug;
47 import android.os.Handler;
48 import android.os.IBinder;
49 import android.os.Looper;
50 import android.os.Message;
51 import android.os.MessageQueue;
52 import android.os.ParcelFileDescriptor;
53 import android.os.Process;
54 import android.os.RemoteException;
55 import android.os.ServiceManager;
56 import android.os.StrictMode;
57 import android.os.SystemClock;
58 import android.util.AndroidRuntimeException;
59 import android.util.Config;
60 import android.util.DisplayMetrics;
61 import android.util.EventLog;
62 import android.util.Log;
63 import android.util.LogPrinter;
64 import android.util.Slog;
65 import android.view.Display;
66 import android.view.View;
67 import android.view.ViewDebug;
68 import android.view.ViewManager;
69 import android.view.ViewRoot;
70 import android.view.Window;
71 import android.view.WindowManager;
72 import android.view.WindowManagerImpl;
73 
74 import com.android.internal.os.BinderInternal;
75 import com.android.internal.os.RuntimeInit;
76 import com.android.internal.os.SamplingProfilerIntegration;
77 
78 import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
79 
80 import java.io.File;
81 import java.io.FileDescriptor;
82 import java.io.FileOutputStream;
83 import java.io.IOException;
84 import java.io.PrintWriter;
85 import java.lang.ref.WeakReference;
86 import java.util.ArrayList;
87 import java.util.HashMap;
88 import java.util.Iterator;
89 import java.util.List;
90 import java.util.Locale;
91 import java.util.Map;
92 import java.util.TimeZone;
93 import java.util.regex.Pattern;
94 
95 import dalvik.system.SamplingProfiler;
96 
97 final class SuperNotCalledException extends AndroidRuntimeException {
SuperNotCalledException(String msg)98     public SuperNotCalledException(String msg) {
99         super(msg);
100     }
101 }
102 
103 final class RemoteServiceException extends AndroidRuntimeException {
RemoteServiceException(String msg)104     public RemoteServiceException(String msg) {
105         super(msg);
106     }
107 }
108 
109 /**
110  * This manages the execution of the main thread in an
111  * application process, scheduling and executing activities,
112  * broadcasts, and other operations on it as the activity
113  * manager requests.
114  *
115  * {@hide}
116  */
117 public final class ActivityThread {
118     static final String TAG = "ActivityThread";
119     private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
120     private static final boolean DEBUG = false;
121     static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
122     static final boolean DEBUG_MESSAGES = false;
123     static final boolean DEBUG_BROADCAST = false;
124     private static final boolean DEBUG_RESULTS = false;
125     private static final boolean DEBUG_BACKUP = false;
126     private static final boolean DEBUG_CONFIGURATION = false;
127     private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
128     private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
129     private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
130     private static final int LOG_ON_PAUSE_CALLED = 30021;
131     private static final int LOG_ON_RESUME_CALLED = 30022;
132 
133     static ContextImpl mSystemContext = null;
134 
135     static IPackageManager sPackageManager;
136 
137     final ApplicationThread mAppThread = new ApplicationThread();
138     final Looper mLooper = Looper.myLooper();
139     final H mH = new H();
140     final HashMap<IBinder, ActivityClientRecord> mActivities
141             = new HashMap<IBinder, ActivityClientRecord>();
142     // List of new activities (via ActivityRecord.nextIdle) that should
143     // be reported when next we idle.
144     ActivityClientRecord mNewActivities = null;
145     // Number of activities that are currently visible on-screen.
146     int mNumVisibleActivities = 0;
147     final HashMap<IBinder, Service> mServices
148             = new HashMap<IBinder, Service>();
149     AppBindData mBoundApplication;
150     Configuration mConfiguration;
151     Configuration mResConfiguration;
152     Application mInitialApplication;
153     final ArrayList<Application> mAllApplications
154             = new ArrayList<Application>();
155     // set of instantiated backup agents, keyed by package name
156     final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
157     static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal();
158     Instrumentation mInstrumentation;
159     String mInstrumentationAppDir = null;
160     String mInstrumentationAppPackage = null;
161     String mInstrumentedAppDir = null;
162     boolean mSystemThread = false;
163     boolean mJitEnabled = false;
164 
165     // These can be accessed by multiple threads; mPackages is the lock.
166     // XXX For now we keep around information about all packages we have
167     // seen, not removing entries from this map.
168     final HashMap<String, WeakReference<LoadedApk>> mPackages
169             = new HashMap<String, WeakReference<LoadedApk>>();
170     final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
171             = new HashMap<String, WeakReference<LoadedApk>>();
172     Display mDisplay = null;
173     DisplayMetrics mDisplayMetrics = null;
174     final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
175             = new HashMap<ResourcesKey, WeakReference<Resources> >();
176     final ArrayList<ActivityClientRecord> mRelaunchingActivities
177             = new ArrayList<ActivityClientRecord>();
178     Configuration mPendingConfiguration = null;
179 
180     // The lock of mProviderMap protects the following variables.
181     final HashMap<String, ProviderClientRecord> mProviderMap
182         = new HashMap<String, ProviderClientRecord>();
183     final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
184         = new HashMap<IBinder, ProviderRefCount>();
185     final HashMap<IBinder, ProviderClientRecord> mLocalProviders
186         = new HashMap<IBinder, ProviderClientRecord>();
187 
188     final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
189         = new HashMap<Activity, ArrayList<OnActivityPausedListener>>();
190 
191     final GcIdler mGcIdler = new GcIdler();
192     boolean mGcIdlerScheduled = false;
193 
194     static Handler sMainThreadHandler;  // set once in main()
195 
196     private static final class ActivityClientRecord {
197         IBinder token;
198         int ident;
199         Intent intent;
200         Bundle state;
201         Activity activity;
202         Window window;
203         Activity parent;
204         String embeddedID;
205         Object lastNonConfigurationInstance;
206         HashMap<String,Object> lastNonConfigurationChildInstances;
207         boolean paused;
208         boolean stopped;
209         boolean hideForNow;
210         Configuration newConfig;
211         Configuration createdConfig;
212         ActivityClientRecord nextIdle;
213 
214         ActivityInfo activityInfo;
215         LoadedApk packageInfo;
216 
217         List<ResultInfo> pendingResults;
218         List<Intent> pendingIntents;
219 
220         boolean startsNotResumed;
221         boolean isForward;
222 
ActivityClientRecord()223         ActivityClientRecord() {
224             parent = null;
225             embeddedID = null;
226             paused = false;
227             stopped = false;
228             hideForNow = false;
229             nextIdle = null;
230         }
231 
toString()232         public String toString() {
233             ComponentName componentName = intent.getComponent();
234             return "ActivityRecord{"
235                 + Integer.toHexString(System.identityHashCode(this))
236                 + " token=" + token + " " + (componentName == null
237                         ? "no component name" : componentName.toShortString())
238                 + "}";
239         }
240     }
241 
242     private final class ProviderClientRecord implements IBinder.DeathRecipient {
243         final String mName;
244         final IContentProvider mProvider;
245         final ContentProvider mLocalProvider;
246 
ProviderClientRecord(String name, IContentProvider provider, ContentProvider localProvider)247         ProviderClientRecord(String name, IContentProvider provider,
248                 ContentProvider localProvider) {
249             mName = name;
250             mProvider = provider;
251             mLocalProvider = localProvider;
252         }
253 
binderDied()254         public void binderDied() {
255             removeDeadProvider(mName, mProvider);
256         }
257     }
258 
259     private static final class NewIntentData {
260         List<Intent> intents;
261         IBinder token;
toString()262         public String toString() {
263             return "NewIntentData{intents=" + intents + " token=" + token + "}";
264         }
265     }
266 
267     private static final class ReceiverData {
268         Intent intent;
269         ActivityInfo info;
270         int resultCode;
271         String resultData;
272         Bundle resultExtras;
273         boolean sync;
274         boolean resultAbort;
toString()275         public String toString() {
276             return "ReceiverData{intent=" + intent + " packageName=" +
277             info.packageName + " resultCode=" + resultCode
278             + " resultData=" + resultData + " resultExtras=" + resultExtras + "}";
279         }
280     }
281 
282     private static final class CreateBackupAgentData {
283         ApplicationInfo appInfo;
284         int backupMode;
toString()285         public String toString() {
286             return "CreateBackupAgentData{appInfo=" + appInfo
287                     + " backupAgent=" + appInfo.backupAgentName
288                     + " mode=" + backupMode + "}";
289         }
290     }
291 
292     private static final class CreateServiceData {
293         IBinder token;
294         ServiceInfo info;
295         Intent intent;
toString()296         public String toString() {
297             return "CreateServiceData{token=" + token + " className="
298             + info.name + " packageName=" + info.packageName
299             + " intent=" + intent + "}";
300         }
301     }
302 
303     private static final class BindServiceData {
304         IBinder token;
305         Intent intent;
306         boolean rebind;
toString()307         public String toString() {
308             return "BindServiceData{token=" + token + " intent=" + intent + "}";
309         }
310     }
311 
312     private static final class ServiceArgsData {
313         IBinder token;
314         int startId;
315         int flags;
316         Intent args;
toString()317         public String toString() {
318             return "ServiceArgsData{token=" + token + " startId=" + startId
319             + " args=" + args + "}";
320         }
321     }
322 
323     private static final class AppBindData {
324         LoadedApk info;
325         String processName;
326         ApplicationInfo appInfo;
327         List<ProviderInfo> providers;
328         ComponentName instrumentationName;
329         String profileFile;
330         Bundle instrumentationArgs;
331         IInstrumentationWatcher instrumentationWatcher;
332         int debugMode;
333         boolean restrictedBackupMode;
334         Configuration config;
335         boolean handlingProfiling;
toString()336         public String toString() {
337             return "AppBindData{appInfo=" + appInfo + "}";
338         }
339     }
340 
341     private static final class DumpServiceInfo {
342         FileDescriptor fd;
343         IBinder service;
344         String[] args;
345         boolean dumped;
346     }
347 
348     private static final class ResultData {
349         IBinder token;
350         List<ResultInfo> results;
toString()351         public String toString() {
352             return "ResultData{token=" + token + " results" + results + "}";
353         }
354     }
355 
356     private static final class ContextCleanupInfo {
357         ContextImpl context;
358         String what;
359         String who;
360     }
361 
362     private static final class ProfilerControlData {
363         String path;
364         ParcelFileDescriptor fd;
365     }
366 
367     private final class ApplicationThread extends ApplicationThreadNative {
368         private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
369         private static final String ONE_COUNT_COLUMN = "%17s %8d";
370         private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
371         private static final String TWO_COUNT_COLUMNS_DB = "%20s %8d %20s %8d";
372         private static final String DB_INFO_FORMAT = "  %8d %8d %14d  %s";
373 
374         // Formatting for checkin service - update version if row format changes
375         private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
376 
schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges)377         public final void schedulePauseActivity(IBinder token, boolean finished,
378                 boolean userLeaving, int configChanges) {
379             queueOrSendMessage(
380                     finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
381                     token,
382                     (userLeaving ? 1 : 0),
383                     configChanges);
384         }
385 
scheduleStopActivity(IBinder token, boolean showWindow, int configChanges)386         public final void scheduleStopActivity(IBinder token, boolean showWindow,
387                 int configChanges) {
388            queueOrSendMessage(
389                 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
390                 token, 0, configChanges);
391         }
392 
scheduleWindowVisibility(IBinder token, boolean showWindow)393         public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
394             queueOrSendMessage(
395                 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
396                 token);
397         }
398 
scheduleResumeActivity(IBinder token, boolean isForward)399         public final void scheduleResumeActivity(IBinder token, boolean isForward) {
400             queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
401         }
402 
scheduleSendResult(IBinder token, List<ResultInfo> results)403         public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
404             ResultData res = new ResultData();
405             res.token = token;
406             res.results = results;
407             queueOrSendMessage(H.SEND_RESULT, res);
408         }
409 
410         // we use token to identify this activity without having to send the
411         // activity itself back to the activity manager. (matters more with ipc)
scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Bundle state, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)412         public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
413                 ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
414                 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
415             ActivityClientRecord r = new ActivityClientRecord();
416 
417             r.token = token;
418             r.ident = ident;
419             r.intent = intent;
420             r.activityInfo = info;
421             r.state = state;
422 
423             r.pendingResults = pendingResults;
424             r.pendingIntents = pendingNewIntents;
425 
426             r.startsNotResumed = notResumed;
427             r.isForward = isForward;
428 
429             queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
430         }
431 
scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config)432         public final void scheduleRelaunchActivity(IBinder token,
433                 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
434                 int configChanges, boolean notResumed, Configuration config) {
435             ActivityClientRecord r = new ActivityClientRecord();
436 
437             r.token = token;
438             r.pendingResults = pendingResults;
439             r.pendingIntents = pendingNewIntents;
440             r.startsNotResumed = notResumed;
441             r.createdConfig = config;
442 
443             synchronized (mPackages) {
444                 mRelaunchingActivities.add(r);
445             }
446 
447             queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
448         }
449 
scheduleNewIntent(List<Intent> intents, IBinder token)450         public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
451             NewIntentData data = new NewIntentData();
452             data.intents = intents;
453             data.token = token;
454 
455             queueOrSendMessage(H.NEW_INTENT, data);
456         }
457 
scheduleDestroyActivity(IBinder token, boolean finishing, int configChanges)458         public final void scheduleDestroyActivity(IBinder token, boolean finishing,
459                 int configChanges) {
460             queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
461                     configChanges);
462         }
463 
scheduleReceiver(Intent intent, ActivityInfo info, int resultCode, String data, Bundle extras, boolean sync)464         public final void scheduleReceiver(Intent intent, ActivityInfo info,
465                 int resultCode, String data, Bundle extras, boolean sync) {
466             ReceiverData r = new ReceiverData();
467 
468             r.intent = intent;
469             r.info = info;
470             r.resultCode = resultCode;
471             r.resultData = data;
472             r.resultExtras = extras;
473             r.sync = sync;
474 
475             queueOrSendMessage(H.RECEIVER, r);
476         }
477 
scheduleCreateBackupAgent(ApplicationInfo app, int backupMode)478         public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) {
479             CreateBackupAgentData d = new CreateBackupAgentData();
480             d.appInfo = app;
481             d.backupMode = backupMode;
482 
483             queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
484         }
485 
scheduleDestroyBackupAgent(ApplicationInfo app)486         public final void scheduleDestroyBackupAgent(ApplicationInfo app) {
487             CreateBackupAgentData d = new CreateBackupAgentData();
488             d.appInfo = app;
489 
490             queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
491         }
492 
scheduleCreateService(IBinder token, ServiceInfo info)493         public final void scheduleCreateService(IBinder token,
494                 ServiceInfo info) {
495             CreateServiceData s = new CreateServiceData();
496             s.token = token;
497             s.info = info;
498 
499             queueOrSendMessage(H.CREATE_SERVICE, s);
500         }
501 
scheduleBindService(IBinder token, Intent intent, boolean rebind)502         public final void scheduleBindService(IBinder token, Intent intent,
503                 boolean rebind) {
504             BindServiceData s = new BindServiceData();
505             s.token = token;
506             s.intent = intent;
507             s.rebind = rebind;
508 
509             queueOrSendMessage(H.BIND_SERVICE, s);
510         }
511 
scheduleUnbindService(IBinder token, Intent intent)512         public final void scheduleUnbindService(IBinder token, Intent intent) {
513             BindServiceData s = new BindServiceData();
514             s.token = token;
515             s.intent = intent;
516 
517             queueOrSendMessage(H.UNBIND_SERVICE, s);
518         }
519 
scheduleServiceArgs(IBinder token, int startId, int flags ,Intent args)520         public final void scheduleServiceArgs(IBinder token, int startId,
521             int flags ,Intent args) {
522             ServiceArgsData s = new ServiceArgsData();
523             s.token = token;
524             s.startId = startId;
525             s.flags = flags;
526             s.args = args;
527 
528             queueOrSendMessage(H.SERVICE_ARGS, s);
529         }
530 
scheduleStopService(IBinder token)531         public final void scheduleStopService(IBinder token) {
532             queueOrSendMessage(H.STOP_SERVICE, token);
533         }
534 
bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, String profileFile, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, int debugMode, boolean isRestrictedBackupMode, Configuration config, Map<String, IBinder> services)535         public final void bindApplication(String processName,
536                 ApplicationInfo appInfo, List<ProviderInfo> providers,
537                 ComponentName instrumentationName, String profileFile,
538                 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
539                 int debugMode, boolean isRestrictedBackupMode, Configuration config,
540                 Map<String, IBinder> services) {
541 
542             if (services != null) {
543                 // Setup the service cache in the ServiceManager
544                 ServiceManager.initServiceCache(services);
545             }
546 
547             AppBindData data = new AppBindData();
548             data.processName = processName;
549             data.appInfo = appInfo;
550             data.providers = providers;
551             data.instrumentationName = instrumentationName;
552             data.profileFile = profileFile;
553             data.instrumentationArgs = instrumentationArgs;
554             data.instrumentationWatcher = instrumentationWatcher;
555             data.debugMode = debugMode;
556             data.restrictedBackupMode = isRestrictedBackupMode;
557             data.config = config;
558             queueOrSendMessage(H.BIND_APPLICATION, data);
559         }
560 
scheduleExit()561         public final void scheduleExit() {
562             queueOrSendMessage(H.EXIT_APPLICATION, null);
563         }
564 
scheduleSuicide()565         public final void scheduleSuicide() {
566             queueOrSendMessage(H.SUICIDE, null);
567         }
568 
requestThumbnail(IBinder token)569         public void requestThumbnail(IBinder token) {
570             queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
571         }
572 
scheduleConfigurationChanged(Configuration config)573         public void scheduleConfigurationChanged(Configuration config) {
574             synchronized (mPackages) {
575                 if (mPendingConfiguration == null ||
576                         mPendingConfiguration.isOtherSeqNewer(config)) {
577                     mPendingConfiguration = config;
578                 }
579             }
580             queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
581         }
582 
updateTimeZone()583         public void updateTimeZone() {
584             TimeZone.setDefault(null);
585         }
586 
processInBackground()587         public void processInBackground() {
588             mH.removeMessages(H.GC_WHEN_IDLE);
589             mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
590         }
591 
dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)592         public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
593             DumpServiceInfo data = new DumpServiceInfo();
594             data.fd = fd;
595             data.service = servicetoken;
596             data.args = args;
597             data.dumped = false;
598             queueOrSendMessage(H.DUMP_SERVICE, data);
599             synchronized (data) {
600                 while (!data.dumped) {
601                     try {
602                         data.wait();
603                     } catch (InterruptedException e) {
604                         // no need to do anything here, we will keep waiting until
605                         // dumped is set
606                     }
607                 }
608             }
609         }
610 
611         // This function exists to make sure all receiver dispatching is
612         // correctly ordered, since these are one-way calls and the binder driver
613         // applies transaction ordering per object for such calls.
scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)614         public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
615                 int resultCode, String dataStr, Bundle extras, boolean ordered,
616                 boolean sticky) throws RemoteException {
617             receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
618         }
619 
scheduleLowMemory()620         public void scheduleLowMemory() {
621             queueOrSendMessage(H.LOW_MEMORY, null);
622         }
623 
scheduleActivityConfigurationChanged(IBinder token)624         public void scheduleActivityConfigurationChanged(IBinder token) {
625             queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
626         }
627 
profilerControl(boolean start, String path, ParcelFileDescriptor fd)628         public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
629             ProfilerControlData pcd = new ProfilerControlData();
630             pcd.path = path;
631             pcd.fd = fd;
632             queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
633         }
634 
setSchedulingGroup(int group)635         public void setSchedulingGroup(int group) {
636             // Note: do this immediately, since going into the foreground
637             // should happen regardless of what pending work we have to do
638             // and the activity manager will wait for us to report back that
639             // we are done before sending us to the background.
640             try {
641                 Process.setProcessGroup(Process.myPid(), group);
642             } catch (Exception e) {
643                 Slog.w(TAG, "Failed setting process group to " + group, e);
644             }
645         }
646 
getMemoryInfo(Debug.MemoryInfo outInfo)647         public void getMemoryInfo(Debug.MemoryInfo outInfo) {
648             Debug.getMemoryInfo(outInfo);
649         }
650 
dispatchPackageBroadcast(int cmd, String[] packages)651         public void dispatchPackageBroadcast(int cmd, String[] packages) {
652             queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
653         }
654 
scheduleCrash(String msg)655         public void scheduleCrash(String msg) {
656             queueOrSendMessage(H.SCHEDULE_CRASH, msg);
657         }
658 
659         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)660         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
661             long nativeMax = Debug.getNativeHeapSize() / 1024;
662             long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
663             long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
664 
665             Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
666             Debug.getMemoryInfo(memInfo);
667 
668             final int nativeShared = memInfo.nativeSharedDirty;
669             final int dalvikShared = memInfo.dalvikSharedDirty;
670             final int otherShared = memInfo.otherSharedDirty;
671 
672             final int nativePrivate = memInfo.nativePrivateDirty;
673             final int dalvikPrivate = memInfo.dalvikPrivateDirty;
674             final int otherPrivate = memInfo.otherPrivateDirty;
675 
676             Runtime runtime = Runtime.getRuntime();
677 
678             long dalvikMax = runtime.totalMemory() / 1024;
679             long dalvikFree = runtime.freeMemory() / 1024;
680             long dalvikAllocated = dalvikMax - dalvikFree;
681             long viewInstanceCount = ViewDebug.getViewInstanceCount();
682             long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount();
683             long appContextInstanceCount = ContextImpl.getInstanceCount();
684             long activityInstanceCount = Activity.getInstanceCount();
685             int globalAssetCount = AssetManager.getGlobalAssetCount();
686             int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
687             int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
688             int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
689             int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
690             int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount();
691             long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
692             SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
693 
694             // Check to see if we were called by checkin server. If so, print terse format.
695             boolean doCheckinFormat = false;
696             if (args != null) {
697                 for (String arg : args) {
698                     if ("-c".equals(arg)) doCheckinFormat = true;
699                 }
700             }
701 
702             // For checkin, we print one long comma-separated list of values
703             if (doCheckinFormat) {
704                 // NOTE: if you change anything significant below, also consider changing
705                 // ACTIVITY_THREAD_CHECKIN_VERSION.
706                 String processName = (mBoundApplication != null)
707                         ? mBoundApplication.processName : "unknown";
708 
709                 // Header
710                 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
711                 pw.print(Process.myPid()); pw.print(',');
712                 pw.print(processName); pw.print(',');
713 
714                 // Heap info - max
715                 pw.print(nativeMax); pw.print(',');
716                 pw.print(dalvikMax); pw.print(',');
717                 pw.print("N/A,");
718                 pw.print(nativeMax + dalvikMax); pw.print(',');
719 
720                 // Heap info - allocated
721                 pw.print(nativeAllocated); pw.print(',');
722                 pw.print(dalvikAllocated); pw.print(',');
723                 pw.print("N/A,");
724                 pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
725 
726                 // Heap info - free
727                 pw.print(nativeFree); pw.print(',');
728                 pw.print(dalvikFree); pw.print(',');
729                 pw.print("N/A,");
730                 pw.print(nativeFree + dalvikFree); pw.print(',');
731 
732                 // Heap info - proportional set size
733                 pw.print(memInfo.nativePss); pw.print(',');
734                 pw.print(memInfo.dalvikPss); pw.print(',');
735                 pw.print(memInfo.otherPss); pw.print(',');
736                 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
737 
738                 // Heap info - shared
739                 pw.print(nativeShared); pw.print(',');
740                 pw.print(dalvikShared); pw.print(',');
741                 pw.print(otherShared); pw.print(',');
742                 pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
743 
744                 // Heap info - private
745                 pw.print(nativePrivate); pw.print(',');
746                 pw.print(dalvikPrivate); pw.print(',');
747                 pw.print(otherPrivate); pw.print(',');
748                 pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
749 
750                 // Object counts
751                 pw.print(viewInstanceCount); pw.print(',');
752                 pw.print(viewRootInstanceCount); pw.print(',');
753                 pw.print(appContextInstanceCount); pw.print(',');
754                 pw.print(activityInstanceCount); pw.print(',');
755 
756                 pw.print(globalAssetCount); pw.print(',');
757                 pw.print(globalAssetManagerCount); pw.print(',');
758                 pw.print(binderLocalObjectCount); pw.print(',');
759                 pw.print(binderProxyObjectCount); pw.print(',');
760 
761                 pw.print(binderDeathObjectCount); pw.print(',');
762                 pw.print(openSslSocketCount); pw.print(',');
763 
764                 // SQL
765                 pw.print(sqliteAllocated); pw.print(',');
766                 pw.print(stats.memoryUsed / 1024); pw.print(',');
767                 pw.print(stats.pageCacheOverflo / 1024); pw.print(',');
768                 pw.print(stats.largestMemAlloc / 1024); pw.print(',');
769                 for (int i = 0; i < stats.dbStats.size(); i++) {
770                     DbStats dbStats = stats.dbStats.get(i);
771                     printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
772                             dbStats.lookaside, dbStats.dbName);
773                     pw.print(',');
774                 }
775 
776                 return;
777             }
778 
779             // otherwise, show human-readable format
780             printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
781             printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
782             printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
783                     nativeAllocated + dalvikAllocated);
784             printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
785                     nativeFree + dalvikFree);
786 
787             printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
788                     memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
789 
790             printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
791                     nativeShared + dalvikShared + otherShared);
792             printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
793                     nativePrivate + dalvikPrivate + otherPrivate);
794 
795             pw.println(" ");
796             pw.println(" Objects");
797             printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:",
798                     viewRootInstanceCount);
799 
800             printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
801                     "Activities:", activityInstanceCount);
802 
803             printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
804                     "AssetManagers:", globalAssetManagerCount);
805 
806             printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
807                     "Proxy Binders:", binderProxyObjectCount);
808             printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
809 
810             printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
811 
812             // SQLite mem info
813             pw.println(" ");
814             pw.println(" SQL");
815             printRow(pw, TWO_COUNT_COLUMNS_DB, "heap:", sqliteAllocated, "MEMORY_USED:",
816                     stats.memoryUsed / 1024);
817             printRow(pw, TWO_COUNT_COLUMNS_DB, "PAGECACHE_OVERFLOW:",
818                     stats.pageCacheOverflo / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
819             pw.println(" ");
820             int N = stats.dbStats.size();
821             if (N > 0) {
822                 pw.println(" DATABASES");
823                 printRow(pw, "  %8s %8s %14s  %s", "pgsz", "dbsz", "Lookaside(b)", "Dbname");
824                 for (int i = 0; i < N; i++) {
825                     DbStats dbStats = stats.dbStats.get(i);
826                     printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
827                             dbStats.lookaside, dbStats.dbName);
828                 }
829             }
830 
831             // Asset details.
832             String assetAlloc = AssetManager.getAssetAllocations();
833             if (assetAlloc != null) {
834                 pw.println(" ");
835                 pw.println(" Asset Allocations");
836                 pw.print(assetAlloc);
837             }
838         }
839 
printRow(PrintWriter pw, String format, Object...objs)840         private void printRow(PrintWriter pw, String format, Object...objs) {
841             pw.println(String.format(format, objs));
842         }
843     }
844 
845     private final class H extends Handler {
846         public static final int LAUNCH_ACTIVITY         = 100;
847         public static final int PAUSE_ACTIVITY          = 101;
848         public static final int PAUSE_ACTIVITY_FINISHING= 102;
849         public static final int STOP_ACTIVITY_SHOW      = 103;
850         public static final int STOP_ACTIVITY_HIDE      = 104;
851         public static final int SHOW_WINDOW             = 105;
852         public static final int HIDE_WINDOW             = 106;
853         public static final int RESUME_ACTIVITY         = 107;
854         public static final int SEND_RESULT             = 108;
855         public static final int DESTROY_ACTIVITY         = 109;
856         public static final int BIND_APPLICATION        = 110;
857         public static final int EXIT_APPLICATION        = 111;
858         public static final int NEW_INTENT              = 112;
859         public static final int RECEIVER                = 113;
860         public static final int CREATE_SERVICE          = 114;
861         public static final int SERVICE_ARGS            = 115;
862         public static final int STOP_SERVICE            = 116;
863         public static final int REQUEST_THUMBNAIL       = 117;
864         public static final int CONFIGURATION_CHANGED   = 118;
865         public static final int CLEAN_UP_CONTEXT        = 119;
866         public static final int GC_WHEN_IDLE            = 120;
867         public static final int BIND_SERVICE            = 121;
868         public static final int UNBIND_SERVICE          = 122;
869         public static final int DUMP_SERVICE            = 123;
870         public static final int LOW_MEMORY              = 124;
871         public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
872         public static final int RELAUNCH_ACTIVITY       = 126;
873         public static final int PROFILER_CONTROL        = 127;
874         public static final int CREATE_BACKUP_AGENT     = 128;
875         public static final int DESTROY_BACKUP_AGENT    = 129;
876         public static final int SUICIDE                 = 130;
877         public static final int REMOVE_PROVIDER         = 131;
878         public static final int ENABLE_JIT              = 132;
879         public static final int DISPATCH_PACKAGE_BROADCAST = 133;
880         public static final int SCHEDULE_CRASH          = 134;
codeToString(int code)881         String codeToString(int code) {
882             if (DEBUG_MESSAGES) {
883                 switch (code) {
884                     case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
885                     case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
886                     case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
887                     case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
888                     case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
889                     case SHOW_WINDOW: return "SHOW_WINDOW";
890                     case HIDE_WINDOW: return "HIDE_WINDOW";
891                     case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
892                     case SEND_RESULT: return "SEND_RESULT";
893                     case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
894                     case BIND_APPLICATION: return "BIND_APPLICATION";
895                     case EXIT_APPLICATION: return "EXIT_APPLICATION";
896                     case NEW_INTENT: return "NEW_INTENT";
897                     case RECEIVER: return "RECEIVER";
898                     case CREATE_SERVICE: return "CREATE_SERVICE";
899                     case SERVICE_ARGS: return "SERVICE_ARGS";
900                     case STOP_SERVICE: return "STOP_SERVICE";
901                     case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
902                     case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
903                     case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
904                     case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
905                     case BIND_SERVICE: return "BIND_SERVICE";
906                     case UNBIND_SERVICE: return "UNBIND_SERVICE";
907                     case DUMP_SERVICE: return "DUMP_SERVICE";
908                     case LOW_MEMORY: return "LOW_MEMORY";
909                     case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
910                     case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
911                     case PROFILER_CONTROL: return "PROFILER_CONTROL";
912                     case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
913                     case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
914                     case SUICIDE: return "SUICIDE";
915                     case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
916                     case ENABLE_JIT: return "ENABLE_JIT";
917                     case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
918                     case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
919                 }
920             }
921             return "(unknown)";
922         }
handleMessage(Message msg)923         public void handleMessage(Message msg) {
924             if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
925             switch (msg.what) {
926                 case LAUNCH_ACTIVITY: {
927                     ActivityClientRecord r = (ActivityClientRecord)msg.obj;
928 
929                     r.packageInfo = getPackageInfoNoCheck(
930                             r.activityInfo.applicationInfo);
931                     handleLaunchActivity(r, null);
932                 } break;
933                 case RELAUNCH_ACTIVITY: {
934                     ActivityClientRecord r = (ActivityClientRecord)msg.obj;
935                     handleRelaunchActivity(r, msg.arg1);
936                 } break;
937                 case PAUSE_ACTIVITY:
938                     handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
939                     maybeSnapshot();
940                     break;
941                 case PAUSE_ACTIVITY_FINISHING:
942                     handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
943                     break;
944                 case STOP_ACTIVITY_SHOW:
945                     handleStopActivity((IBinder)msg.obj, true, msg.arg2);
946                     break;
947                 case STOP_ACTIVITY_HIDE:
948                     handleStopActivity((IBinder)msg.obj, false, msg.arg2);
949                     break;
950                 case SHOW_WINDOW:
951                     handleWindowVisibility((IBinder)msg.obj, true);
952                     break;
953                 case HIDE_WINDOW:
954                     handleWindowVisibility((IBinder)msg.obj, false);
955                     break;
956                 case RESUME_ACTIVITY:
957                     handleResumeActivity((IBinder)msg.obj, true,
958                             msg.arg1 != 0);
959                     break;
960                 case SEND_RESULT:
961                     handleSendResult((ResultData)msg.obj);
962                     break;
963                 case DESTROY_ACTIVITY:
964                     handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
965                             msg.arg2, false);
966                     break;
967                 case BIND_APPLICATION:
968                     AppBindData data = (AppBindData)msg.obj;
969                     handleBindApplication(data);
970                     break;
971                 case EXIT_APPLICATION:
972                     if (mInitialApplication != null) {
973                         mInitialApplication.onTerminate();
974                     }
975                     Looper.myLooper().quit();
976                     break;
977                 case NEW_INTENT:
978                     handleNewIntent((NewIntentData)msg.obj);
979                     break;
980                 case RECEIVER:
981                     handleReceiver((ReceiverData)msg.obj);
982                     maybeSnapshot();
983                     break;
984                 case CREATE_SERVICE:
985                     handleCreateService((CreateServiceData)msg.obj);
986                     break;
987                 case BIND_SERVICE:
988                     handleBindService((BindServiceData)msg.obj);
989                     break;
990                 case UNBIND_SERVICE:
991                     handleUnbindService((BindServiceData)msg.obj);
992                     break;
993                 case SERVICE_ARGS:
994                     handleServiceArgs((ServiceArgsData)msg.obj);
995                     break;
996                 case STOP_SERVICE:
997                     handleStopService((IBinder)msg.obj);
998                     maybeSnapshot();
999                     break;
1000                 case REQUEST_THUMBNAIL:
1001                     handleRequestThumbnail((IBinder)msg.obj);
1002                     break;
1003                 case CONFIGURATION_CHANGED:
1004                     handleConfigurationChanged((Configuration)msg.obj);
1005                     break;
1006                 case CLEAN_UP_CONTEXT:
1007                     ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
1008                     cci.context.performFinalCleanup(cci.who, cci.what);
1009                     break;
1010                 case GC_WHEN_IDLE:
1011                     scheduleGcIdler();
1012                     break;
1013                 case DUMP_SERVICE:
1014                     handleDumpService((DumpServiceInfo)msg.obj);
1015                     break;
1016                 case LOW_MEMORY:
1017                     handleLowMemory();
1018                     break;
1019                 case ACTIVITY_CONFIGURATION_CHANGED:
1020                     handleActivityConfigurationChanged((IBinder)msg.obj);
1021                     break;
1022                 case PROFILER_CONTROL:
1023                     handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
1024                     break;
1025                 case CREATE_BACKUP_AGENT:
1026                     handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
1027                     break;
1028                 case DESTROY_BACKUP_AGENT:
1029                     handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
1030                     break;
1031                 case SUICIDE:
1032                     Process.killProcess(Process.myPid());
1033                     break;
1034                 case REMOVE_PROVIDER:
1035                     completeRemoveProvider((IContentProvider)msg.obj);
1036                     break;
1037                 case ENABLE_JIT:
1038                     ensureJitEnabled();
1039                     break;
1040                 case DISPATCH_PACKAGE_BROADCAST:
1041                     handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
1042                     break;
1043                 case SCHEDULE_CRASH:
1044                     throw new RemoteServiceException((String)msg.obj);
1045             }
1046             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
1047         }
1048 
maybeSnapshot()1049         void maybeSnapshot() {
1050             if (mBoundApplication != null) {
1051                 SamplingProfilerIntegration.writeSnapshot(
1052                         mBoundApplication.processName);
1053             }
1054         }
1055     }
1056 
1057     private final class Idler implements MessageQueue.IdleHandler {
queueIdle()1058         public final boolean queueIdle() {
1059             ActivityClientRecord a = mNewActivities;
1060             if (a != null) {
1061                 mNewActivities = null;
1062                 IActivityManager am = ActivityManagerNative.getDefault();
1063                 ActivityClientRecord prev;
1064                 do {
1065                     if (localLOGV) Slog.v(
1066                         TAG, "Reporting idle of " + a +
1067                         " finished=" +
1068                         (a.activity != null ? a.activity.mFinished : false));
1069                     if (a.activity != null && !a.activity.mFinished) {
1070                         try {
1071                             am.activityIdle(a.token, a.createdConfig);
1072                             a.createdConfig = null;
1073                         } catch (RemoteException ex) {
1074                         }
1075                     }
1076                     prev = a;
1077                     a = a.nextIdle;
1078                     prev.nextIdle = null;
1079                 } while (a != null);
1080             }
1081             ensureJitEnabled();
1082             return false;
1083         }
1084     }
1085 
1086     final class GcIdler implements MessageQueue.IdleHandler {
queueIdle()1087         public final boolean queueIdle() {
1088             doGcIfNeeded();
1089             return false;
1090         }
1091     }
1092 
1093     private final static class ResourcesKey {
1094         final private String mResDir;
1095         final private float mScale;
1096         final private int mHash;
1097 
ResourcesKey(String resDir, float scale)1098         ResourcesKey(String resDir, float scale) {
1099             mResDir = resDir;
1100             mScale = scale;
1101             mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
1102         }
1103 
1104         @Override
hashCode()1105         public int hashCode() {
1106             return mHash;
1107         }
1108 
1109         @Override
equals(Object obj)1110         public boolean equals(Object obj) {
1111             if (!(obj instanceof ResourcesKey)) {
1112                 return false;
1113             }
1114             ResourcesKey peer = (ResourcesKey) obj;
1115             return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
1116         }
1117     }
1118 
currentActivityThread()1119     public static final ActivityThread currentActivityThread() {
1120         return sThreadLocal.get();
1121     }
1122 
currentPackageName()1123     public static final String currentPackageName() {
1124         ActivityThread am = currentActivityThread();
1125         return (am != null && am.mBoundApplication != null)
1126             ? am.mBoundApplication.processName : null;
1127     }
1128 
currentApplication()1129     public static final Application currentApplication() {
1130         ActivityThread am = currentActivityThread();
1131         return am != null ? am.mInitialApplication : null;
1132     }
1133 
getPackageManager()1134     public static IPackageManager getPackageManager() {
1135         if (sPackageManager != null) {
1136             //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
1137             return sPackageManager;
1138         }
1139         IBinder b = ServiceManager.getService("package");
1140         //Slog.v("PackageManager", "default service binder = " + b);
1141         sPackageManager = IPackageManager.Stub.asInterface(b);
1142         //Slog.v("PackageManager", "default service = " + sPackageManager);
1143         return sPackageManager;
1144     }
1145 
getDisplayMetricsLocked(boolean forceUpdate)1146     DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
1147         if (mDisplayMetrics != null && !forceUpdate) {
1148             return mDisplayMetrics;
1149         }
1150         if (mDisplay == null) {
1151             WindowManager wm = WindowManagerImpl.getDefault();
1152             mDisplay = wm.getDefaultDisplay();
1153         }
1154         DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
1155         mDisplay.getMetrics(metrics);
1156         //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
1157         //        + metrics.heightPixels + " den=" + metrics.density
1158         //        + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
1159         return metrics;
1160     }
1161 
1162     /**
1163      * Creates the top level Resources for applications with the given compatibility info.
1164      *
1165      * @param resDir the resource directory.
1166      * @param compInfo the compability info. It will use the default compatibility info when it's
1167      * null.
1168      */
getTopLevelResources(String resDir, CompatibilityInfo compInfo)1169     Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
1170         ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
1171         Resources r;
1172         synchronized (mPackages) {
1173             // Resources is app scale dependent.
1174             if (false) {
1175                 Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
1176                         + compInfo.applicationScale);
1177             }
1178             WeakReference<Resources> wr = mActiveResources.get(key);
1179             r = wr != null ? wr.get() : null;
1180             //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
1181             if (r != null && r.getAssets().isUpToDate()) {
1182                 if (false) {
1183                     Slog.w(TAG, "Returning cached resources " + r + " " + resDir
1184                             + ": appScale=" + r.getCompatibilityInfo().applicationScale);
1185                 }
1186                 return r;
1187             }
1188         }
1189 
1190         //if (r != null) {
1191         //    Slog.w(TAG, "Throwing away out-of-date resources!!!! "
1192         //            + r + " " + resDir);
1193         //}
1194 
1195         AssetManager assets = new AssetManager();
1196         if (assets.addAssetPath(resDir) == 0) {
1197             return null;
1198         }
1199 
1200         //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
1201         DisplayMetrics metrics = getDisplayMetricsLocked(false);
1202         r = new Resources(assets, metrics, getConfiguration(), compInfo);
1203         if (false) {
1204             Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
1205                     + r.getConfiguration() + " appScale="
1206                     + r.getCompatibilityInfo().applicationScale);
1207         }
1208 
1209         synchronized (mPackages) {
1210             WeakReference<Resources> wr = mActiveResources.get(key);
1211             Resources existing = wr != null ? wr.get() : null;
1212             if (existing != null && existing.getAssets().isUpToDate()) {
1213                 // Someone else already created the resources while we were
1214                 // unlocked; go ahead and use theirs.
1215                 r.getAssets().close();
1216                 return existing;
1217             }
1218 
1219             // XXX need to remove entries when weak references go away
1220             mActiveResources.put(key, new WeakReference<Resources>(r));
1221             return r;
1222         }
1223     }
1224 
1225     /**
1226      * Creates the top level resources for the given package.
1227      */
getTopLevelResources(String resDir, LoadedApk pkgInfo)1228     Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) {
1229         return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
1230     }
1231 
getHandler()1232     final Handler getHandler() {
1233         return mH;
1234     }
1235 
getPackageInfo(String packageName, int flags)1236     public final LoadedApk getPackageInfo(String packageName, int flags) {
1237         synchronized (mPackages) {
1238             WeakReference<LoadedApk> ref;
1239             if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
1240                 ref = mPackages.get(packageName);
1241             } else {
1242                 ref = mResourcePackages.get(packageName);
1243             }
1244             LoadedApk packageInfo = ref != null ? ref.get() : null;
1245             //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
1246             //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
1247             //        + ": " + packageInfo.mResources.getAssets().isUpToDate());
1248             if (packageInfo != null && (packageInfo.mResources == null
1249                     || packageInfo.mResources.getAssets().isUpToDate())) {
1250                 if (packageInfo.isSecurityViolation()
1251                         && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
1252                     throw new SecurityException(
1253                             "Requesting code from " + packageName
1254                             + " to be run in process "
1255                             + mBoundApplication.processName
1256                             + "/" + mBoundApplication.appInfo.uid);
1257                 }
1258                 return packageInfo;
1259             }
1260         }
1261 
1262         ApplicationInfo ai = null;
1263         try {
1264             ai = getPackageManager().getApplicationInfo(packageName,
1265                     PackageManager.GET_SHARED_LIBRARY_FILES);
1266         } catch (RemoteException e) {
1267         }
1268 
1269         if (ai != null) {
1270             return getPackageInfo(ai, flags);
1271         }
1272 
1273         return null;
1274     }
1275 
getPackageInfo(ApplicationInfo ai, int flags)1276     public final LoadedApk getPackageInfo(ApplicationInfo ai, int flags) {
1277         boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
1278         boolean securityViolation = includeCode && ai.uid != 0
1279                 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
1280                         ? ai.uid != mBoundApplication.appInfo.uid : true);
1281         if ((flags&(Context.CONTEXT_INCLUDE_CODE
1282                 |Context.CONTEXT_IGNORE_SECURITY))
1283                 == Context.CONTEXT_INCLUDE_CODE) {
1284             if (securityViolation) {
1285                 String msg = "Requesting code from " + ai.packageName
1286                         + " (with uid " + ai.uid + ")";
1287                 if (mBoundApplication != null) {
1288                     msg = msg + " to be run in process "
1289                         + mBoundApplication.processName + " (with uid "
1290                         + mBoundApplication.appInfo.uid + ")";
1291                 }
1292                 throw new SecurityException(msg);
1293             }
1294         }
1295         return getPackageInfo(ai, null, securityViolation, includeCode);
1296     }
1297 
getPackageInfoNoCheck(ApplicationInfo ai)1298     public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai) {
1299         return getPackageInfo(ai, null, false, true);
1300     }
1301 
getPackageInfo(ApplicationInfo aInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode)1302     private final LoadedApk getPackageInfo(ApplicationInfo aInfo,
1303             ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
1304         synchronized (mPackages) {
1305             WeakReference<LoadedApk> ref;
1306             if (includeCode) {
1307                 ref = mPackages.get(aInfo.packageName);
1308             } else {
1309                 ref = mResourcePackages.get(aInfo.packageName);
1310             }
1311             LoadedApk packageInfo = ref != null ? ref.get() : null;
1312             if (packageInfo == null || (packageInfo.mResources != null
1313                     && !packageInfo.mResources.getAssets().isUpToDate())) {
1314                 if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
1315                         : "Loading resource-only package ") + aInfo.packageName
1316                         + " (in " + (mBoundApplication != null
1317                                 ? mBoundApplication.processName : null)
1318                         + ")");
1319                 packageInfo =
1320                     new LoadedApk(this, aInfo, this, baseLoader,
1321                             securityViolation, includeCode &&
1322                             (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
1323                 if (includeCode) {
1324                     mPackages.put(aInfo.packageName,
1325                             new WeakReference<LoadedApk>(packageInfo));
1326                 } else {
1327                     mResourcePackages.put(aInfo.packageName,
1328                             new WeakReference<LoadedApk>(packageInfo));
1329                 }
1330             }
1331             return packageInfo;
1332         }
1333     }
1334 
ActivityThread()1335     ActivityThread() {
1336     }
1337 
getApplicationThread()1338     public ApplicationThread getApplicationThread()
1339     {
1340         return mAppThread;
1341     }
1342 
getInstrumentation()1343     public Instrumentation getInstrumentation()
1344     {
1345         return mInstrumentation;
1346     }
1347 
getConfiguration()1348     public Configuration getConfiguration() {
1349         return mConfiguration;
1350     }
1351 
isProfiling()1352     public boolean isProfiling() {
1353         return mBoundApplication != null && mBoundApplication.profileFile != null;
1354     }
1355 
getProfileFilePath()1356     public String getProfileFilePath() {
1357         return mBoundApplication.profileFile;
1358     }
1359 
getLooper()1360     public Looper getLooper() {
1361         return mLooper;
1362     }
1363 
getApplication()1364     public Application getApplication() {
1365         return mInitialApplication;
1366     }
1367 
getProcessName()1368     public String getProcessName() {
1369         return mBoundApplication.processName;
1370     }
1371 
getSystemContext()1372     public ContextImpl getSystemContext() {
1373         synchronized (this) {
1374             if (mSystemContext == null) {
1375                 ContextImpl context =
1376                     ContextImpl.createSystemContext(this);
1377                 LoadedApk info = new LoadedApk(this, "android", context, null);
1378                 context.init(info, null, this);
1379                 context.getResources().updateConfiguration(
1380                         getConfiguration(), getDisplayMetricsLocked(false));
1381                 mSystemContext = context;
1382                 //Slog.i(TAG, "Created system resources " + context.getResources()
1383                 //        + ": " + context.getResources().getConfiguration());
1384             }
1385         }
1386         return mSystemContext;
1387     }
1388 
installSystemApplicationInfo(ApplicationInfo info)1389     public void installSystemApplicationInfo(ApplicationInfo info) {
1390         synchronized (this) {
1391             ContextImpl context = getSystemContext();
1392             context.init(new LoadedApk(this, "android", context, info), null, this);
1393         }
1394     }
1395 
ensureJitEnabled()1396     void ensureJitEnabled() {
1397         if (!mJitEnabled) {
1398             mJitEnabled = true;
1399             dalvik.system.VMRuntime.getRuntime().startJitCompilation();
1400         }
1401     }
1402 
scheduleGcIdler()1403     void scheduleGcIdler() {
1404         if (!mGcIdlerScheduled) {
1405             mGcIdlerScheduled = true;
1406             Looper.myQueue().addIdleHandler(mGcIdler);
1407         }
1408         mH.removeMessages(H.GC_WHEN_IDLE);
1409     }
1410 
unscheduleGcIdler()1411     void unscheduleGcIdler() {
1412         if (mGcIdlerScheduled) {
1413             mGcIdlerScheduled = false;
1414             Looper.myQueue().removeIdleHandler(mGcIdler);
1415         }
1416         mH.removeMessages(H.GC_WHEN_IDLE);
1417     }
1418 
doGcIfNeeded()1419     void doGcIfNeeded() {
1420         mGcIdlerScheduled = false;
1421         final long now = SystemClock.uptimeMillis();
1422         //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
1423         //        + "m now=" + now);
1424         if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
1425             //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
1426             BinderInternal.forceGc("bg");
1427         }
1428     }
1429 
registerOnActivityPausedListener(Activity activity, OnActivityPausedListener listener)1430     public void registerOnActivityPausedListener(Activity activity,
1431             OnActivityPausedListener listener) {
1432         synchronized (mOnPauseListeners) {
1433             ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
1434             if (list == null) {
1435                 list = new ArrayList<OnActivityPausedListener>();
1436                 mOnPauseListeners.put(activity, list);
1437             }
1438             list.add(listener);
1439         }
1440     }
1441 
unregisterOnActivityPausedListener(Activity activity, OnActivityPausedListener listener)1442     public void unregisterOnActivityPausedListener(Activity activity,
1443             OnActivityPausedListener listener) {
1444         synchronized (mOnPauseListeners) {
1445             ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
1446             if (list != null) {
1447                 list.remove(listener);
1448             }
1449         }
1450     }
1451 
resolveActivityInfo(Intent intent)1452     public final ActivityInfo resolveActivityInfo(Intent intent) {
1453         ActivityInfo aInfo = intent.resolveActivityInfo(
1454                 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
1455         if (aInfo == null) {
1456             // Throw an exception.
1457             Instrumentation.checkStartActivityResult(
1458                     IActivityManager.START_CLASS_NOT_FOUND, intent);
1459         }
1460         return aInfo;
1461     }
1462 
startActivityNow(Activity parent, String id, Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state, Object lastNonConfigurationInstance)1463     public final Activity startActivityNow(Activity parent, String id,
1464         Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
1465         Object lastNonConfigurationInstance) {
1466         ActivityClientRecord r = new ActivityClientRecord();
1467             r.token = token;
1468             r.ident = 0;
1469             r.intent = intent;
1470             r.state = state;
1471             r.parent = parent;
1472             r.embeddedID = id;
1473             r.activityInfo = activityInfo;
1474             r.lastNonConfigurationInstance = lastNonConfigurationInstance;
1475         if (localLOGV) {
1476             ComponentName compname = intent.getComponent();
1477             String name;
1478             if (compname != null) {
1479                 name = compname.toShortString();
1480             } else {
1481                 name = "(Intent " + intent + ").getComponent() returned null";
1482             }
1483             Slog.v(TAG, "Performing launch: action=" + intent.getAction()
1484                     + ", comp=" + name
1485                     + ", token=" + token);
1486         }
1487         return performLaunchActivity(r, null);
1488     }
1489 
getActivity(IBinder token)1490     public final Activity getActivity(IBinder token) {
1491         return mActivities.get(token).activity;
1492     }
1493 
sendActivityResult( IBinder token, String id, int requestCode, int resultCode, Intent data)1494     public final void sendActivityResult(
1495             IBinder token, String id, int requestCode,
1496             int resultCode, Intent data) {
1497         if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
1498                 + " req=" + requestCode + " res=" + resultCode + " data=" + data);
1499         ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
1500         list.add(new ResultInfo(id, requestCode, resultCode, data));
1501         mAppThread.scheduleSendResult(token, list);
1502     }
1503 
1504     // if the thread hasn't started yet, we don't have the handler, so just
1505     // save the messages until we're ready.
queueOrSendMessage(int what, Object obj)1506     private final void queueOrSendMessage(int what, Object obj) {
1507         queueOrSendMessage(what, obj, 0, 0);
1508     }
1509 
queueOrSendMessage(int what, Object obj, int arg1)1510     private final void queueOrSendMessage(int what, Object obj, int arg1) {
1511         queueOrSendMessage(what, obj, arg1, 0);
1512     }
1513 
queueOrSendMessage(int what, Object obj, int arg1, int arg2)1514     private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
1515         synchronized (this) {
1516             if (DEBUG_MESSAGES) Slog.v(
1517                 TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
1518                 + ": " + arg1 + " / " + obj);
1519             Message msg = Message.obtain();
1520             msg.what = what;
1521             msg.obj = obj;
1522             msg.arg1 = arg1;
1523             msg.arg2 = arg2;
1524             mH.sendMessage(msg);
1525         }
1526     }
1527 
scheduleContextCleanup(ContextImpl context, String who, String what)1528     final void scheduleContextCleanup(ContextImpl context, String who,
1529             String what) {
1530         ContextCleanupInfo cci = new ContextCleanupInfo();
1531         cci.context = context;
1532         cci.who = who;
1533         cci.what = what;
1534         queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
1535     }
1536 
performLaunchActivity(ActivityClientRecord r, Intent customIntent)1537     private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
1538         // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
1539 
1540         ActivityInfo aInfo = r.activityInfo;
1541         if (r.packageInfo == null) {
1542             r.packageInfo = getPackageInfo(aInfo.applicationInfo,
1543                     Context.CONTEXT_INCLUDE_CODE);
1544         }
1545 
1546         ComponentName component = r.intent.getComponent();
1547         if (component == null) {
1548             component = r.intent.resolveActivity(
1549                 mInitialApplication.getPackageManager());
1550             r.intent.setComponent(component);
1551         }
1552 
1553         if (r.activityInfo.targetActivity != null) {
1554             component = new ComponentName(r.activityInfo.packageName,
1555                     r.activityInfo.targetActivity);
1556         }
1557 
1558         Activity activity = null;
1559         try {
1560             java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
1561             activity = mInstrumentation.newActivity(
1562                     cl, component.getClassName(), r.intent);
1563             r.intent.setExtrasClassLoader(cl);
1564             if (r.state != null) {
1565                 r.state.setClassLoader(cl);
1566             }
1567         } catch (Exception e) {
1568             if (!mInstrumentation.onException(activity, e)) {
1569                 throw new RuntimeException(
1570                     "Unable to instantiate activity " + component
1571                     + ": " + e.toString(), e);
1572             }
1573         }
1574 
1575         try {
1576             Application app = r.packageInfo.makeApplication(false, mInstrumentation);
1577 
1578             if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
1579             if (localLOGV) Slog.v(
1580                     TAG, r + ": app=" + app
1581                     + ", appName=" + app.getPackageName()
1582                     + ", pkg=" + r.packageInfo.getPackageName()
1583                     + ", comp=" + r.intent.getComponent().toShortString()
1584                     + ", dir=" + r.packageInfo.getAppDir());
1585 
1586             if (activity != null) {
1587                 ContextImpl appContext = new ContextImpl();
1588                 appContext.init(r.packageInfo, r.token, this);
1589                 appContext.setOuterContext(activity);
1590                 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
1591                 Configuration config = new Configuration(mConfiguration);
1592                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
1593                         + r.activityInfo.name + " with config " + config);
1594                 activity.attach(appContext, this, getInstrumentation(), r.token,
1595                         r.ident, app, r.intent, r.activityInfo, title, r.parent,
1596                         r.embeddedID, r.lastNonConfigurationInstance,
1597                         r.lastNonConfigurationChildInstances, config);
1598 
1599                 if (customIntent != null) {
1600                     activity.mIntent = customIntent;
1601                 }
1602                 r.lastNonConfigurationInstance = null;
1603                 r.lastNonConfigurationChildInstances = null;
1604                 activity.mStartedActivity = false;
1605                 int theme = r.activityInfo.getThemeResource();
1606                 if (theme != 0) {
1607                     activity.setTheme(theme);
1608                 }
1609 
1610                 activity.mCalled = false;
1611                 mInstrumentation.callActivityOnCreate(activity, r.state);
1612                 if (!activity.mCalled) {
1613                     throw new SuperNotCalledException(
1614                         "Activity " + r.intent.getComponent().toShortString() +
1615                         " did not call through to super.onCreate()");
1616                 }
1617                 r.activity = activity;
1618                 r.stopped = true;
1619                 if (!r.activity.mFinished) {
1620                     activity.performStart();
1621                     r.stopped = false;
1622                 }
1623                 if (!r.activity.mFinished) {
1624                     if (r.state != null) {
1625                         mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
1626                     }
1627                 }
1628                 if (!r.activity.mFinished) {
1629                     activity.mCalled = false;
1630                     mInstrumentation.callActivityOnPostCreate(activity, r.state);
1631                     if (!activity.mCalled) {
1632                         throw new SuperNotCalledException(
1633                             "Activity " + r.intent.getComponent().toShortString() +
1634                             " did not call through to super.onPostCreate()");
1635                     }
1636                 }
1637             }
1638             r.paused = true;
1639 
1640             mActivities.put(r.token, r);
1641 
1642         } catch (SuperNotCalledException e) {
1643             throw e;
1644 
1645         } catch (Exception e) {
1646             if (!mInstrumentation.onException(activity, e)) {
1647                 throw new RuntimeException(
1648                     "Unable to start activity " + component
1649                     + ": " + e.toString(), e);
1650             }
1651         }
1652 
1653         return activity;
1654     }
1655 
handleLaunchActivity(ActivityClientRecord r, Intent customIntent)1656     private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
1657         // If we are getting ready to gc after going to the background, well
1658         // we are back active so skip it.
1659         unscheduleGcIdler();
1660 
1661         if (localLOGV) Slog.v(
1662             TAG, "Handling launch of " + r);
1663         Activity a = performLaunchActivity(r, customIntent);
1664 
1665         if (a != null) {
1666             r.createdConfig = new Configuration(mConfiguration);
1667             Bundle oldState = r.state;
1668             handleResumeActivity(r.token, false, r.isForward);
1669 
1670             if (!r.activity.mFinished && r.startsNotResumed) {
1671                 // The activity manager actually wants this one to start out
1672                 // paused, because it needs to be visible but isn't in the
1673                 // foreground.  We accomplish this by going through the
1674                 // normal startup (because activities expect to go through
1675                 // onResume() the first time they run, before their window
1676                 // is displayed), and then pausing it.  However, in this case
1677                 // we do -not- need to do the full pause cycle (of freezing
1678                 // and such) because the activity manager assumes it can just
1679                 // retain the current state it has.
1680                 try {
1681                     r.activity.mCalled = false;
1682                     mInstrumentation.callActivityOnPause(r.activity);
1683                     // We need to keep around the original state, in case
1684                     // we need to be created again.
1685                     r.state = oldState;
1686                     if (!r.activity.mCalled) {
1687                         throw new SuperNotCalledException(
1688                             "Activity " + r.intent.getComponent().toShortString() +
1689                             " did not call through to super.onPause()");
1690                     }
1691 
1692                 } catch (SuperNotCalledException e) {
1693                     throw e;
1694 
1695                 } catch (Exception e) {
1696                     if (!mInstrumentation.onException(r.activity, e)) {
1697                         throw new RuntimeException(
1698                                 "Unable to pause activity "
1699                                 + r.intent.getComponent().toShortString()
1700                                 + ": " + e.toString(), e);
1701                     }
1702                 }
1703                 r.paused = true;
1704             }
1705         } else {
1706             // If there was an error, for any reason, tell the activity
1707             // manager to stop us.
1708             try {
1709                 ActivityManagerNative.getDefault()
1710                     .finishActivity(r.token, Activity.RESULT_CANCELED, null);
1711             } catch (RemoteException ex) {
1712             }
1713         }
1714     }
1715 
deliverNewIntents(ActivityClientRecord r, List<Intent> intents)1716     private final void deliverNewIntents(ActivityClientRecord r,
1717             List<Intent> intents) {
1718         final int N = intents.size();
1719         for (int i=0; i<N; i++) {
1720             Intent intent = intents.get(i);
1721             intent.setExtrasClassLoader(r.activity.getClassLoader());
1722             mInstrumentation.callActivityOnNewIntent(r.activity, intent);
1723         }
1724     }
1725 
performNewIntents(IBinder token, List<Intent> intents)1726     public final void performNewIntents(IBinder token,
1727             List<Intent> intents) {
1728         ActivityClientRecord r = mActivities.get(token);
1729         if (r != null) {
1730             final boolean resumed = !r.paused;
1731             if (resumed) {
1732                 mInstrumentation.callActivityOnPause(r.activity);
1733             }
1734             deliverNewIntents(r, intents);
1735             if (resumed) {
1736                 mInstrumentation.callActivityOnResume(r.activity);
1737             }
1738         }
1739     }
1740 
handleNewIntent(NewIntentData data)1741     private final void handleNewIntent(NewIntentData data) {
1742         performNewIntents(data.token, data.intents);
1743     }
1744 
handleReceiver(ReceiverData data)1745     private final void handleReceiver(ReceiverData data) {
1746         // If we are getting ready to gc after going to the background, well
1747         // we are back active so skip it.
1748         unscheduleGcIdler();
1749 
1750         String component = data.intent.getComponent().getClassName();
1751 
1752         LoadedApk packageInfo = getPackageInfoNoCheck(
1753                 data.info.applicationInfo);
1754 
1755         IActivityManager mgr = ActivityManagerNative.getDefault();
1756 
1757         BroadcastReceiver receiver = null;
1758         try {
1759             java.lang.ClassLoader cl = packageInfo.getClassLoader();
1760             data.intent.setExtrasClassLoader(cl);
1761             if (data.resultExtras != null) {
1762                 data.resultExtras.setClassLoader(cl);
1763             }
1764             receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
1765         } catch (Exception e) {
1766             try {
1767                 if (DEBUG_BROADCAST) Slog.i(TAG,
1768                         "Finishing failed broadcast to " + data.intent.getComponent());
1769                 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
1770                                    data.resultData, data.resultExtras, data.resultAbort);
1771             } catch (RemoteException ex) {
1772             }
1773             throw new RuntimeException(
1774                 "Unable to instantiate receiver " + component
1775                 + ": " + e.toString(), e);
1776         }
1777 
1778         try {
1779             Application app = packageInfo.makeApplication(false, mInstrumentation);
1780 
1781             if (localLOGV) Slog.v(
1782                 TAG, "Performing receive of " + data.intent
1783                 + ": app=" + app
1784                 + ", appName=" + app.getPackageName()
1785                 + ", pkg=" + packageInfo.getPackageName()
1786                 + ", comp=" + data.intent.getComponent().toShortString()
1787                 + ", dir=" + packageInfo.getAppDir());
1788 
1789             ContextImpl context = (ContextImpl)app.getBaseContext();
1790             receiver.setOrderedHint(true);
1791             receiver.setResult(data.resultCode, data.resultData,
1792                 data.resultExtras);
1793             receiver.setOrderedHint(data.sync);
1794             receiver.onReceive(context.getReceiverRestrictedContext(),
1795                     data.intent);
1796         } catch (Exception e) {
1797             try {
1798                 if (DEBUG_BROADCAST) Slog.i(TAG,
1799                         "Finishing failed broadcast to " + data.intent.getComponent());
1800                 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
1801                     data.resultData, data.resultExtras, data.resultAbort);
1802             } catch (RemoteException ex) {
1803             }
1804             if (!mInstrumentation.onException(receiver, e)) {
1805                 throw new RuntimeException(
1806                     "Unable to start receiver " + component
1807                     + ": " + e.toString(), e);
1808             }
1809         }
1810 
1811         QueuedWork.waitToFinish();
1812 
1813         try {
1814             if (data.sync) {
1815                 if (DEBUG_BROADCAST) Slog.i(TAG,
1816                         "Finishing ordered broadcast to " + data.intent.getComponent());
1817                 mgr.finishReceiver(
1818                     mAppThread.asBinder(), receiver.getResultCode(),
1819                     receiver.getResultData(), receiver.getResultExtras(false),
1820                         receiver.getAbortBroadcast());
1821             } else {
1822                 if (DEBUG_BROADCAST) Slog.i(TAG,
1823                         "Finishing broadcast to " + data.intent.getComponent());
1824                 mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
1825             }
1826         } catch (RemoteException ex) {
1827         }
1828     }
1829 
1830     // Instantiate a BackupAgent and tell it that it's alive
handleCreateBackupAgent(CreateBackupAgentData data)1831     private final void handleCreateBackupAgent(CreateBackupAgentData data) {
1832         if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
1833 
1834         // no longer idle; we have backup work to do
1835         unscheduleGcIdler();
1836 
1837         // instantiate the BackupAgent class named in the manifest
1838         LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo);
1839         String packageName = packageInfo.mPackageName;
1840         if (mBackupAgents.get(packageName) != null) {
1841             Slog.d(TAG, "BackupAgent " + "  for " + packageName
1842                     + " already exists");
1843             return;
1844         }
1845 
1846         BackupAgent agent = null;
1847         String classname = data.appInfo.backupAgentName;
1848         if (classname == null) {
1849             if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) {
1850                 Slog.e(TAG, "Attempted incremental backup but no defined agent for "
1851                         + packageName);
1852                 return;
1853             }
1854             classname = "android.app.FullBackupAgent";
1855         }
1856         try {
1857             IBinder binder = null;
1858             try {
1859                 java.lang.ClassLoader cl = packageInfo.getClassLoader();
1860                 agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance();
1861 
1862                 // set up the agent's context
1863                 if (DEBUG_BACKUP) Slog.v(TAG, "Initializing BackupAgent "
1864                         + data.appInfo.backupAgentName);
1865 
1866                 ContextImpl context = new ContextImpl();
1867                 context.init(packageInfo, null, this);
1868                 context.setOuterContext(agent);
1869                 agent.attach(context);
1870 
1871                 agent.onCreate();
1872                 binder = agent.onBind();
1873                 mBackupAgents.put(packageName, agent);
1874             } catch (Exception e) {
1875                 // If this is during restore, fail silently; otherwise go
1876                 // ahead and let the user see the crash.
1877                 Slog.e(TAG, "Agent threw during creation: " + e);
1878                 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) {
1879                     throw e;
1880                 }
1881                 // falling through with 'binder' still null
1882             }
1883 
1884             // tell the OS that we're live now
1885             try {
1886                 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
1887             } catch (RemoteException e) {
1888                 // nothing to do.
1889             }
1890         } catch (Exception e) {
1891             throw new RuntimeException("Unable to create BackupAgent "
1892                     + data.appInfo.backupAgentName + ": " + e.toString(), e);
1893         }
1894     }
1895 
1896     // Tear down a BackupAgent
handleDestroyBackupAgent(CreateBackupAgentData data)1897     private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
1898         if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
1899 
1900         LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo);
1901         String packageName = packageInfo.mPackageName;
1902         BackupAgent agent = mBackupAgents.get(packageName);
1903         if (agent != null) {
1904             try {
1905                 agent.onDestroy();
1906             } catch (Exception e) {
1907                 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
1908                 e.printStackTrace();
1909             }
1910             mBackupAgents.remove(packageName);
1911         } else {
1912             Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
1913         }
1914     }
1915 
handleCreateService(CreateServiceData data)1916     private final void handleCreateService(CreateServiceData data) {
1917         // If we are getting ready to gc after going to the background, well
1918         // we are back active so skip it.
1919         unscheduleGcIdler();
1920 
1921         LoadedApk packageInfo = getPackageInfoNoCheck(
1922                 data.info.applicationInfo);
1923         Service service = null;
1924         try {
1925             java.lang.ClassLoader cl = packageInfo.getClassLoader();
1926             service = (Service) cl.loadClass(data.info.name).newInstance();
1927         } catch (Exception e) {
1928             if (!mInstrumentation.onException(service, e)) {
1929                 throw new RuntimeException(
1930                     "Unable to instantiate service " + data.info.name
1931                     + ": " + e.toString(), e);
1932             }
1933         }
1934 
1935         try {
1936             if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
1937 
1938             ContextImpl context = new ContextImpl();
1939             context.init(packageInfo, null, this);
1940 
1941             Application app = packageInfo.makeApplication(false, mInstrumentation);
1942             context.setOuterContext(service);
1943             service.attach(context, this, data.info.name, data.token, app,
1944                     ActivityManagerNative.getDefault());
1945             service.onCreate();
1946             mServices.put(data.token, service);
1947             try {
1948                 ActivityManagerNative.getDefault().serviceDoneExecuting(
1949                         data.token, 0, 0, 0);
1950             } catch (RemoteException e) {
1951                 // nothing to do.
1952             }
1953         } catch (Exception e) {
1954             if (!mInstrumentation.onException(service, e)) {
1955                 throw new RuntimeException(
1956                     "Unable to create service " + data.info.name
1957                     + ": " + e.toString(), e);
1958             }
1959         }
1960     }
1961 
handleBindService(BindServiceData data)1962     private final void handleBindService(BindServiceData data) {
1963         Service s = mServices.get(data.token);
1964         if (s != null) {
1965             try {
1966                 data.intent.setExtrasClassLoader(s.getClassLoader());
1967                 try {
1968                     if (!data.rebind) {
1969                         IBinder binder = s.onBind(data.intent);
1970                         ActivityManagerNative.getDefault().publishService(
1971                                 data.token, data.intent, binder);
1972                     } else {
1973                         s.onRebind(data.intent);
1974                         ActivityManagerNative.getDefault().serviceDoneExecuting(
1975                                 data.token, 0, 0, 0);
1976                     }
1977                     ensureJitEnabled();
1978                 } catch (RemoteException ex) {
1979                 }
1980             } catch (Exception e) {
1981                 if (!mInstrumentation.onException(s, e)) {
1982                     throw new RuntimeException(
1983                             "Unable to bind to service " + s
1984                             + " with " + data.intent + ": " + e.toString(), e);
1985                 }
1986             }
1987         }
1988     }
1989 
handleUnbindService(BindServiceData data)1990     private final void handleUnbindService(BindServiceData data) {
1991         Service s = mServices.get(data.token);
1992         if (s != null) {
1993             try {
1994                 data.intent.setExtrasClassLoader(s.getClassLoader());
1995                 boolean doRebind = s.onUnbind(data.intent);
1996                 try {
1997                     if (doRebind) {
1998                         ActivityManagerNative.getDefault().unbindFinished(
1999                                 data.token, data.intent, doRebind);
2000                     } else {
2001                         ActivityManagerNative.getDefault().serviceDoneExecuting(
2002                                 data.token, 0, 0, 0);
2003                     }
2004                 } catch (RemoteException ex) {
2005                 }
2006             } catch (Exception e) {
2007                 if (!mInstrumentation.onException(s, e)) {
2008                     throw new RuntimeException(
2009                             "Unable to unbind to service " + s
2010                             + " with " + data.intent + ": " + e.toString(), e);
2011                 }
2012             }
2013         }
2014     }
2015 
handleDumpService(DumpServiceInfo info)2016     private void handleDumpService(DumpServiceInfo info) {
2017         try {
2018             Service s = mServices.get(info.service);
2019             if (s != null) {
2020                 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
2021                 s.dump(info.fd, pw, info.args);
2022                 pw.close();
2023             }
2024         } finally {
2025             synchronized (info) {
2026                 info.dumped = true;
2027                 info.notifyAll();
2028             }
2029         }
2030     }
2031 
handleServiceArgs(ServiceArgsData data)2032     private final void handleServiceArgs(ServiceArgsData data) {
2033         Service s = mServices.get(data.token);
2034         if (s != null) {
2035             try {
2036                 if (data.args != null) {
2037                     data.args.setExtrasClassLoader(s.getClassLoader());
2038                 }
2039                 int res = s.onStartCommand(data.args, data.flags, data.startId);
2040 
2041                 QueuedWork.waitToFinish();
2042 
2043                 try {
2044                     ActivityManagerNative.getDefault().serviceDoneExecuting(
2045                             data.token, 1, data.startId, res);
2046                 } catch (RemoteException e) {
2047                     // nothing to do.
2048                 }
2049                 ensureJitEnabled();
2050             } catch (Exception e) {
2051                 if (!mInstrumentation.onException(s, e)) {
2052                     throw new RuntimeException(
2053                             "Unable to start service " + s
2054                             + " with " + data.args + ": " + e.toString(), e);
2055                 }
2056             }
2057         }
2058     }
2059 
handleStopService(IBinder token)2060     private final void handleStopService(IBinder token) {
2061         Service s = mServices.remove(token);
2062         if (s != null) {
2063             try {
2064                 if (localLOGV) Slog.v(TAG, "Destroying service " + s);
2065                 s.onDestroy();
2066                 Context context = s.getBaseContext();
2067                 if (context instanceof ContextImpl) {
2068                     final String who = s.getClassName();
2069                     ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
2070                 }
2071 
2072                 QueuedWork.waitToFinish();
2073 
2074                 try {
2075                     ActivityManagerNative.getDefault().serviceDoneExecuting(
2076                             token, 0, 0, 0);
2077                 } catch (RemoteException e) {
2078                     // nothing to do.
2079                 }
2080             } catch (Exception e) {
2081                 if (!mInstrumentation.onException(s, e)) {
2082                     throw new RuntimeException(
2083                             "Unable to stop service " + s
2084                             + ": " + e.toString(), e);
2085                 }
2086             }
2087         }
2088         //Slog.i(TAG, "Running services: " + mServices);
2089     }
2090 
performResumeActivity(IBinder token, boolean clearHide)2091     public final ActivityClientRecord performResumeActivity(IBinder token,
2092             boolean clearHide) {
2093         ActivityClientRecord r = mActivities.get(token);
2094         if (localLOGV) Slog.v(TAG, "Performing resume of " + r
2095                 + " finished=" + r.activity.mFinished);
2096         if (r != null && !r.activity.mFinished) {
2097             if (clearHide) {
2098                 r.hideForNow = false;
2099                 r.activity.mStartedActivity = false;
2100             }
2101             try {
2102                 if (r.pendingIntents != null) {
2103                     deliverNewIntents(r, r.pendingIntents);
2104                     r.pendingIntents = null;
2105                 }
2106                 if (r.pendingResults != null) {
2107                     deliverResults(r, r.pendingResults);
2108                     r.pendingResults = null;
2109                 }
2110                 r.activity.performResume();
2111 
2112                 EventLog.writeEvent(LOG_ON_RESUME_CALLED,
2113                         r.activity.getComponentName().getClassName());
2114 
2115                 r.paused = false;
2116                 r.stopped = false;
2117                 r.state = null;
2118             } catch (Exception e) {
2119                 if (!mInstrumentation.onException(r.activity, e)) {
2120                     throw new RuntimeException(
2121                         "Unable to resume activity "
2122                         + r.intent.getComponent().toShortString()
2123                         + ": " + e.toString(), e);
2124                 }
2125             }
2126         }
2127         return r;
2128     }
2129 
handleResumeActivity(IBinder token, boolean clearHide, boolean isForward)2130     final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
2131         // If we are getting ready to gc after going to the background, well
2132         // we are back active so skip it.
2133         unscheduleGcIdler();
2134 
2135         ActivityClientRecord r = performResumeActivity(token, clearHide);
2136 
2137         if (r != null) {
2138             final Activity a = r.activity;
2139 
2140             if (localLOGV) Slog.v(
2141                 TAG, "Resume " + r + " started activity: " +
2142                 a.mStartedActivity + ", hideForNow: " + r.hideForNow
2143                 + ", finished: " + a.mFinished);
2144 
2145             final int forwardBit = isForward ?
2146                     WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
2147 
2148             // If the window hasn't yet been added to the window manager,
2149             // and this guy didn't finish itself or start another activity,
2150             // then go ahead and add the window.
2151             boolean willBeVisible = !a.mStartedActivity;
2152             if (!willBeVisible) {
2153                 try {
2154                     willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
2155                             a.getActivityToken());
2156                 } catch (RemoteException e) {
2157                 }
2158             }
2159             if (r.window == null && !a.mFinished && willBeVisible) {
2160                 r.window = r.activity.getWindow();
2161                 View decor = r.window.getDecorView();
2162                 decor.setVisibility(View.INVISIBLE);
2163                 ViewManager wm = a.getWindowManager();
2164                 WindowManager.LayoutParams l = r.window.getAttributes();
2165                 a.mDecor = decor;
2166                 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2167                 l.softInputMode |= forwardBit;
2168                 if (a.mVisibleFromClient) {
2169                     a.mWindowAdded = true;
2170                     wm.addView(decor, l);
2171                 }
2172 
2173             // If the window has already been added, but during resume
2174             // we started another activity, then don't yet make the
2175             // window visible.
2176             } else if (!willBeVisible) {
2177                 if (localLOGV) Slog.v(
2178                     TAG, "Launch " + r + " mStartedActivity set");
2179                 r.hideForNow = true;
2180             }
2181 
2182             // The window is now visible if it has been added, we are not
2183             // simply finishing, and we are not starting another activity.
2184             if (!r.activity.mFinished && willBeVisible
2185                     && r.activity.mDecor != null && !r.hideForNow) {
2186                 if (r.newConfig != null) {
2187                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
2188                             + r.activityInfo.name + " with newConfig " + r.newConfig);
2189                     performConfigurationChanged(r.activity, r.newConfig);
2190                     r.newConfig = null;
2191                 }
2192                 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
2193                         + isForward);
2194                 WindowManager.LayoutParams l = r.window.getAttributes();
2195                 if ((l.softInputMode
2196                         & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
2197                         != forwardBit) {
2198                     l.softInputMode = (l.softInputMode
2199                             & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
2200                             | forwardBit;
2201                     if (r.activity.mVisibleFromClient) {
2202                         ViewManager wm = a.getWindowManager();
2203                         View decor = r.window.getDecorView();
2204                         wm.updateViewLayout(decor, l);
2205                     }
2206                 }
2207                 r.activity.mVisibleFromServer = true;
2208                 mNumVisibleActivities++;
2209                 if (r.activity.mVisibleFromClient) {
2210                     r.activity.makeVisible();
2211                 }
2212             }
2213 
2214             r.nextIdle = mNewActivities;
2215             mNewActivities = r;
2216             if (localLOGV) Slog.v(
2217                 TAG, "Scheduling idle handler for " + r);
2218             Looper.myQueue().addIdleHandler(new Idler());
2219 
2220         } else {
2221             // If an exception was thrown when trying to resume, then
2222             // just end this activity.
2223             try {
2224                 ActivityManagerNative.getDefault()
2225                     .finishActivity(token, Activity.RESULT_CANCELED, null);
2226             } catch (RemoteException ex) {
2227             }
2228         }
2229     }
2230 
2231     private int mThumbnailWidth = -1;
2232     private int mThumbnailHeight = -1;
2233 
createThumbnailBitmap(ActivityClientRecord r)2234     private final Bitmap createThumbnailBitmap(ActivityClientRecord r) {
2235         Bitmap thumbnail = null;
2236         try {
2237             int w = mThumbnailWidth;
2238             int h;
2239             if (w < 0) {
2240                 Resources res = r.activity.getResources();
2241                 mThumbnailHeight = h =
2242                     res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
2243 
2244                 mThumbnailWidth = w =
2245                     res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
2246             } else {
2247                 h = mThumbnailHeight;
2248             }
2249 
2250             // On platforms where we don't want thumbnails, set dims to (0,0)
2251             if ((w > 0) && (h > 0)) {
2252                 View topView = r.activity.getWindow().getDecorView();
2253 
2254                 // Maximize bitmap by capturing in native aspect.
2255                 if (topView.getWidth() >= topView.getHeight()) {
2256                     thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT);
2257                 } else {
2258                     thumbnail = Bitmap.createBitmap(h, w, THUMBNAIL_FORMAT);
2259                 }
2260 
2261                 thumbnail.eraseColor(0);
2262                 Canvas cv = new Canvas(thumbnail);
2263                 if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
2264                     thumbnail = null;
2265                 }
2266             }
2267 
2268         } catch (Exception e) {
2269             if (!mInstrumentation.onException(r.activity, e)) {
2270                 throw new RuntimeException(
2271                         "Unable to create thumbnail of "
2272                         + r.intent.getComponent().toShortString()
2273                         + ": " + e.toString(), e);
2274             }
2275             thumbnail = null;
2276         }
2277 
2278         return thumbnail;
2279     }
2280 
handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges)2281     private final void handlePauseActivity(IBinder token, boolean finished,
2282             boolean userLeaving, int configChanges) {
2283         ActivityClientRecord r = mActivities.get(token);
2284         if (r != null) {
2285             //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
2286             if (userLeaving) {
2287                 performUserLeavingActivity(r);
2288             }
2289 
2290             r.activity.mConfigChangeFlags |= configChanges;
2291             Bundle state = performPauseActivity(token, finished, true);
2292 
2293             // Make sure any pending writes are now committed.
2294             QueuedWork.waitToFinish();
2295 
2296             // Tell the activity manager we have paused.
2297             try {
2298                 ActivityManagerNative.getDefault().activityPaused(token, state);
2299             } catch (RemoteException ex) {
2300             }
2301         }
2302     }
2303 
performUserLeavingActivity(ActivityClientRecord r)2304     final void performUserLeavingActivity(ActivityClientRecord r) {
2305         mInstrumentation.callActivityOnUserLeaving(r.activity);
2306     }
2307 
performPauseActivity(IBinder token, boolean finished, boolean saveState)2308     final Bundle performPauseActivity(IBinder token, boolean finished,
2309             boolean saveState) {
2310         ActivityClientRecord r = mActivities.get(token);
2311         return r != null ? performPauseActivity(r, finished, saveState) : null;
2312     }
2313 
performPauseActivity(ActivityClientRecord r, boolean finished, boolean saveState)2314     final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
2315             boolean saveState) {
2316         if (r.paused) {
2317             if (r.activity.mFinished) {
2318                 // If we are finishing, we won't call onResume() in certain cases.
2319                 // So here we likewise don't want to call onPause() if the activity
2320                 // isn't resumed.
2321                 return null;
2322             }
2323             RuntimeException e = new RuntimeException(
2324                     "Performing pause of activity that is not resumed: "
2325                     + r.intent.getComponent().toShortString());
2326             Slog.e(TAG, e.getMessage(), e);
2327         }
2328         Bundle state = null;
2329         if (finished) {
2330             r.activity.mFinished = true;
2331         }
2332         try {
2333             // Next have the activity save its current state and managed dialogs...
2334             if (!r.activity.mFinished && saveState) {
2335                 state = new Bundle();
2336                 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
2337                 r.state = state;
2338             }
2339             // Now we are idle.
2340             r.activity.mCalled = false;
2341             mInstrumentation.callActivityOnPause(r.activity);
2342             EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
2343             if (!r.activity.mCalled) {
2344                 throw new SuperNotCalledException(
2345                     "Activity " + r.intent.getComponent().toShortString() +
2346                     " did not call through to super.onPause()");
2347             }
2348 
2349         } catch (SuperNotCalledException e) {
2350             throw e;
2351 
2352         } catch (Exception e) {
2353             if (!mInstrumentation.onException(r.activity, e)) {
2354                 throw new RuntimeException(
2355                         "Unable to pause activity "
2356                         + r.intent.getComponent().toShortString()
2357                         + ": " + e.toString(), e);
2358             }
2359         }
2360         r.paused = true;
2361 
2362         // Notify any outstanding on paused listeners
2363         ArrayList<OnActivityPausedListener> listeners;
2364         synchronized (mOnPauseListeners) {
2365             listeners = mOnPauseListeners.remove(r.activity);
2366         }
2367         int size = (listeners != null ? listeners.size() : 0);
2368         for (int i = 0; i < size; i++) {
2369             listeners.get(i).onPaused(r.activity);
2370         }
2371 
2372         return state;
2373     }
2374 
performStopActivity(IBinder token)2375     final void performStopActivity(IBinder token) {
2376         ActivityClientRecord r = mActivities.get(token);
2377         performStopActivityInner(r, null, false);
2378     }
2379 
2380     private static class StopInfo {
2381         Bitmap thumbnail;
2382         CharSequence description;
2383     }
2384 
2385     private final class ProviderRefCount {
2386         public int count;
ProviderRefCount(int pCount)2387         ProviderRefCount(int pCount) {
2388             count = pCount;
2389         }
2390     }
2391 
performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown)2392     private final void performStopActivityInner(ActivityClientRecord r,
2393             StopInfo info, boolean keepShown) {
2394         if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
2395         if (r != null) {
2396             if (!keepShown && r.stopped) {
2397                 if (r.activity.mFinished) {
2398                     // If we are finishing, we won't call onResume() in certain
2399                     // cases.  So here we likewise don't want to call onStop()
2400                     // if the activity isn't resumed.
2401                     return;
2402                 }
2403                 RuntimeException e = new RuntimeException(
2404                         "Performing stop of activity that is not resumed: "
2405                         + r.intent.getComponent().toShortString());
2406                 Slog.e(TAG, e.getMessage(), e);
2407             }
2408 
2409             if (info != null) {
2410                 try {
2411                     // First create a thumbnail for the activity...
2412                     info.thumbnail = createThumbnailBitmap(r);
2413                     info.description = r.activity.onCreateDescription();
2414                 } catch (Exception e) {
2415                     if (!mInstrumentation.onException(r.activity, e)) {
2416                         throw new RuntimeException(
2417                                 "Unable to save state of activity "
2418                                 + r.intent.getComponent().toShortString()
2419                                 + ": " + e.toString(), e);
2420                     }
2421                 }
2422             }
2423 
2424             if (!keepShown) {
2425                 try {
2426                     // Now we are idle.
2427                     r.activity.performStop();
2428                 } catch (Exception e) {
2429                     if (!mInstrumentation.onException(r.activity, e)) {
2430                         throw new RuntimeException(
2431                                 "Unable to stop activity "
2432                                 + r.intent.getComponent().toShortString()
2433                                 + ": " + e.toString(), e);
2434                     }
2435                 }
2436                 r.stopped = true;
2437             }
2438 
2439             r.paused = true;
2440         }
2441     }
2442 
updateVisibility(ActivityClientRecord r, boolean show)2443     private final void updateVisibility(ActivityClientRecord r, boolean show) {
2444         View v = r.activity.mDecor;
2445         if (v != null) {
2446             if (show) {
2447                 if (!r.activity.mVisibleFromServer) {
2448                     r.activity.mVisibleFromServer = true;
2449                     mNumVisibleActivities++;
2450                     if (r.activity.mVisibleFromClient) {
2451                         r.activity.makeVisible();
2452                     }
2453                 }
2454                 if (r.newConfig != null) {
2455                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
2456                             + r.activityInfo.name + " with new config " + r.newConfig);
2457                     performConfigurationChanged(r.activity, r.newConfig);
2458                     r.newConfig = null;
2459                 }
2460             } else {
2461                 if (r.activity.mVisibleFromServer) {
2462                     r.activity.mVisibleFromServer = false;
2463                     mNumVisibleActivities--;
2464                     v.setVisibility(View.INVISIBLE);
2465                 }
2466             }
2467         }
2468     }
2469 
handleStopActivity(IBinder token, boolean show, int configChanges)2470     private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
2471         ActivityClientRecord r = mActivities.get(token);
2472         r.activity.mConfigChangeFlags |= configChanges;
2473 
2474         StopInfo info = new StopInfo();
2475         performStopActivityInner(r, info, show);
2476 
2477         if (localLOGV) Slog.v(
2478             TAG, "Finishing stop of " + r + ": show=" + show
2479             + " win=" + r.window);
2480 
2481         updateVisibility(r, show);
2482 
2483         // Tell activity manager we have been stopped.
2484         try {
2485             ActivityManagerNative.getDefault().activityStopped(
2486                 r.token, info.thumbnail, info.description);
2487         } catch (RemoteException ex) {
2488         }
2489     }
2490 
performRestartActivity(IBinder token)2491     final void performRestartActivity(IBinder token) {
2492         ActivityClientRecord r = mActivities.get(token);
2493         if (r.stopped) {
2494             r.activity.performRestart();
2495             r.stopped = false;
2496         }
2497     }
2498 
handleWindowVisibility(IBinder token, boolean show)2499     private final void handleWindowVisibility(IBinder token, boolean show) {
2500         ActivityClientRecord r = mActivities.get(token);
2501         if (!show && !r.stopped) {
2502             performStopActivityInner(r, null, show);
2503         } else if (show && r.stopped) {
2504             // If we are getting ready to gc after going to the background, well
2505             // we are back active so skip it.
2506             unscheduleGcIdler();
2507 
2508             r.activity.performRestart();
2509             r.stopped = false;
2510         }
2511         if (r.activity.mDecor != null) {
2512             if (Config.LOGV) Slog.v(
2513                 TAG, "Handle window " + r + " visibility: " + show);
2514             updateVisibility(r, show);
2515         }
2516     }
2517 
deliverResults(ActivityClientRecord r, List<ResultInfo> results)2518     private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
2519         final int N = results.size();
2520         for (int i=0; i<N; i++) {
2521             ResultInfo ri = results.get(i);
2522             try {
2523                 if (ri.mData != null) {
2524                     ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
2525                 }
2526                 if (DEBUG_RESULTS) Slog.v(TAG,
2527                         "Delivering result to activity " + r + " : " + ri);
2528                 r.activity.dispatchActivityResult(ri.mResultWho,
2529                         ri.mRequestCode, ri.mResultCode, ri.mData);
2530             } catch (Exception e) {
2531                 if (!mInstrumentation.onException(r.activity, e)) {
2532                     throw new RuntimeException(
2533                             "Failure delivering result " + ri + " to activity "
2534                             + r.intent.getComponent().toShortString()
2535                             + ": " + e.toString(), e);
2536                 }
2537             }
2538         }
2539     }
2540 
handleSendResult(ResultData res)2541     private final void handleSendResult(ResultData res) {
2542         ActivityClientRecord r = mActivities.get(res.token);
2543         if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
2544         if (r != null) {
2545             final boolean resumed = !r.paused;
2546             if (!r.activity.mFinished && r.activity.mDecor != null
2547                     && r.hideForNow && resumed) {
2548                 // We had hidden the activity because it started another
2549                 // one...  we have gotten a result back and we are not
2550                 // paused, so make sure our window is visible.
2551                 updateVisibility(r, true);
2552             }
2553             if (resumed) {
2554                 try {
2555                     // Now we are idle.
2556                     r.activity.mCalled = false;
2557                     mInstrumentation.callActivityOnPause(r.activity);
2558                     if (!r.activity.mCalled) {
2559                         throw new SuperNotCalledException(
2560                             "Activity " + r.intent.getComponent().toShortString()
2561                             + " did not call through to super.onPause()");
2562                     }
2563                 } catch (SuperNotCalledException e) {
2564                     throw e;
2565                 } catch (Exception e) {
2566                     if (!mInstrumentation.onException(r.activity, e)) {
2567                         throw new RuntimeException(
2568                                 "Unable to pause activity "
2569                                 + r.intent.getComponent().toShortString()
2570                                 + ": " + e.toString(), e);
2571                     }
2572                 }
2573             }
2574             deliverResults(r, res.results);
2575             if (resumed) {
2576                 mInstrumentation.callActivityOnResume(r.activity);
2577             }
2578         }
2579     }
2580 
performDestroyActivity(IBinder token, boolean finishing)2581     public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
2582         return performDestroyActivity(token, finishing, 0, false);
2583     }
2584 
performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance)2585     private final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
2586             int configChanges, boolean getNonConfigInstance) {
2587         ActivityClientRecord r = mActivities.get(token);
2588         if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
2589         if (r != null) {
2590             r.activity.mConfigChangeFlags |= configChanges;
2591             if (finishing) {
2592                 r.activity.mFinished = true;
2593             }
2594             if (!r.paused) {
2595                 try {
2596                     r.activity.mCalled = false;
2597                     mInstrumentation.callActivityOnPause(r.activity);
2598                     EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
2599                             r.activity.getComponentName().getClassName());
2600                     if (!r.activity.mCalled) {
2601                         throw new SuperNotCalledException(
2602                             "Activity " + safeToComponentShortString(r.intent)
2603                             + " did not call through to super.onPause()");
2604                     }
2605                 } catch (SuperNotCalledException e) {
2606                     throw e;
2607                 } catch (Exception e) {
2608                     if (!mInstrumentation.onException(r.activity, e)) {
2609                         throw new RuntimeException(
2610                                 "Unable to pause activity "
2611                                 + safeToComponentShortString(r.intent)
2612                                 + ": " + e.toString(), e);
2613                     }
2614                 }
2615                 r.paused = true;
2616             }
2617             if (!r.stopped) {
2618                 try {
2619                     r.activity.performStop();
2620                 } catch (SuperNotCalledException e) {
2621                     throw e;
2622                 } catch (Exception e) {
2623                     if (!mInstrumentation.onException(r.activity, e)) {
2624                         throw new RuntimeException(
2625                                 "Unable to stop activity "
2626                                 + safeToComponentShortString(r.intent)
2627                                 + ": " + e.toString(), e);
2628                     }
2629                 }
2630                 r.stopped = true;
2631             }
2632             if (getNonConfigInstance) {
2633                 try {
2634                     r.lastNonConfigurationInstance
2635                             = r.activity.onRetainNonConfigurationInstance();
2636                 } catch (Exception e) {
2637                     if (!mInstrumentation.onException(r.activity, e)) {
2638                         throw new RuntimeException(
2639                                 "Unable to retain activity "
2640                                 + r.intent.getComponent().toShortString()
2641                                 + ": " + e.toString(), e);
2642                     }
2643                 }
2644                 try {
2645                     r.lastNonConfigurationChildInstances
2646                             = r.activity.onRetainNonConfigurationChildInstances();
2647                 } catch (Exception e) {
2648                     if (!mInstrumentation.onException(r.activity, e)) {
2649                         throw new RuntimeException(
2650                                 "Unable to retain child activities "
2651                                 + safeToComponentShortString(r.intent)
2652                                 + ": " + e.toString(), e);
2653                     }
2654                 }
2655 
2656             }
2657             try {
2658                 r.activity.mCalled = false;
2659                 r.activity.onDestroy();
2660                 if (!r.activity.mCalled) {
2661                     throw new SuperNotCalledException(
2662                         "Activity " + safeToComponentShortString(r.intent) +
2663                         " did not call through to super.onDestroy()");
2664                 }
2665                 if (r.window != null) {
2666                     r.window.closeAllPanels();
2667                 }
2668             } catch (SuperNotCalledException e) {
2669                 throw e;
2670             } catch (Exception e) {
2671                 if (!mInstrumentation.onException(r.activity, e)) {
2672                     throw new RuntimeException(
2673                             "Unable to destroy activity " + safeToComponentShortString(r.intent)
2674                             + ": " + e.toString(), e);
2675                 }
2676             }
2677         }
2678         mActivities.remove(token);
2679 
2680         return r;
2681     }
2682 
safeToComponentShortString(Intent intent)2683     private static String safeToComponentShortString(Intent intent) {
2684         ComponentName component = intent.getComponent();
2685         return component == null ? "[Unknown]" : component.toShortString();
2686     }
2687 
handleDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance)2688     private final void handleDestroyActivity(IBinder token, boolean finishing,
2689             int configChanges, boolean getNonConfigInstance) {
2690         ActivityClientRecord r = performDestroyActivity(token, finishing,
2691                 configChanges, getNonConfigInstance);
2692         if (r != null) {
2693             WindowManager wm = r.activity.getWindowManager();
2694             View v = r.activity.mDecor;
2695             if (v != null) {
2696                 if (r.activity.mVisibleFromServer) {
2697                     mNumVisibleActivities--;
2698                 }
2699                 IBinder wtoken = v.getWindowToken();
2700                 if (r.activity.mWindowAdded) {
2701                     wm.removeViewImmediate(v);
2702                 }
2703                 if (wtoken != null) {
2704                     WindowManagerImpl.getDefault().closeAll(wtoken,
2705                             r.activity.getClass().getName(), "Activity");
2706                 }
2707                 r.activity.mDecor = null;
2708             }
2709             WindowManagerImpl.getDefault().closeAll(token,
2710                     r.activity.getClass().getName(), "Activity");
2711 
2712             // Mocked out contexts won't be participating in the normal
2713             // process lifecycle, but if we're running with a proper
2714             // ApplicationContext we need to have it tear down things
2715             // cleanly.
2716             Context c = r.activity.getBaseContext();
2717             if (c instanceof ContextImpl) {
2718                 ((ContextImpl) c).scheduleFinalCleanup(
2719                         r.activity.getClass().getName(), "Activity");
2720             }
2721         }
2722         if (finishing) {
2723             try {
2724                 ActivityManagerNative.getDefault().activityDestroyed(token);
2725             } catch (RemoteException ex) {
2726                 // If the system process has died, it's game over for everyone.
2727             }
2728         }
2729     }
2730 
handleRelaunchActivity(ActivityClientRecord tmp, int configChanges)2731     private final void handleRelaunchActivity(ActivityClientRecord tmp, int configChanges) {
2732         // If we are getting ready to gc after going to the background, well
2733         // we are back active so skip it.
2734         unscheduleGcIdler();
2735 
2736         Configuration changedConfig = null;
2737 
2738         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
2739                 + tmp.token + " with configChanges=0x"
2740                 + Integer.toHexString(configChanges));
2741 
2742         // First: make sure we have the most recent configuration and most
2743         // recent version of the activity, or skip it if some previous call
2744         // had taken a more recent version.
2745         synchronized (mPackages) {
2746             int N = mRelaunchingActivities.size();
2747             IBinder token = tmp.token;
2748             tmp = null;
2749             for (int i=0; i<N; i++) {
2750                 ActivityClientRecord r = mRelaunchingActivities.get(i);
2751                 if (r.token == token) {
2752                     tmp = r;
2753                     mRelaunchingActivities.remove(i);
2754                     i--;
2755                     N--;
2756                 }
2757             }
2758 
2759             if (tmp == null) {
2760                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
2761                 return;
2762             }
2763 
2764             if (mPendingConfiguration != null) {
2765                 changedConfig = mPendingConfiguration;
2766                 mPendingConfiguration = null;
2767             }
2768         }
2769 
2770         if (tmp.createdConfig != null) {
2771             // If the activity manager is passing us its current config,
2772             // assume that is really what we want regardless of what we
2773             // may have pending.
2774             if (mConfiguration == null
2775                     || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
2776                             && mConfiguration.diff(tmp.createdConfig) != 0)) {
2777                 if (changedConfig == null
2778                         || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
2779                     changedConfig = tmp.createdConfig;
2780                 }
2781             }
2782         }
2783 
2784         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
2785                 + tmp.token + ": changedConfig=" + changedConfig);
2786 
2787         // If there was a pending configuration change, execute it first.
2788         if (changedConfig != null) {
2789             handleConfigurationChanged(changedConfig);
2790         }
2791 
2792         ActivityClientRecord r = mActivities.get(tmp.token);
2793         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
2794         if (r == null) {
2795             return;
2796         }
2797 
2798         r.activity.mConfigChangeFlags |= configChanges;
2799         Intent currentIntent = r.activity.mIntent;
2800 
2801         Bundle savedState = null;
2802         if (!r.paused) {
2803             savedState = performPauseActivity(r.token, false, true);
2804         }
2805 
2806         handleDestroyActivity(r.token, false, configChanges, true);
2807 
2808         r.activity = null;
2809         r.window = null;
2810         r.hideForNow = false;
2811         r.nextIdle = null;
2812         // Merge any pending results and pending intents; don't just replace them
2813         if (tmp.pendingResults != null) {
2814             if (r.pendingResults == null) {
2815                 r.pendingResults = tmp.pendingResults;
2816             } else {
2817                 r.pendingResults.addAll(tmp.pendingResults);
2818             }
2819         }
2820         if (tmp.pendingIntents != null) {
2821             if (r.pendingIntents == null) {
2822                 r.pendingIntents = tmp.pendingIntents;
2823             } else {
2824                 r.pendingIntents.addAll(tmp.pendingIntents);
2825             }
2826         }
2827         r.startsNotResumed = tmp.startsNotResumed;
2828         if (savedState != null) {
2829             r.state = savedState;
2830         }
2831 
2832         handleLaunchActivity(r, currentIntent);
2833     }
2834 
handleRequestThumbnail(IBinder token)2835     private final void handleRequestThumbnail(IBinder token) {
2836         ActivityClientRecord r = mActivities.get(token);
2837         Bitmap thumbnail = createThumbnailBitmap(r);
2838         CharSequence description = null;
2839         try {
2840             description = r.activity.onCreateDescription();
2841         } catch (Exception e) {
2842             if (!mInstrumentation.onException(r.activity, e)) {
2843                 throw new RuntimeException(
2844                         "Unable to create description of activity "
2845                         + r.intent.getComponent().toShortString()
2846                         + ": " + e.toString(), e);
2847             }
2848         }
2849         //System.out.println("Reporting top thumbnail " + thumbnail);
2850         try {
2851             ActivityManagerNative.getDefault().reportThumbnail(
2852                 token, thumbnail, description);
2853         } catch (RemoteException ex) {
2854         }
2855     }
2856 
collectComponentCallbacksLocked( boolean allActivities, Configuration newConfig)2857     ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
2858             boolean allActivities, Configuration newConfig) {
2859         ArrayList<ComponentCallbacks> callbacks
2860                 = new ArrayList<ComponentCallbacks>();
2861 
2862         if (mActivities.size() > 0) {
2863             Iterator<ActivityClientRecord> it = mActivities.values().iterator();
2864             while (it.hasNext()) {
2865                 ActivityClientRecord ar = it.next();
2866                 Activity a = ar.activity;
2867                 if (a != null) {
2868                     if (!ar.activity.mFinished && (allActivities ||
2869                             (a != null && !ar.paused))) {
2870                         // If the activity is currently resumed, its configuration
2871                         // needs to change right now.
2872                         callbacks.add(a);
2873                     } else if (newConfig != null) {
2874                         // Otherwise, we will tell it about the change
2875                         // the next time it is resumed or shown.  Note that
2876                         // the activity manager may, before then, decide the
2877                         // activity needs to be destroyed to handle its new
2878                         // configuration.
2879                         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity "
2880                                 + ar.activityInfo.name + " newConfig=" + newConfig);
2881                         ar.newConfig = newConfig;
2882                     }
2883                 }
2884             }
2885         }
2886         if (mServices.size() > 0) {
2887             Iterator<Service> it = mServices.values().iterator();
2888             while (it.hasNext()) {
2889                 callbacks.add(it.next());
2890             }
2891         }
2892         synchronized (mProviderMap) {
2893             if (mLocalProviders.size() > 0) {
2894                 Iterator<ProviderClientRecord> it = mLocalProviders.values().iterator();
2895                 while (it.hasNext()) {
2896                     callbacks.add(it.next().mLocalProvider);
2897                 }
2898             }
2899         }
2900         final int N = mAllApplications.size();
2901         for (int i=0; i<N; i++) {
2902             callbacks.add(mAllApplications.get(i));
2903         }
2904 
2905         return callbacks;
2906     }
2907 
performConfigurationChanged( ComponentCallbacks cb, Configuration config)2908     private final void performConfigurationChanged(
2909             ComponentCallbacks cb, Configuration config) {
2910         // Only for Activity objects, check that they actually call up to their
2911         // superclass implementation.  ComponentCallbacks is an interface, so
2912         // we check the runtime type and act accordingly.
2913         Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
2914         if (activity != null) {
2915             activity.mCalled = false;
2916         }
2917 
2918         boolean shouldChangeConfig = false;
2919         if ((activity == null) || (activity.mCurrentConfig == null)) {
2920             shouldChangeConfig = true;
2921         } else {
2922 
2923             // If the new config is the same as the config this Activity
2924             // is already running with then don't bother calling
2925             // onConfigurationChanged
2926             int diff = activity.mCurrentConfig.diff(config);
2927             if (diff != 0) {
2928 
2929                 // If this activity doesn't handle any of the config changes
2930                 // then don't bother calling onConfigurationChanged as we're
2931                 // going to destroy it.
2932                 if ((~activity.mActivityInfo.configChanges & diff) == 0) {
2933                     shouldChangeConfig = true;
2934                 }
2935             }
2936         }
2937 
2938         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
2939                 + ": shouldChangeConfig=" + shouldChangeConfig);
2940         if (shouldChangeConfig) {
2941             cb.onConfigurationChanged(config);
2942 
2943             if (activity != null) {
2944                 if (!activity.mCalled) {
2945                     throw new SuperNotCalledException(
2946                             "Activity " + activity.getLocalClassName() +
2947                         " did not call through to super.onConfigurationChanged()");
2948                 }
2949                 activity.mConfigChangeFlags = 0;
2950                 activity.mCurrentConfig = new Configuration(config);
2951             }
2952         }
2953     }
2954 
applyConfigurationToResourcesLocked(Configuration config)2955     final boolean applyConfigurationToResourcesLocked(Configuration config) {
2956         if (mResConfiguration == null) {
2957             mResConfiguration = new Configuration();
2958         }
2959         if (!mResConfiguration.isOtherSeqNewer(config)) {
2960             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
2961                     + mResConfiguration.seq + ", newSeq=" + config.seq);
2962             return false;
2963         }
2964         int changes = mResConfiguration.updateFrom(config);
2965         DisplayMetrics dm = getDisplayMetricsLocked(true);
2966 
2967         // set it for java, this also affects newly created Resources
2968         if (config.locale != null) {
2969             Locale.setDefault(config.locale);
2970         }
2971 
2972         Resources.updateSystemConfiguration(config, dm);
2973 
2974         ContextImpl.ApplicationPackageManager.configurationChanged();
2975         //Slog.i(TAG, "Configuration changed in " + currentPackageName());
2976 
2977         Iterator<WeakReference<Resources>> it =
2978             mActiveResources.values().iterator();
2979         //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
2980         //    mActiveResources.entrySet().iterator();
2981         while (it.hasNext()) {
2982             WeakReference<Resources> v = it.next();
2983             Resources r = v.get();
2984             if (r != null) {
2985                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
2986                         + r + " config to: " + config);
2987                 r.updateConfiguration(config, dm);
2988                 //Slog.i(TAG, "Updated app resources " + v.getKey()
2989                 //        + " " + r + ": " + r.getConfiguration());
2990             } else {
2991                 //Slog.i(TAG, "Removing old resources " + v.getKey());
2992                 it.remove();
2993             }
2994         }
2995 
2996         return changes != 0;
2997     }
2998 
handleConfigurationChanged(Configuration config)2999     final void handleConfigurationChanged(Configuration config) {
3000 
3001         ArrayList<ComponentCallbacks> callbacks = null;
3002 
3003         synchronized (mPackages) {
3004             if (mPendingConfiguration != null) {
3005                 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
3006                     config = mPendingConfiguration;
3007                 }
3008                 mPendingConfiguration = null;
3009             }
3010 
3011             if (config == null) {
3012                 return;
3013             }
3014 
3015             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
3016                     + config);
3017 
3018             applyConfigurationToResourcesLocked(config);
3019 
3020             if (mConfiguration == null) {
3021                 mConfiguration = new Configuration();
3022             }
3023             if (!mConfiguration.isOtherSeqNewer(config)) {
3024                 return;
3025             }
3026             mConfiguration.updateFrom(config);
3027 
3028             callbacks = collectComponentCallbacksLocked(false, config);
3029         }
3030 
3031         if (callbacks != null) {
3032             final int N = callbacks.size();
3033             for (int i=0; i<N; i++) {
3034                 performConfigurationChanged(callbacks.get(i), config);
3035             }
3036         }
3037     }
3038 
handleActivityConfigurationChanged(IBinder token)3039     final void handleActivityConfigurationChanged(IBinder token) {
3040         ActivityClientRecord r = mActivities.get(token);
3041         if (r == null || r.activity == null) {
3042             return;
3043         }
3044 
3045         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
3046                 + r.activityInfo.name);
3047 
3048         performConfigurationChanged(r.activity, mConfiguration);
3049     }
3050 
handleProfilerControl(boolean start, ProfilerControlData pcd)3051     final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
3052         if (start) {
3053             try {
3054                 Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
3055                         8 * 1024 * 1024, 0);
3056             } catch (RuntimeException e) {
3057                 Slog.w(TAG, "Profiling failed on path " + pcd.path
3058                         + " -- can the process access this path?");
3059             } finally {
3060                 try {
3061                     pcd.fd.close();
3062                 } catch (IOException e) {
3063                     Slog.w(TAG, "Failure closing profile fd", e);
3064                 }
3065             }
3066         } else {
3067             Debug.stopMethodTracing();
3068         }
3069     }
3070 
handleDispatchPackageBroadcast(int cmd, String[] packages)3071     final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
3072         boolean hasPkgInfo = false;
3073         if (packages != null) {
3074             for (int i=packages.length-1; i>=0; i--) {
3075                 //Slog.i(TAG, "Cleaning old package: " + packages[i]);
3076                 if (!hasPkgInfo) {
3077                     WeakReference<LoadedApk> ref;
3078                     ref = mPackages.get(packages[i]);
3079                     if (ref != null && ref.get() != null) {
3080                         hasPkgInfo = true;
3081                     } else {
3082                         ref = mResourcePackages.get(packages[i]);
3083                         if (ref != null && ref.get() != null) {
3084                             hasPkgInfo = true;
3085                         }
3086                     }
3087                 }
3088                 mPackages.remove(packages[i]);
3089                 mResourcePackages.remove(packages[i]);
3090             }
3091         }
3092         ContextImpl.ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
3093                 hasPkgInfo);
3094     }
3095 
handleLowMemory()3096     final void handleLowMemory() {
3097         ArrayList<ComponentCallbacks> callbacks
3098                 = new ArrayList<ComponentCallbacks>();
3099 
3100         synchronized (mPackages) {
3101             callbacks = collectComponentCallbacksLocked(true, null);
3102         }
3103 
3104         final int N = callbacks.size();
3105         for (int i=0; i<N; i++) {
3106             callbacks.get(i).onLowMemory();
3107         }
3108 
3109         // Ask SQLite to free up as much memory as it can, mostly from its page caches.
3110         if (Process.myUid() != Process.SYSTEM_UID) {
3111             int sqliteReleased = SQLiteDatabase.releaseMemory();
3112             EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
3113         }
3114 
3115         // Ask graphics to free up as much as possible (font/image caches)
3116         Canvas.freeCaches();
3117 
3118         BinderInternal.forceGc("mem");
3119     }
3120 
handleBindApplication(AppBindData data)3121     private final void handleBindApplication(AppBindData data) {
3122         mBoundApplication = data;
3123         mConfiguration = new Configuration(data.config);
3124 
3125         // send up app name; do this *before* waiting for debugger
3126         Process.setArgV0(data.processName);
3127         android.ddm.DdmHandleAppName.setAppName(data.processName);
3128 
3129         /*
3130          * Before spawning a new process, reset the time zone to be the system time zone.
3131          * This needs to be done because the system time zone could have changed after the
3132          * the spawning of this process. Without doing this this process would have the incorrect
3133          * system time zone.
3134          */
3135         TimeZone.setDefault(null);
3136 
3137         /*
3138          * Initialize the default locale in this process for the reasons we set the time zone.
3139          */
3140         Locale.setDefault(data.config.locale);
3141 
3142         /*
3143          * Update the system configuration since its preloaded and might not
3144          * reflect configuration changes. The configuration object passed
3145          * in AppBindData can be safely assumed to be up to date
3146          */
3147         Resources.getSystem().updateConfiguration(mConfiguration, null);
3148 
3149         data.info = getPackageInfoNoCheck(data.appInfo);
3150 
3151         /**
3152          * For system applications on userdebug/eng builds, log stack
3153          * traces of disk and network access to dropbox for analysis.
3154          */
3155         if ((data.appInfo.flags &
3156              (ApplicationInfo.FLAG_SYSTEM |
3157               ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
3158             StrictMode.conditionallyEnableDebugLogging();
3159         }
3160 
3161         /**
3162          * Switch this process to density compatibility mode if needed.
3163          */
3164         if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
3165                 == 0) {
3166             Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
3167         }
3168 
3169         if (data.debugMode != IApplicationThread.DEBUG_OFF) {
3170             // XXX should have option to change the port.
3171             Debug.changeDebugPort(8100);
3172             if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
3173                 Slog.w(TAG, "Application " + data.info.getPackageName()
3174                       + " is waiting for the debugger on port 8100...");
3175 
3176                 IActivityManager mgr = ActivityManagerNative.getDefault();
3177                 try {
3178                     mgr.showWaitingForDebugger(mAppThread, true);
3179                 } catch (RemoteException ex) {
3180                 }
3181 
3182                 Debug.waitForDebugger();
3183 
3184                 try {
3185                     mgr.showWaitingForDebugger(mAppThread, false);
3186                 } catch (RemoteException ex) {
3187                 }
3188 
3189             } else {
3190                 Slog.w(TAG, "Application " + data.info.getPackageName()
3191                       + " can be debugged on port 8100...");
3192             }
3193         }
3194 
3195         if (data.instrumentationName != null) {
3196             ContextImpl appContext = new ContextImpl();
3197             appContext.init(data.info, null, this);
3198             InstrumentationInfo ii = null;
3199             try {
3200                 ii = appContext.getPackageManager().
3201                     getInstrumentationInfo(data.instrumentationName, 0);
3202             } catch (PackageManager.NameNotFoundException e) {
3203             }
3204             if (ii == null) {
3205                 throw new RuntimeException(
3206                     "Unable to find instrumentation info for: "
3207                     + data.instrumentationName);
3208             }
3209 
3210             mInstrumentationAppDir = ii.sourceDir;
3211             mInstrumentationAppPackage = ii.packageName;
3212             mInstrumentedAppDir = data.info.getAppDir();
3213 
3214             ApplicationInfo instrApp = new ApplicationInfo();
3215             instrApp.packageName = ii.packageName;
3216             instrApp.sourceDir = ii.sourceDir;
3217             instrApp.publicSourceDir = ii.publicSourceDir;
3218             instrApp.dataDir = ii.dataDir;
3219             instrApp.nativeLibraryDir = ii.nativeLibraryDir;
3220             LoadedApk pi = getPackageInfo(instrApp,
3221                     appContext.getClassLoader(), false, true);
3222             ContextImpl instrContext = new ContextImpl();
3223             instrContext.init(pi, null, this);
3224 
3225             try {
3226                 java.lang.ClassLoader cl = instrContext.getClassLoader();
3227                 mInstrumentation = (Instrumentation)
3228                     cl.loadClass(data.instrumentationName.getClassName()).newInstance();
3229             } catch (Exception e) {
3230                 throw new RuntimeException(
3231                     "Unable to instantiate instrumentation "
3232                     + data.instrumentationName + ": " + e.toString(), e);
3233             }
3234 
3235             mInstrumentation.init(this, instrContext, appContext,
3236                     new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
3237 
3238             if (data.profileFile != null && !ii.handleProfiling) {
3239                 data.handlingProfiling = true;
3240                 File file = new File(data.profileFile);
3241                 file.getParentFile().mkdirs();
3242                 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
3243             }
3244 
3245             try {
3246                 mInstrumentation.onCreate(data.instrumentationArgs);
3247             }
3248             catch (Exception e) {
3249                 throw new RuntimeException(
3250                     "Exception thrown in onCreate() of "
3251                     + data.instrumentationName + ": " + e.toString(), e);
3252             }
3253 
3254         } else {
3255             mInstrumentation = new Instrumentation();
3256         }
3257 
3258         // If the app is being launched for full backup or restore, bring it up in
3259         // a restricted environment with the base application class.
3260         Application app = data.info.makeApplication(data.restrictedBackupMode, null);
3261         mInitialApplication = app;
3262 
3263         List<ProviderInfo> providers = data.providers;
3264         if (providers != null) {
3265             installContentProviders(app, providers);
3266             // For process that contain content providers, we want to
3267             // ensure that the JIT is enabled "at some point".
3268             mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
3269         }
3270 
3271         try {
3272             mInstrumentation.callApplicationOnCreate(app);
3273         } catch (Exception e) {
3274             if (!mInstrumentation.onException(app, e)) {
3275                 throw new RuntimeException(
3276                     "Unable to create application " + app.getClass().getName()
3277                     + ": " + e.toString(), e);
3278             }
3279         }
3280     }
3281 
finishInstrumentation(int resultCode, Bundle results)3282     /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
3283         IActivityManager am = ActivityManagerNative.getDefault();
3284         if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
3285             Debug.stopMethodTracing();
3286         }
3287         //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
3288         //      + ", app thr: " + mAppThread);
3289         try {
3290             am.finishInstrumentation(mAppThread, resultCode, results);
3291         } catch (RemoteException ex) {
3292         }
3293     }
3294 
installContentProviders( Context context, List<ProviderInfo> providers)3295     private final void installContentProviders(
3296             Context context, List<ProviderInfo> providers) {
3297         final ArrayList<IActivityManager.ContentProviderHolder> results =
3298             new ArrayList<IActivityManager.ContentProviderHolder>();
3299 
3300         Iterator<ProviderInfo> i = providers.iterator();
3301         while (i.hasNext()) {
3302             ProviderInfo cpi = i.next();
3303             StringBuilder buf = new StringBuilder(128);
3304             buf.append("Pub ");
3305             buf.append(cpi.authority);
3306             buf.append(": ");
3307             buf.append(cpi.name);
3308             Log.i(TAG, buf.toString());
3309             IContentProvider cp = installProvider(context, null, cpi, false);
3310             if (cp != null) {
3311                 IActivityManager.ContentProviderHolder cph =
3312                     new IActivityManager.ContentProviderHolder(cpi);
3313                 cph.provider = cp;
3314                 results.add(cph);
3315                 // Don't ever unload this provider from the process.
3316                 synchronized(mProviderMap) {
3317                     mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
3318                 }
3319             }
3320         }
3321 
3322         try {
3323             ActivityManagerNative.getDefault().publishContentProviders(
3324                 getApplicationThread(), results);
3325         } catch (RemoteException ex) {
3326         }
3327     }
3328 
getExistingProvider(Context context, String name)3329     private final IContentProvider getExistingProvider(Context context, String name) {
3330         synchronized(mProviderMap) {
3331             final ProviderClientRecord pr = mProviderMap.get(name);
3332             if (pr != null) {
3333                 return pr.mProvider;
3334             }
3335             return null;
3336         }
3337     }
3338 
getProvider(Context context, String name)3339     private final IContentProvider getProvider(Context context, String name) {
3340         IContentProvider existing = getExistingProvider(context, name);
3341         if (existing != null) {
3342             return existing;
3343         }
3344 
3345         IActivityManager.ContentProviderHolder holder = null;
3346         try {
3347             holder = ActivityManagerNative.getDefault().getContentProvider(
3348                 getApplicationThread(), name);
3349         } catch (RemoteException ex) {
3350         }
3351         if (holder == null) {
3352             Slog.e(TAG, "Failed to find provider info for " + name);
3353             return null;
3354         }
3355 
3356         IContentProvider prov = installProvider(context, holder.provider,
3357                 holder.info, true);
3358         //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
3359         if (holder.noReleaseNeeded || holder.provider == null) {
3360             // We are not going to release the provider if it is an external
3361             // provider that doesn't care about being released, or if it is
3362             // a local provider running in this process.
3363             //Slog.i(TAG, "*** NO RELEASE NEEDED");
3364             synchronized(mProviderMap) {
3365                 mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
3366             }
3367         }
3368         return prov;
3369     }
3370 
acquireProvider(Context c, String name)3371     public final IContentProvider acquireProvider(Context c, String name) {
3372         IContentProvider provider = getProvider(c, name);
3373         if(provider == null)
3374             return null;
3375         IBinder jBinder = provider.asBinder();
3376         synchronized(mProviderMap) {
3377             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
3378             if(prc == null) {
3379                 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
3380             } else {
3381                 prc.count++;
3382             } //end else
3383         } //end synchronized
3384         return provider;
3385     }
3386 
acquireExistingProvider(Context c, String name)3387     public final IContentProvider acquireExistingProvider(Context c, String name) {
3388         IContentProvider provider = getExistingProvider(c, name);
3389         if(provider == null)
3390             return null;
3391         IBinder jBinder = provider.asBinder();
3392         synchronized(mProviderMap) {
3393             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
3394             if(prc == null) {
3395                 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
3396             } else {
3397                 prc.count++;
3398             } //end else
3399         } //end synchronized
3400         return provider;
3401     }
3402 
releaseProvider(IContentProvider provider)3403     public final boolean releaseProvider(IContentProvider provider) {
3404         if(provider == null) {
3405             return false;
3406         }
3407         IBinder jBinder = provider.asBinder();
3408         synchronized(mProviderMap) {
3409             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
3410             if(prc == null) {
3411                 if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldn't be here");
3412                 return false;
3413             } else {
3414                 prc.count--;
3415                 if(prc.count == 0) {
3416                     // Schedule the actual remove asynchronously, since we
3417                     // don't know the context this will be called in.
3418                     // TODO: it would be nice to post a delayed message, so
3419                     // if we come back and need the same provider quickly
3420                     // we will still have it available.
3421                     Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
3422                     mH.sendMessage(msg);
3423                 } //end if
3424             } //end else
3425         } //end synchronized
3426         return true;
3427     }
3428 
completeRemoveProvider(IContentProvider provider)3429     final void completeRemoveProvider(IContentProvider provider) {
3430         IBinder jBinder = provider.asBinder();
3431         String name = null;
3432         synchronized(mProviderMap) {
3433             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
3434             if(prc != null && prc.count == 0) {
3435                 mProviderRefCountMap.remove(jBinder);
3436                 //invoke removeProvider to dereference provider
3437                 name = removeProviderLocked(provider);
3438             }
3439         }
3440 
3441         if (name != null) {
3442             try {
3443                 if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " +
3444                         "ActivityManagerNative.removeContentProvider(" + name);
3445                 ActivityManagerNative.getDefault().removeContentProvider(
3446                         getApplicationThread(), name);
3447             } catch (RemoteException e) {
3448                 //do nothing content provider object is dead any way
3449             } //end catch
3450         }
3451     }
3452 
removeProviderLocked(IContentProvider provider)3453     public final String removeProviderLocked(IContentProvider provider) {
3454         if (provider == null) {
3455             return null;
3456         }
3457         IBinder providerBinder = provider.asBinder();
3458 
3459         String name = null;
3460 
3461         // remove the provider from mProviderMap
3462         Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
3463         while (iter.hasNext()) {
3464             ProviderClientRecord pr = iter.next();
3465             IBinder myBinder = pr.mProvider.asBinder();
3466             if (myBinder == providerBinder) {
3467                 //find if its published by this process itself
3468                 if(pr.mLocalProvider != null) {
3469                     if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning");
3470                     return name;
3471                 }
3472                 if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " +
3473                         "death recipient");
3474                 //content provider is in another process
3475                 myBinder.unlinkToDeath(pr, 0);
3476                 iter.remove();
3477                 //invoke remove only once for the very first name seen
3478                 if(name == null) {
3479                     name = pr.mName;
3480                 }
3481             } //end if myBinder
3482         }  //end while iter
3483 
3484         return name;
3485     }
3486 
removeDeadProvider(String name, IContentProvider provider)3487     final void removeDeadProvider(String name, IContentProvider provider) {
3488         synchronized(mProviderMap) {
3489             ProviderClientRecord pr = mProviderMap.get(name);
3490             if (pr.mProvider.asBinder() == provider.asBinder()) {
3491                 Slog.i(TAG, "Removing dead content provider: " + name);
3492                 ProviderClientRecord removed = mProviderMap.remove(name);
3493                 if (removed != null) {
3494                     removed.mProvider.asBinder().unlinkToDeath(removed, 0);
3495                 }
3496             }
3497         }
3498     }
3499 
removeDeadProviderLocked(String name, IContentProvider provider)3500     final void removeDeadProviderLocked(String name, IContentProvider provider) {
3501         ProviderClientRecord pr = mProviderMap.get(name);
3502         if (pr.mProvider.asBinder() == provider.asBinder()) {
3503             Slog.i(TAG, "Removing dead content provider: " + name);
3504             ProviderClientRecord removed = mProviderMap.remove(name);
3505             if (removed != null) {
3506                 removed.mProvider.asBinder().unlinkToDeath(removed, 0);
3507             }
3508         }
3509     }
3510 
installProvider(Context context, IContentProvider provider, ProviderInfo info, boolean noisy)3511     private final IContentProvider installProvider(Context context,
3512             IContentProvider provider, ProviderInfo info, boolean noisy) {
3513         ContentProvider localProvider = null;
3514         if (provider == null) {
3515             if (noisy) {
3516                 Slog.d(TAG, "Loading provider " + info.authority + ": "
3517                         + info.name);
3518             }
3519             Context c = null;
3520             ApplicationInfo ai = info.applicationInfo;
3521             if (context.getPackageName().equals(ai.packageName)) {
3522                 c = context;
3523             } else if (mInitialApplication != null &&
3524                     mInitialApplication.getPackageName().equals(ai.packageName)) {
3525                 c = mInitialApplication;
3526             } else {
3527                 try {
3528                     c = context.createPackageContext(ai.packageName,
3529                             Context.CONTEXT_INCLUDE_CODE);
3530                 } catch (PackageManager.NameNotFoundException e) {
3531                 }
3532             }
3533             if (c == null) {
3534                 Slog.w(TAG, "Unable to get context for package " +
3535                       ai.packageName +
3536                       " while loading content provider " +
3537                       info.name);
3538                 return null;
3539             }
3540             try {
3541                 final java.lang.ClassLoader cl = c.getClassLoader();
3542                 localProvider = (ContentProvider)cl.
3543                     loadClass(info.name).newInstance();
3544                 provider = localProvider.getIContentProvider();
3545                 if (provider == null) {
3546                     Slog.e(TAG, "Failed to instantiate class " +
3547                           info.name + " from sourceDir " +
3548                           info.applicationInfo.sourceDir);
3549                     return null;
3550                 }
3551                 if (Config.LOGV) Slog.v(
3552                     TAG, "Instantiating local provider " + info.name);
3553                 // XXX Need to create the correct context for this provider.
3554                 localProvider.attachInfo(c, info);
3555             } catch (java.lang.Exception e) {
3556                 if (!mInstrumentation.onException(null, e)) {
3557                     throw new RuntimeException(
3558                             "Unable to get provider " + info.name
3559                             + ": " + e.toString(), e);
3560                 }
3561                 return null;
3562             }
3563         } else if (localLOGV) {
3564             Slog.v(TAG, "Installing external provider " + info.authority + ": "
3565                     + info.name);
3566         }
3567 
3568         synchronized (mProviderMap) {
3569             // Cache the pointer for the remote provider.
3570             String names[] = PATTERN_SEMICOLON.split(info.authority);
3571             for (int i=0; i<names.length; i++) {
3572                 ProviderClientRecord pr = new ProviderClientRecord(names[i], provider,
3573                         localProvider);
3574                 try {
3575                     provider.asBinder().linkToDeath(pr, 0);
3576                     mProviderMap.put(names[i], pr);
3577                 } catch (RemoteException e) {
3578                     return null;
3579                 }
3580             }
3581             if (localProvider != null) {
3582                 mLocalProviders.put(provider.asBinder(),
3583                         new ProviderClientRecord(null, provider, localProvider));
3584             }
3585         }
3586 
3587         return provider;
3588     }
3589 
attach(boolean system)3590     private final void attach(boolean system) {
3591         sThreadLocal.set(this);
3592         mSystemThread = system;
3593         if (!system) {
3594             ViewRoot.addFirstDrawHandler(new Runnable() {
3595                 public void run() {
3596                     ensureJitEnabled();
3597                 }
3598             });
3599             android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
3600             RuntimeInit.setApplicationObject(mAppThread.asBinder());
3601             IActivityManager mgr = ActivityManagerNative.getDefault();
3602             try {
3603                 mgr.attachApplication(mAppThread);
3604             } catch (RemoteException ex) {
3605             }
3606         } else {
3607             // Don't set application object here -- if the system crashes,
3608             // we can't display an alert, we just want to die die die.
3609             android.ddm.DdmHandleAppName.setAppName("system_process");
3610             try {
3611                 mInstrumentation = new Instrumentation();
3612                 ContextImpl context = new ContextImpl();
3613                 context.init(getSystemContext().mPackageInfo, null, this);
3614                 Application app = Instrumentation.newApplication(Application.class, context);
3615                 mAllApplications.add(app);
3616                 mInitialApplication = app;
3617                 app.onCreate();
3618             } catch (Exception e) {
3619                 throw new RuntimeException(
3620                         "Unable to instantiate Application():" + e.toString(), e);
3621             }
3622         }
3623 
3624         ViewRoot.addConfigCallback(new ComponentCallbacks() {
3625             public void onConfigurationChanged(Configuration newConfig) {
3626                 synchronized (mPackages) {
3627                     // We need to apply this change to the resources
3628                     // immediately, because upon returning the view
3629                     // hierarchy will be informed about it.
3630                     if (applyConfigurationToResourcesLocked(newConfig)) {
3631                         // This actually changed the resources!  Tell
3632                         // everyone about it.
3633                         if (mPendingConfiguration == null ||
3634                                 mPendingConfiguration.isOtherSeqNewer(newConfig)) {
3635                             mPendingConfiguration = newConfig;
3636 
3637                             queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
3638                         }
3639                     }
3640                 }
3641             }
3642             public void onLowMemory() {
3643             }
3644         });
3645     }
3646 
detach()3647     private final void detach()
3648     {
3649         sThreadLocal.set(null);
3650     }
3651 
systemMain()3652     public static final ActivityThread systemMain() {
3653         ActivityThread thread = new ActivityThread();
3654         thread.attach(true);
3655         return thread;
3656     }
3657 
installSystemProviders(List providers)3658     public final void installSystemProviders(List providers) {
3659         if (providers != null) {
3660             installContentProviders(mInitialApplication,
3661                                     (List<ProviderInfo>)providers);
3662         }
3663     }
3664 
main(String[] args)3665     public static final void main(String[] args) {
3666         SamplingProfilerIntegration.start();
3667 
3668         Process.setArgV0("<pre-initialized>");
3669 
3670         Looper.prepareMainLooper();
3671         if (sMainThreadHandler == null) {
3672             sMainThreadHandler = new Handler();
3673         }
3674 
3675         ActivityThread thread = new ActivityThread();
3676         thread.attach(false);
3677 
3678         if (false) {
3679             Looper.myLooper().setMessageLogging(new
3680                     LogPrinter(Log.DEBUG, "ActivityThread"));
3681         }
3682 
3683         Looper.loop();
3684 
3685         if (Process.supportsProcesses()) {
3686             throw new RuntimeException("Main thread loop unexpectedly exited");
3687         }
3688 
3689         thread.detach();
3690         String name = (thread.mInitialApplication != null)
3691             ? thread.mInitialApplication.getPackageName()
3692             : "<unknown>";
3693         Slog.i(TAG, "Main thread of " + name + " is now exiting");
3694     }
3695 }
3696