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