zoukankan      html  css  js  c++  java
  • 深入理解android的UI更新机制

    深入理解android的UI更新机制

    由问题开始:

    如何更新android UI?

      可以通过如下方法:

    1. 在主线程里直接操作UI控件。
    2. handler.post(Runnable)
    3. runOnUiThread(Runnable action)
    4. View.post(Runnable)
    5. Handler.sendMessage,在Handler handleMessage()方法里执行。

    大家基本都知道这些方法,那么为什么要这么做?

    我们把几个方法的源码都看一遍吧。

    1. 主线程,这个好像不能说为什么,他就是可以更新,就是这么任性。其实是有原因的。后面说。
    2. handler.post(Runnable)    
      public final boolean post(Runnable r)
      {
         return  sendMessageDelayed(getPostMessage(r), 0);
      }
    3. runOnUiThread(Runnable action)
      public final void runOnUiThread(Runnable action) {
          if (Thread.currentThread() != mUiThread) {
              mHandler.post(action);
          } else {
              action.run();
          }
      }
    4. View.post(Runnable)
      public boolean post(Runnable action) {
          final AttachInfo attachInfo = mAttachInfo;
          if (attachInfo != null) {
              return attachInfo.mHandler.post(action);
          }
      
          // Postpone the runnable until we know on which thread it needs to run.
          // Assume that the runnable will be successfully placed after attach.
          getRunQueue().post(action);
          return true;
      }
    5. Handler.sendMessage,在Handler handleMessage()方法里执行。

    挨个看完源码,你会发现,其实他们最后的实现都是通过Handler来的。

    那现在问题来了,Handler 是什么?怎么工作的?

    大家以上会想到 Handler Looper MessageQueue 

    bala bala 一通。

    Handler Looper MessageQueue 这三个东西是什么,这里不去讲了,工作过程网上也有很多很多,但总感觉80%的人是没有正直搞明白其中原理。

    还是从提问题来说:

        1.UI线程在不断刷新界面,他是怎么做的?是死循环吗?怎么开启的?Activity生命周期是怎么调用的?

        2.Looper是一个消息循环,他是怎么循环的,为什么不阻塞主线程?Looper属于主线程吗?

    先看Looper的源码吧。比较关键。

    /*
     * Copyright (C) 2006 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package android.os;
    
    import android.annotation.NonNull;
    import android.annotation.Nullable;
    import android.os.LooperProto;
    import android.util.Log;
    import android.util.Printer;
    import android.util.Slog;
    import android.util.proto.ProtoOutputStream;
    
    
    public final class Looper {
    
        private static final String TAG = "Looper";
    
        static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
        private static Looper sMainLooper;  // guarded by Looper.class
    
        final MessageQueue mQueue;
        final Thread mThread;
    
        private Printer mLogging;
        private long mTraceTag;
    
        private long mSlowDispatchThresholdMs;
    
       
        public static void prepare() {
            prepare(true);
        }
    
        private static void prepare(boolean quitAllowed) {
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
            sThreadLocal.set(new Looper(quitAllowed));
        }
    
        public static void prepareMainLooper() {
            prepare(false);
            synchronized (Looper.class) {
                if (sMainLooper != null) {
                    throw new IllegalStateException("The main Looper has already been prepared.");
                }
                sMainLooper = myLooper();
            }
        }
    
        /**
         * Returns the application's main looper, which lives in the main thread of the application.
         */
        public static Looper getMainLooper() {
            synchronized (Looper.class) {
                return sMainLooper;
            }
        }
    
        public static void loop() {
            final Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            final MessageQueue queue = me.mQueue;
    
            // Make sure the identity of this thread is that of the local process,
            // and keep track of what that identity token actually is.
            Binder.clearCallingIdentity();
            final long ident = Binder.clearCallingIdentity();
    
            for (;;) {
                Message msg = queue.next(); // might block
                if (msg == null) {
                    // No message indicates that the message queue is quitting.
                    return;
                }
    
                // This must be in a local variable, in case a UI event sets the logger
                final Printer logging = me.mLogging;
                if (logging != null) {
                    logging.println(">>>>> Dispatching to " + msg.target + " " +
                            msg.callback + ": " + msg.what);
                }
    
                final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
    
                final long traceTag = me.mTraceTag;
                if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                    Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
                }
                final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
                final long end;
                try {
                    msg.target.dispatchMessage(msg);
                    end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
                } finally {
                    if (traceTag != 0) {
                        Trace.traceEnd(traceTag);
                    }
                }
                if (slowDispatchThresholdMs > 0) {
                    final long time = end - start;
                    if (time > slowDispatchThresholdMs) {
                        Slog.w(TAG, "Dispatch took " + time + "ms on "
                                + Thread.currentThread().getName() + ", h=" +
                                msg.target + " cb=" + msg.callback + " msg=" + msg.what);
                    }
                }
    
                if (logging != null) {
                    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
                }
    
                // Make sure that during the course of dispatching the
                // identity of the thread wasn't corrupted.
                final long newIdent = Binder.clearCallingIdentity();
                if (ident != newIdent) {
                    Log.wtf(TAG, "Thread identity changed from 0x"
                            + Long.toHexString(ident) + " to 0x"
                            + Long.toHexString(newIdent) + " while dispatching to "
                            + msg.target.getClass().getName() + " "
                            + msg.callback + " what=" + msg.what);
                }
    
                msg.recycleUnchecked();
            }
        }
    
        /**
         * Return the Looper object associated with the current thread.  Returns
         * null if the calling thread is not associated with a Looper.
         */
        public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
        }
    
        /**
         * Return the {@link MessageQueue} object associated with the current
         * thread.  This must be called from a thread running a Looper, or a
         * NullPointerException will be thrown.
         */
        public static @NonNull MessageQueue myQueue() {
            return myLooper().mQueue;
        }
    
        private Looper(boolean quitAllowed) {
            mQueue = new MessageQueue(quitAllowed);
            mThread = Thread.currentThread();
        }
    
        /**
         * Returns true if the current thread is this looper's thread.
         */
        public boolean isCurrentThread() {
            return Thread.currentThread() == mThread;
        }
    
       
        public void setMessageLogging(@Nullable Printer printer) {
            mLogging = printer;
        }
    
        /** {@hide} */
        public void setTraceTag(long traceTag) {
            mTraceTag = traceTag;
        }
    
        /** {@hide} */
        public void setSlowDispatchThresholdMs(long slowDispatchThresholdMs) {
            mSlowDispatchThresholdMs = slowDispatchThresholdMs;
        }
    
    
        public void quit() {
            mQueue.quit(false);
        }
    
    
        public void quitSafely() {
            mQueue.quit(true);
        }
    
        /**
         * Gets the Thread associated with this Looper.
         *
         * @return The looper's thread.
         */
        public @NonNull Thread getThread() {
            return mThread;
        }
    
        /**
         * Gets this looper's message queue.
         *
         * @return The looper's message queue.
         */
        public @NonNull MessageQueue getQueue() {
            return mQueue;
        }
    
        /**
         * Dumps the state of the looper for debugging purposes.
         *
         * @param pw A printer to receive the contents of the dump.
         * @param prefix A prefix to prepend to each line which is printed.
         */
        public void dump(@NonNull Printer pw, @NonNull String prefix) {
            pw.println(prefix + toString());
            mQueue.dump(pw, prefix + "  ", null);
        }
    
        /**
         * Dumps the state of the looper for debugging purposes.
         *
         * @param pw A printer to receive the contents of the dump.
         * @param prefix A prefix to prepend to each line which is printed.
         * @param handler Only dump messages for this Handler.
         * @hide
         */
        public void dump(@NonNull Printer pw, @NonNull String prefix, Handler handler) {
            pw.println(prefix + toString());
            mQueue.dump(pw, prefix + "  ", handler);
        }
    
        /** @hide */
        public void writeToProto(ProtoOutputStream proto, long fieldId) {
            final long looperToken = proto.start(fieldId);
            proto.write(LooperProto.THREAD_NAME, mThread.getName());
            proto.write(LooperProto.THREAD_ID, mThread.getId());
            proto.write(LooperProto.IDENTITY_HASH_CODE, System.identityHashCode(this));
            mQueue.writeToProto(proto, LooperProto.QUEUE);
            proto.end(looperToken);
        }
    
        @Override
        public String toString() {
            return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
                    + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}";
        }
    }

    这个类开头注释给了一个HandlerThread的例子,告诉你怎么用这个Looper .

    同时会发现构造方法是私有的,不能直接调用。

    private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
    }

    分析Looper文章很多;主要内容是:一个线程只能起一个Looper。looper怎么运行起来的。

    来看看loop()方法吧。

    public static void loop() {
            final Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            final MessageQueue queue = me.mQueue;
    
            // Make sure the identity of this thread is that of the local process,
            // and keep track of what that identity token actually is.
            Binder.clearCallingIdentity();
            final long ident = Binder.clearCallingIdentity();
    
            for (;;) {
                Message msg = queue.next(); // might block
                if (msg == null) {
                    // No message indicates that the message queue is quitting.
                    return;
                }
    
                // This must be in a local variable, in case a UI event sets the logger
                final Printer logging = me.mLogging;
                if (logging != null) {
                    logging.println(">>>>> Dispatching to " + msg.target + " " +
                            msg.callback + ": " + msg.what);
                }
    
                final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
    
                final long traceTag = me.mTraceTag;
                if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                    Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
                }
                final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
                final long end;
                try {
                    msg.target.dispatchMessage(msg);
                    end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
                } finally {
                    if (traceTag != 0) {
                        Trace.traceEnd(traceTag);
                    }
                }
                if (slowDispatchThresholdMs > 0) {
                    final long time = end - start;
                    if (time > slowDispatchThresholdMs) {
                        Slog.w(TAG, "Dispatch took " + time + "ms on "
                                + Thread.currentThread().getName() + ", h=" +
                                msg.target + " cb=" + msg.callback + " msg=" + msg.what);
                    }
                }
    
                if (logging != null) {
                    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
                }
    
                // Make sure that during the course of dispatching the
                // identity of the thread wasn't corrupted.
                final long newIdent = Binder.clearCallingIdentity();
                if (ident != newIdent) {
                    Log.wtf(TAG, "Thread identity changed from 0x"
                            + Long.toHexString(ident) + " to 0x"
                            + Long.toHexString(newIdent) + " while dispatching to "
                            + msg.target.getClass().getName() + " "
                            + msg.callback + " what=" + msg.what);
                }
    
                msg.recycleUnchecked();
            }
        }

     最关键的代码如下:

    一个列循环,调用queue.next();msg为空时返回。

    那么我们的消息队列里面,不是永远都有消息的啊?那怎么不退出呢?

    带着这个问题,我们再看看ActivityThread ;

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

     ActivityThread 类 只是一个普通类,没有继承Thread 以是入口方法

     public static void main(String[] args) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
            SamplingProfilerIntegration.start();
    
            // CloseGuard defaults to true and can be quite spammy.  We
            // disable it here, but selectively enable it later (via
            // StrictMode) on debug builds, but using DropBox, not logs.
            CloseGuard.setEnabled(false);
    
            Environment.initForCurrentUser();
    
            // Set the reporter for event logging in libcore
            EventLogger.setReporter(new EventLoggingReporter());
    
            // Make sure TrustedCertificateStore looks in the right place for CA certificates
            final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
            TrustedCertificateStore.setDefaultUserDirectory(configDir);
    
            Process.setArgV0("<pre-initialized>");
    
            Looper.prepareMainLooper();
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
    
            if (false) {
                Looper.myLooper().setMessageLogging(new
                        LogPrinter(Log.DEBUG, "ActivityThread"));
            }
    
            // End of event ActivityThreadMain.
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            Looper.loop();
    
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
     
    通过Looper.prepareMainLooper();起了一个Looper .就是那个静态的mainlooper
    后面调了Looper.loop();

    其实我们怎么找,也没有找到类似while(true)这样的代码来循环主线程。那倒底怎么实现的呢。
    这里涉及到Lunix的知识。Linux pipe/epoll机制
    简单说就是在主线程的MessageQueue没有消息时,便阻塞在loop的queue.next()中的nativePollOnce()方法里,此时主线程会释放CPU资源进入休眠状态,直到下个消息到达或者有事务发生,通过往pipe管道写端写入数据来唤醒主线程工作。这里采用的epoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作,本质同步I/O,即读写是阻塞的

    如果在之前有去研究MessageQueue这个类,其实你会发现是native现实的。

    queue.next()方法执行的时候如果没有消息,它会阻塞。等待消息到来。所以就解释了之前loop方法里那个for循环为什么不会退出。

    篇幅原因不再去研究更多源码了,直接回答上面的疑问。
     
    1.主线程是怎么循环的?
    主线程通过mainLooper来执行动作(其它不是循环)。ActivityThread类中有H类,其实是就是Handler。H类发送各种动作消息,并执行。
    android 系统会16ms发一个UI更新消息,执行对象就是主线程。Activity的生命周期都是依靠主线程的Looper.loop,当收到不同Message时则采用相应措施:

    在H.handleMessage(msg)方法中,根据接收到不同的msg,执行相应的生命周期。

    比如收到msg=H.LAUNCH_ACTIVITY,则调用ActivityThread.handleLaunchActivity()方法,最终会通过反射机制,创建Activity实例,然后再执行Activity.onCreate()等方法;
    再比如收到msg=H.PAUSE_ACTIVITY,则调用ActivityThread.handlePauseActivity()方法,最终会执行Activity.onPause()等方法。

    既然如此,我们在主线程里new 一个Handler .最终用到的是这个静态的mainLooper,如果处理逻辑过于复杂,执行时间过长,事必会影 响主线程的效率。造成UI卡顿。
     
    2.谁去执行的更新?
    主线程里当然是H类的实例。当消息来的时候会调相应的callback 以及handlemssage方法里的代码。H实例是跟mainLooper绑定,mainLooper只和mainThread绑定,所以感觉是ActivityThread在更新UI。
    但其实ActivityThread并没有继承Thread类。它是启动APK后的主程序。
    所以 更新者是:ActivityThread 中 H实例 的callback 以及handlemssage方法在更新。
     
    3.子线程可不可以更新UI?
    网上很多文章会告诉你,通过重新生成一个Looper 。让Handler 在线程中实例化。生成线程Handler.结果。handler也可以现新UI的。
     
    Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                threadhandler = new Handler(Looper.myLooper()) {
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        tvHello = findViewById(R.id.tv_hello);
                        tvHello.setText("thread tv operation");
                    }
                };
                Looper.loop();
            }
        });

    以上代码是可以执行成功的。

    但你仔细分析,这代码跟所谓的主线程一点关系也没有。仅仅是一个线程加Looper而矣,怎么就可以了呢?

    到此得出结论,能更新UI的并不是主线程的专利,android其实是利用的了handler Looper MessageQueue这套Lunux的机制。

    handler Looper MessageQueue关不是专为主线程设计的一套东西。到此我们才能真正理解androidUI的更新机制了。

    验证一下结果。看下图

    当前线程正在操作控件,但并不是主线程。

    在代码中,我打了断点,线程wait了,但程序中的另一个控件progressbar却一直还是在转的。所以通过Looper机制让非UI线程(主线程)去处理一些ui相关代码非常有意义。

    其实H类处理事务,也是通Binder起了线程去处理的。详细的可以深入研究源码。

    这篇文章本来想一点点引导去分析然后得出结果。发现在时间不允许。过程有点乱。表达得不太好。或许不太准确,有问题欢迎留交流。

     
     
     
  • 相关阅读:
    ionic环境搭建
    C# Enum Type
    【IOS】3. OC 类声明和实现
    【IOS】2.基础
    【IOS】1.学前准备
    win8, VS2013 .NET 4.5在哪找svcutil.exe?
    【你吐吧c#每日学习】11.10 C# Data Type conversion
    【你吐吧c#每日学习】10.30 C#Nullable Types
    【你吐吧c#每日学习】10.29 C#字符串类型&Common operators
    给三个int,判断是否可构成三角形算法
  • 原文地址:https://www.cnblogs.com/mamamia/p/8034588.html
Copyright © 2011-2022 走看看