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