blob: 565eaeb632b1d780020cc602fec9a63e46506685 [file] [log] [blame]
/*
* 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.app;
import static android.view.Display.INVALID_DISPLAY;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.Context;
import android.content.IContentProvider;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteDebug.DbStats;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.hardware.display.DisplayManagerGlobal;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.Network;
import android.net.Proxy;
import android.net.ProxyInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.GraphicsEnvironment;
import android.os.Handler;
import android.os.IBinder;
import android.os.LocaleList;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.TransactionTooLargeException;
import android.os.UserHandle;
import android.provider.BlockedNumberContract;
import android.provider.CalendarContract;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.provider.Downloads;
import android.provider.FontsContract;
import android.provider.Settings;
import android.renderscript.RenderScriptCacheDir;
import android.security.NetworkSecurityPolicy;
import android.security.net.config.NetworkSecurityConfigProvider;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.LogPrinter;
import android.util.LogWriter;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.SuperNotCalledException;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewManager;
import android.view.ViewRootImpl;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.webkit.WebView;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
import com.android.org.conscrypt.OpenSSLSocketImpl;
import com.android.org.conscrypt.TrustedCertificateStore;
import dalvik.system.BaseDexClassLoader;
import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;
import libcore.io.DropBox;
import libcore.io.EventLogger;
import libcore.io.IoUtils;
import libcore.net.event.NetworkEventDispatcher;
import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
final class RemoteServiceException extends AndroidRuntimeException {
public RemoteServiceException(String msg) {
super(msg);
}
}
/**
* This manages the execution of the main thread in an
* application process, scheduling and executing activities,
* broadcasts, and other operations on it as the activity
* manager requests.
*
* {@hide}
*/
public final class ActivityThread {
/** @hide */
public static final String TAG = "ActivityThread";
private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
static final boolean localLOGV = false;
static final boolean DEBUG_MESSAGES = false;
/** @hide */
public static final boolean DEBUG_BROADCAST = false;
private static final boolean DEBUG_RESULTS = false;
private static final boolean DEBUG_BACKUP = false;
public static final boolean DEBUG_CONFIGURATION = false;
private static final boolean DEBUG_SERVICE = false;
private static final boolean DEBUG_MEMORY_TRIM = false;
private static final boolean DEBUG_PROVIDER = false;
private static final boolean DEBUG_ORDER = false;
private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
private static final int LOG_AM_ON_PAUSE_CALLED = 30021;
private static final int LOG_AM_ON_RESUME_CALLED = 30022;
private static final int LOG_AM_ON_STOP_CALLED = 30049;
/** Type for IActivityManager.serviceDoneExecuting: anonymous operation */
public static final int SERVICE_DONE_EXECUTING_ANON = 0;
/** Type for IActivityManager.serviceDoneExecuting: done with an onStart call */
public static final int SERVICE_DONE_EXECUTING_START = 1;
/** Type for IActivityManager.serviceDoneExecuting: done stopping (destroying) service */
public static final int SERVICE_DONE_EXECUTING_STOP = 2;
// Details for pausing activity.
private static final int USER_LEAVING = 1;
private static final int DONT_REPORT = 2;
// Whether to invoke an activity callback after delivering new configuration.
private static final boolean REPORT_TO_ACTIVITY = true;
/**
* Denotes an invalid sequence number corresponding to a process state change.
*/
public static final long INVALID_PROC_STATE_SEQ = -1;
private final Object mNetworkPolicyLock = new Object();
/**
* Denotes the sequence number of the process state change for which the main thread needs
* to block until the network rules are updated for it.
*
* Value of {@link #INVALID_PROC_STATE_SEQ} indicates there is no need for blocking.
*/
@GuardedBy("mNetworkPolicyLock")
private long mNetworkBlockSeq = INVALID_PROC_STATE_SEQ;
private ContextImpl mSystemContext;
private ContextImpl mSystemUiContext;
static volatile IPackageManager sPackageManager;
final ApplicationThread mAppThread = new ApplicationThread();
final Looper mLooper = Looper.myLooper();
final H mH = new H();
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
// List of new activities (via ActivityRecord.nextIdle) that should
// be reported when next we idle.
ActivityClientRecord mNewActivities = null;
// Number of activities that are currently visible on-screen.
int mNumVisibleActivities = 0;
ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
private int mLastSessionId;
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
AppBindData mBoundApplication;
Profiler mProfiler;
int mCurDefaultDisplayDpi;
boolean mDensityCompatMode;
Configuration mConfiguration;
Configuration mCompatConfiguration;
Application mInitialApplication;
final ArrayList<Application> mAllApplications
= new ArrayList<Application>();
// set of instantiated backup agents, keyed by package name
final ArrayMap<String, BackupAgent> mBackupAgents = new ArrayMap<String, BackupAgent>();
/** Reference to singleton {@link ActivityThread} */
private static volatile ActivityThread sCurrentActivityThread;
Instrumentation mInstrumentation;
String mInstrumentationPackageName = null;
String mInstrumentationAppDir = null;
String[] mInstrumentationSplitAppDirs = null;
String mInstrumentationLibDir = null;
String mInstrumentedAppDir = null;
String[] mInstrumentedSplitAppDirs = null;
String mInstrumentedLibDir = null;
boolean mSystemThread = false;
boolean mJitEnabled = false;
boolean mSomeActivitiesChanged = false;
boolean mUpdatingSystemConfig = false;
/* package */ boolean mHiddenApiWarningShown = false;
// These can be accessed by multiple threads; mResourcesManager is the lock.
// XXX For now we keep around information about all packages we have
// seen, not removing entries from this map.
// NOTE: The activity and window managers need to call in to
// ActivityThread to do things like update resource configurations,
// which means this lock gets held while the activity and window managers
// holds their own lock. Thus you MUST NEVER call back into the activity manager
// or window manager or anything that depends on them while holding this lock.
// These LoadedApk are only valid for the userId that we're running as.
@GuardedBy("mResourcesManager")
final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<>();
@GuardedBy("mResourcesManager")
final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<>();
@GuardedBy("mResourcesManager")
final ArrayList<ActivityClientRecord> mRelaunchingActivities = new ArrayList<>();
@GuardedBy("mResourcesManager")
Configuration mPendingConfiguration = null;
// Because we merge activity relaunch operations we can't depend on the ordering provided by
// the handler messages. We need to introduce secondary ordering mechanism, which will allow
// us to drop certain events, if we know that they happened before relaunch we already executed.
// This represents the order of receiving the request from AM.
@GuardedBy("mResourcesManager")
int mLifecycleSeq = 0;
private final ResourcesManager mResourcesManager;
private static final class ProviderKey {
final String authority;
final int userId;
public ProviderKey(String authority, int userId) {
this.authority = authority;
this.userId = userId;
}
@Override
public boolean equals(Object o) {
if (o instanceof ProviderKey) {
final ProviderKey other = (ProviderKey) o;
return Objects.equals(authority, other.authority) && userId == other.userId;
}
return false;
}
@Override
public int hashCode() {
return ((authority != null) ? authority.hashCode() : 0) ^ userId;
}
}
// The lock of mProviderMap protects the following variables.
final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
= new ArrayMap<ProviderKey, ProviderClientRecord>();
final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap
= new ArrayMap<IBinder, ProviderRefCount>();
final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders
= new ArrayMap<IBinder, ProviderClientRecord>();
final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName
= new ArrayMap<ComponentName, ProviderClientRecord>();
final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
= new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
final GcIdler mGcIdler = new GcIdler();
boolean mGcIdlerScheduled = false;
static volatile Handler sMainThreadHandler; // set once in main()
Bundle mCoreSettings = null;
static final class ActivityClientRecord {
IBinder token;
int ident;
Intent intent;
String referrer;
IVoiceInteractor voiceInteractor;
Bundle state;
PersistableBundle persistentState;
Activity activity;
Window window;
Activity parent;
String embeddedID;
Activity.NonConfigurationInstances lastNonConfigurationInstances;
boolean paused;
boolean stopped;
boolean hideForNow;
Configuration newConfig;
Configuration createdConfig;
Configuration overrideConfig;
// Used for consolidating configs before sending on to Activity.
private Configuration tmpConfig = new Configuration();
// Callback used for updating activity override config.
ViewRootImpl.ActivityConfigCallback configCallback;
ActivityClientRecord nextIdle;
ProfilerInfo profilerInfo;
ActivityInfo activityInfo;
CompatibilityInfo compatInfo;
LoadedApk loadedApk;
List<ResultInfo> pendingResults;
List<ReferrerIntent> pendingIntents;
boolean startsNotResumed;
boolean isForward;
int pendingConfigChanges;
boolean onlyLocalRequest;
Window mPendingRemoveWindow;
WindowManager mPendingRemoveWindowManager;
boolean mPreserveWindow;
// Set for relaunch requests, indicates the order number of the relaunch operation, so it
// can be compared with other lifecycle operations.
int relaunchSeq = 0;
// Can only be accessed from the UI thread. This represents the latest processed message
// that is related to lifecycle events/
int lastProcessedSeq = 0;
ActivityClientRecord() {
parent = null;
embeddedID = null;
paused = false;
stopped = false;
hideForNow = false;
nextIdle = null;
configCallback = (Configuration overrideConfig, int newDisplayId) -> {
if (activity == null) {
throw new IllegalStateException(
"Received config update for non-existing activity");
}
activity.mMainThread.handleActivityConfigurationChanged(
new ActivityConfigChangeData(token, overrideConfig), newDisplayId);
};
}
public boolean isPreHoneycomb() {
if (activity != null) {
return activity.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.HONEYCOMB;
}
return false;
}
public boolean isPersistable() {
return activityInfo.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS;
}
public String toString() {
ComponentName componentName = intent != null ? intent.getComponent() : null;
return "ActivityRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " token=" + token + " " + (componentName == null
? "no component name" : componentName.toShortString())
+ "}";
}
public String getStateString() {
StringBuilder sb = new StringBuilder();
sb.append("ActivityClientRecord{");
sb.append("paused=").append(paused);
sb.append(", stopped=").append(stopped);
sb.append(", hideForNow=").append(hideForNow);
sb.append(", startsNotResumed=").append(startsNotResumed);
sb.append(", isForward=").append(isForward);
sb.append(", pendingConfigChanges=").append(pendingConfigChanges);
sb.append(", onlyLocalRequest=").append(onlyLocalRequest);
sb.append(", preserveWindow=").append(mPreserveWindow);
if (activity != null) {
sb.append(", Activity{");
sb.append("resumed=").append(activity.mResumed);
sb.append(", stopped=").append(activity.mStopped);
sb.append(", finished=").append(activity.isFinishing());
sb.append(", destroyed=").append(activity.isDestroyed());
sb.append(", startedActivity=").append(activity.mStartedActivity);
sb.append(", temporaryPause=").append(activity.mTemporaryPause);
sb.append(", changingConfigurations=").append(activity.mChangingConfigurations);
sb.append("}");
}
sb.append("}");
return sb.toString();
}
}
final class ProviderClientRecord {
final String[] mNames;
final IContentProvider mProvider;
final ContentProvider mLocalProvider;
final ContentProviderHolder mHolder;
ProviderClientRecord(String[] names, IContentProvider provider,
ContentProvider localProvider, ContentProviderHolder holder) {
mNames = names;
mProvider = provider;
mLocalProvider = localProvider;
mHolder = holder;
}
}
static final class NewIntentData {
List<ReferrerIntent> intents;
IBinder token;
boolean andPause;
public String toString() {
return "NewIntentData{intents=" + intents + " token=" + token
+ " andPause=" + andPause +"}";
}
}
static final class ReceiverData extends BroadcastReceiver.PendingResult {
public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
boolean ordered, boolean sticky, IBinder token, int sendingUser) {
super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,
token, sendingUser, intent.getFlags());
this.intent = intent;
}
Intent intent;
ActivityInfo info;
CompatibilityInfo compatInfo;
public String toString() {
return "ReceiverData{intent=" + intent + " packageName=" +
info.packageName + " resultCode=" + getResultCode()
+ " resultData=" + getResultData() + " resultExtras="
+ getResultExtras(false) + "}";
}
}
static final class CreateBackupAgentData {
ApplicationInfo appInfo;
CompatibilityInfo compatInfo;
int backupMode;
public String toString() {
return "CreateBackupAgentData{appInfo=" + appInfo
+ " backupAgent=" + appInfo.backupAgentName
+ " mode=" + backupMode + "}";
}
}
static final class CreateServiceData {
IBinder token;
ServiceInfo info;
CompatibilityInfo compatInfo;
Intent intent;
public String toString() {
return "CreateServiceData{token=" + token + " className="
+ info.name + " packageName=" + info.packageName
+ " intent=" + intent + "}";
}
}
static final class BindServiceData {
IBinder token;
Intent intent;
boolean rebind;
public String toString() {
return "BindServiceData{token=" + token + " intent=" + intent + "}";
}
}
static final class ServiceArgsData {
IBinder token;
boolean taskRemoved;
int startId;
int flags;
Intent args;
public String toString() {
return "ServiceArgsData{token=" + token + " startId=" + startId
+ " args=" + args + "}";
}
}
static final class AppBindData {
LoadedApk loadedApk;
String processName;
ApplicationInfo appInfo;
List<ProviderInfo> providers;
ComponentName instrumentationName;
Bundle instrumentationArgs;
IInstrumentationWatcher instrumentationWatcher;
IUiAutomationConnection instrumentationUiAutomationConnection;
int debugMode;
boolean enableBinderTracking;
boolean trackAllocation;
boolean restrictedBackupMode;
boolean persistent;
Configuration config;
CompatibilityInfo compatInfo;
String buildSerial;
/** Initial values for {@link Profiler}. */
ProfilerInfo initProfilerInfo;
public String toString() {
return "AppBindData{appInfo=" + appInfo + "}";
}
}
static final class Profiler {
String profileFile;
ParcelFileDescriptor profileFd;
int samplingInterval;
boolean autoStopProfiler;
boolean streamingOutput;
boolean profiling;
boolean handlingProfiling;
public void setProfiler(ProfilerInfo profilerInfo) {
ParcelFileDescriptor fd = profilerInfo.profileFd;
if (profiling) {
if (fd != null) {
try {
fd.close();
} catch (IOException e) {
// Ignore
}
}
return;
}
if (profileFd != null) {
try {
profileFd.close();
} catch (IOException e) {
// Ignore
}
}
profileFile = profilerInfo.profileFile;
profileFd = fd;
samplingInterval = profilerInfo.samplingInterval;
autoStopProfiler = profilerInfo.autoStopProfiler;
streamingOutput = profilerInfo.streamingOutput;
}
public void startProfiling() {
if (profileFd == null || profiling) {
return;
}
try {
int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8);
VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval,
streamingOutput);
profiling = true;
} catch (RuntimeException e) {
Slog.w(TAG, "Profiling failed on path " + profileFile);
try {
profileFd.close();
profileFd = null;
} catch (IOException e2) {
Slog.w(TAG, "Failure closing profile fd", e2);
}
}
}
public void stopProfiling() {
if (profiling) {
profiling = false;
Debug.stopMethodTracing();
if (profileFd != null) {
try {
profileFd.close();
} catch (IOException e) {
}
}
profileFd = null;
profileFile = null;
}
}
}
static final class DumpComponentInfo {
ParcelFileDescriptor fd;
IBinder token;
String prefix;
String[] args;
}
static final class ResultData {
IBinder token;
List<ResultInfo> results;
public String toString() {
return "ResultData{token=" + token + " results" + results + "}";
}
}
static final class ContextCleanupInfo {
ContextImpl context;
String what;
String who;
}
static final class DumpHeapData {
public boolean managed;
public boolean mallocInfo;
public boolean runGc;
String path;
ParcelFileDescriptor fd;
}
static final class UpdateCompatibilityData {
String pkg;
CompatibilityInfo info;
}
static final class RequestAssistContextExtras {
IBinder activityToken;
IBinder requestToken;
int requestType;
int sessionId;
int flags;
}
static final class ActivityConfigChangeData {
final IBinder activityToken;
final Configuration overrideConfig;
public ActivityConfigChangeData(IBinder token, Configuration config) {
activityToken = token;
overrideConfig = config;
}
}
private class ApplicationThread extends IApplicationThread.Stub {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
private int mLastProcessState = -1;
private void updatePendingConfiguration(Configuration config) {
synchronized (mResourcesManager) {
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(config)) {
mPendingConfiguration = config;
}
}
}
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
int seq = getLifecycleSeq();
if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
+ " operation received seq: " + seq);
sendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
configChanges,
seq);
}
public final void scheduleStopActivity(IBinder token, boolean showWindow,
int configChanges) {
int seq = getLifecycleSeq();
if (DEBUG_ORDER) Slog.d(TAG, "stopActivity " + ActivityThread.this
+ " operation received seq: " + seq);
sendMessage(
showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
token, 0, configChanges, seq);
}
public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
sendMessage(
showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
token);
}
public final void scheduleSleeping(IBinder token, boolean sleeping) {
sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
}
public final void scheduleResumeActivity(IBinder token, int processState,
boolean isForward, Bundle resumeArgs) {
int seq = getLifecycleSeq();
if (DEBUG_ORDER) Slog.d(TAG, "resumeActivity " + ActivityThread.this
+ " operation received seq: " + seq);
updateProcessState(processState, false);
sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0, 0, seq);
}
public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
ResultData res = new ResultData();
res.token = token;
res.results = results;
sendMessage(H.SEND_RESULT, res);
}
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
@Override
public final void scheduleRelaunchActivity(IBinder token,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
int configChanges, boolean notResumed, Configuration config,
Configuration overrideConfig, boolean preserveWindow) {
requestRelaunchActivity(token, pendingResults, pendingNewIntents,
configChanges, notResumed, config, overrideConfig, true, preserveWindow);
}
public final void scheduleNewIntent(
List<ReferrerIntent> intents, IBinder token, boolean andPause) {
NewIntentData data = new NewIntentData();
data.intents = intents;
data.token = token;
data.andPause = andPause;
sendMessage(H.NEW_INTENT, data);
}
public final void scheduleDestroyActivity(IBinder token, boolean finishing,
int configChanges) {
sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
configChanges);
}
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
updateProcessState(processState, false);
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
r.info = info;
r.compatInfo = compatInfo;
sendMessage(H.RECEIVER, r);
}
public final void scheduleCreateBackupAgent(ApplicationInfo app,
CompatibilityInfo compatInfo, int backupMode) {
CreateBackupAgentData d = new CreateBackupAgentData();
d.appInfo = app;
d.compatInfo = compatInfo;
d.backupMode = backupMode;
sendMessage(H.CREATE_BACKUP_AGENT, d);
}
public final void scheduleDestroyBackupAgent(ApplicationInfo app,
CompatibilityInfo compatInfo) {
CreateBackupAgentData d = new CreateBackupAgentData();
d.appInfo = app;
d.compatInfo = compatInfo;
sendMessage(H.DESTROY_BACKUP_AGENT, d);
}
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
if (DEBUG_SERVICE)
Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
sendMessage(H.BIND_SERVICE, s);
}
public final void scheduleUnbindService(IBinder token, Intent intent) {
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
sendMessage(H.UNBIND_SERVICE, s);
}
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
List<ServiceStartArgs> list = args.getList();
for (int i = 0; i < list.size(); i++) {
ServiceStartArgs ssa = list.get(i);
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = ssa.taskRemoved;
s.startId = ssa.startId;
s.flags = ssa.flags;
s.args = ssa.args;
sendMessage(H.SERVICE_ARGS, s);
}
}
public final void scheduleStopService(IBinder token) {
sendMessage(H.STOP_SERVICE, token);
}
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
sendMessage(H.BIND_APPLICATION, data);
}
public final void scheduleExit() {
sendMessage(H.EXIT_APPLICATION, null);
}
public final void scheduleSuicide() {
sendMessage(H.SUICIDE, null);
}
public void scheduleConfigurationChanged(Configuration config) {
updatePendingConfiguration(config);
sendMessage(H.CONFIGURATION_CHANGED, config);
}
public void scheduleApplicationInfoChanged(ApplicationInfo ai) {
sendMessage(H.APPLICATION_INFO_CHANGED, ai);
}
public void updateTimeZone() {
TimeZone.setDefault(null);
}
public void clearDnsCache() {
// a non-standard API to get this to libcore
InetAddress.clearDnsCache();
// Allow libcore to perform the necessary actions as it sees fit upon a network
// configuration change.
NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged();
}
public void setHttpProxy(String host, String port, String exclList, Uri pacFileUrl) {
final ConnectivityManager cm = ConnectivityManager.from(getSystemContext());
final Network network = cm.getBoundNetworkForProcess();
if (network != null) {
Proxy.setHttpProxySystemProperty(cm.getDefaultProxy());
} else {
Proxy.setHttpProxySystemProperty(host, port, exclList, pacFileUrl);
}
}
public void processInBackground() {
mH.removeMessages(H.GC_WHEN_IDLE);
mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
}
public void dumpService(ParcelFileDescriptor pfd, IBinder servicetoken, String[] args) {
DumpComponentInfo data = new DumpComponentInfo();
try {
data.fd = pfd.dup();
data.token = servicetoken;
data.args = args;
sendMessage(H.DUMP_SERVICE, data, 0, 0, true /*async*/);
} catch (IOException e) {
Slog.w(TAG, "dumpService failed", e);
} finally {
IoUtils.closeQuietly(pfd);
}
}
// This function exists to make sure all receiver dispatching is
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
@Override
public void scheduleLowMemory() {
sendMessage(H.LOW_MEMORY, null);
}
@Override
public void scheduleActivityConfigurationChanged(
IBinder token, Configuration overrideConfig) {
sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED,
new ActivityConfigChangeData(token, overrideConfig));
}
@Override
public void scheduleActivityMovedToDisplay(IBinder token, int displayId,
Configuration overrideConfig) {
sendMessage(H.ACTIVITY_MOVED_TO_DISPLAY,
new ActivityConfigChangeData(token, overrideConfig), displayId);
}
@Override
public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
sendMessage(H.PROFILER_CONTROL, profilerInfo, start ? 1 : 0, profileType);
}
@Override
public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String path,
ParcelFileDescriptor fd) {
DumpHeapData dhd = new DumpHeapData();
dhd.managed = managed;
dhd.mallocInfo = mallocInfo;
dhd.runGc = runGc;
dhd.path = path;
dhd.fd = fd;
sendMessage(H.DUMP_HEAP, dhd, 0, 0, true /*async*/);
}
public void attachAgent(String agent) {
sendMessage(H.ATTACH_AGENT, agent);
}
public void setSchedulingGroup(int group) {
// Note: do this immediately, since going into the foreground
// should happen regardless of what pending work we have to do
// and the activity manager will wait for us to report back that
// we are done before sending us to the background.
try {
Process.setProcessGroup(Process.myPid(), group);
} catch (Exception e) {
Slog.w(TAG, "Failed setting process group to " + group, e);
}
}
public void dispatchPackageBroadcast(int cmd, String[] packages) {
sendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
}
public void scheduleCrash(String msg) {
sendMessage(H.SCHEDULE_CRASH, msg);
}
public void dumpActivity(ParcelFileDescriptor pfd, IBinder activitytoken,
String prefix, String[] args) {
DumpComponentInfo data = new DumpComponentInfo();
try {
data.fd = pfd.dup();
data.token = activitytoken;
data.prefix = prefix;
data.args = args;
sendMessage(H.DUMP_ACTIVITY, data, 0, 0, true /*async*/);
} catch (IOException e) {
Slog.w(TAG, "dumpActivity failed", e);
} finally {
IoUtils.closeQuietly(pfd);
}
}
public void dumpProvider(ParcelFileDescriptor pfd, IBinder providertoken,
String[] args) {
DumpComponentInfo data = new DumpComponentInfo();
try {
data.fd = pfd.dup();
data.token = providertoken;
data.args = args;
sendMessage(H.DUMP_PROVIDER, data, 0, 0, true /*async*/);
} catch (IOException e) {
Slog.w(TAG, "dumpProvider failed", e);
} finally {
IoUtils.closeQuietly(pfd);
}
}
@Override
public void dumpMemInfo(ParcelFileDescriptor pfd, Debug.MemoryInfo mem, boolean checkin,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
boolean dumpUnreachable, String[] args) {
FileOutputStream fout = new FileOutputStream(pfd.getFileDescriptor());
PrintWriter pw = new FastPrintWriter(fout);
try {
dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
} finally {
pw.flush();
IoUtils.closeQuietly(pfd);
}
}
private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
long nativeMax = Debug.getNativeHeapSize() / 1024;
long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
Runtime runtime = Runtime.getRuntime();
runtime.gc(); // Do GC since countInstancesOfClass counts unreachable objects.
long dalvikMax = runtime.totalMemory() / 1024;
long dalvikFree = runtime.freeMemory() / 1024;
long dalvikAllocated = dalvikMax - dalvikFree;
Class[] classesToCount = new Class[] {
ContextImpl.class,
Activity.class,
WebView.class,
OpenSSLSocketImpl.class
};
long[] instanceCounts = VMDebug.countInstancesOfClasses(classesToCount, true);
long appContextInstanceCount = instanceCounts[0];
long activityInstanceCount = instanceCounts[1];
long webviewInstanceCount = instanceCounts[2];
long openSslSocketCount = instanceCounts[3];
long viewInstanceCount = ViewDebug.getViewInstanceCount();
long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
int globalAssetCount = AssetManager.getGlobalAssetCount();
int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
long parcelSize = Parcel.getGlobalAllocSize();
long parcelCount = Parcel.getGlobalAllocCount();
SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly,
Process.myPid(),
(mBoundApplication != null) ? mBoundApplication.processName : "unknown",
nativeMax, nativeAllocated, nativeFree,
dalvikMax, dalvikAllocated, dalvikFree);
if (checkin) {
// NOTE: if you change anything significant below, also consider changing
// ACTIVITY_THREAD_CHECKIN_VERSION.
// Object counts
pw.print(viewInstanceCount); pw.print(',');
pw.print(viewRootInstanceCount); pw.print(',');
pw.print(appContextInstanceCount); pw.print(',');
pw.print(activityInstanceCount); pw.print(',');
pw.print(globalAssetCount); pw.print(',');
pw.print(globalAssetManagerCount); pw.print(',');
pw.print(binderLocalObjectCount); pw.print(',');
pw.print(binderProxyObjectCount); pw.print(',');
pw.print(binderDeathObjectCount); pw.print(',');
pw.print(openSslSocketCount); pw.print(',');
// SQL
pw.print(stats.memoryUsed / 1024); pw.print(',');
pw.print(stats.memoryUsed / 1024); pw.print(',');
pw.print(stats.pageCacheOverflow / 1024); pw.print(',');
pw.print(stats.largestMemAlloc / 1024);
for (int i = 0; i < stats.dbStats.size(); i++) {
DbStats dbStats = stats.dbStats.get(i);
pw.print(','); pw.print(dbStats.dbName);
pw.print(','); pw.print(dbStats.pageSize);
pw.print(','); pw.print(dbStats.dbSize);
pw.print(','); pw.print(dbStats.lookaside);
pw.print(','); pw.print(dbStats.cache);
pw.print(','); pw.print(dbStats.cache);
}
pw.println();
return;
}
pw.println(" ");
pw.println(" Objects");
printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:",
viewRootInstanceCount);
printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
"Activities:", activityInstanceCount);
printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
"AssetManagers:", globalAssetManagerCount);
printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
"Proxy Binders:", binderProxyObjectCount);
printRow(pw, TWO_COUNT_COLUMNS, "Parcel memory:", parcelSize/1024,
"Parcel count:", parcelCount);
printRow(pw, TWO_COUNT_COLUMNS, "Death Recipients:", binderDeathObjectCount,
"OpenSSL Sockets:", openSslSocketCount);
printRow(pw, ONE_COUNT_COLUMN, "WebViews:", webviewInstanceCount);
// SQLite mem info
pw.println(" ");
pw.println(" SQL");
printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024);
printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:",
stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
pw.println(" ");
int N = stats.dbStats.size();
if (N > 0) {
pw.println(" DATABASES");
printRow(pw, " %8s %8s %14s %14s %s", "pgsz", "dbsz", "Lookaside(b)", "cache",
"Dbname");
for (int i = 0; i < N; i++) {
DbStats dbStats = stats.dbStats.get(i);
printRow(pw, DB_INFO_FORMAT,
(dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
(dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
(dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
dbStats.cache, dbStats.dbName);
}
}
// Asset details.
String assetAlloc = AssetManager.getAssetAllocations();
if (assetAlloc != null) {
pw.println(" ");
pw.println(" Asset Allocations");
pw.print(assetAlloc);
}
// Unreachable native memory
if (dumpUnreachable) {
boolean showContents = ((mBoundApplication != null)
&& ((mBoundApplication.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0))
|| android.os.Build.IS_DEBUGGABLE;
pw.println(" ");
pw.println(" Unreachable memory");
pw.print(Debug.getUnreachableMemory(100, showContents));
}
}
@Override
public void dumpGfxInfo(ParcelFileDescriptor pfd, String[] args) {
nDumpGraphicsInfo(pfd.getFileDescriptor());
WindowManagerGlobal.getInstance().dumpGfxInfo(pfd.getFileDescriptor(), args);
IoUtils.closeQuietly(pfd);
}
private void dumpDatabaseInfo(ParcelFileDescriptor pfd, String[] args) {
PrintWriter pw = new FastPrintWriter(
new FileOutputStream(pfd.getFileDescriptor()));
PrintWriterPrinter printer = new PrintWriterPrinter(pw);
SQLiteDebug.dump(printer, args);
pw.flush();
}
@Override
public void dumpDbInfo(final ParcelFileDescriptor pfd, final String[] args) {
if (mSystemThread) {
// Ensure this invocation is asynchronous to prevent writer waiting if buffer cannot
// be consumed. But it must duplicate the file descriptor first, since caller might
// be closing it.
final ParcelFileDescriptor dup;
try {
dup = pfd.dup();
} catch (IOException e) {
Log.w(TAG, "Could not dup FD " + pfd.getFileDescriptor().getInt$());
return;
} finally {
IoUtils.closeQuietly(pfd);
}
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
try {
dumpDatabaseInfo(dup, args);
} finally {
IoUtils.closeQuietly(dup);
}
}
});
} else {
dumpDatabaseInfo(pfd, args);
IoUtils.closeQuietly(pfd);
}
}
@Override
public void unstableProviderDied(IBinder provider) {
sendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
}
@Override
public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
int requestType, int sessionId, int flags) {
RequestAssistContextExtras cmd = new RequestAssistContextExtras();
cmd.activityToken = activityToken;
cmd.requestToken = requestToken;
cmd.requestType = requestType;
cmd.sessionId = sessionId;
cmd.flags = flags;
sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
}
public void setCoreSettings(Bundle coreSettings) {
sendMessage(H.SET_CORE_SETTINGS, coreSettings);
}
public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) {
UpdateCompatibilityData ucd = new UpdateCompatibilityData();
ucd.pkg = pkg;
ucd.info = info;
sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
}
public void scheduleTrimMemory(int level) {
sendMessage(H.TRIM_MEMORY, null, level);
}
public void scheduleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
sendMessage(H.TRANSLUCENT_CONVERSION_COMPLETE, token, drawComplete ? 1 : 0);
}
public void scheduleOnNewActivityOptions(IBinder token, Bundle options) {
sendMessage(H.ON_NEW_ACTIVITY_OPTIONS,
new Pair<IBinder, ActivityOptions>(token, ActivityOptions.fromBundle(options)));
}
public void setProcessState(int state) {
updateProcessState(state, true);
}
public void updateProcessState(int processState, boolean fromIpc) {
synchronized (this) {
if (mLastProcessState != processState) {
mLastProcessState = processState;
// Update Dalvik state based on ActivityManager.PROCESS_STATE_* constants.
final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
int dalvikProcessState = DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE;
// TODO: Tune this since things like gmail sync are important background but not jank perceptible.
if (processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
dalvikProcessState = DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE;
}
VMRuntime.getRuntime().updateProcessState(dalvikProcessState);
if (false) {
Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
+ (fromIpc ? " (from ipc": ""));
}
}
}
}
/**
* Updates {@link #mNetworkBlockSeq}. This is used by ActivityManagerService to inform
* the main thread that it needs to wait for the network rules to get updated before
* launching an activity.
*/
@Override
public void setNetworkBlockSeq(long procStateSeq) {
synchronized (mNetworkPolicyLock) {
mNetworkBlockSeq = procStateSeq;
}
}
@Override
public void scheduleInstallProvider(ProviderInfo provider) {
sendMessage(H.INSTALL_PROVIDER, provider);
}
@Override
public final void updateTimePrefs(int timeFormatPreference) {
final Boolean timeFormatPreferenceBool;
// For convenience we are using the Intent extra values.
if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR) {
timeFormatPreferenceBool = Boolean.FALSE;
} else if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_24_HOUR) {
timeFormatPreferenceBool = Boolean.TRUE;
} else {
// timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT
// (or unknown).
timeFormatPreferenceBool = null;
}
DateFormat.set24HourTimePref(timeFormatPreferenceBool);
}
@Override
public void scheduleEnterAnimationComplete(IBinder token) {
sendMessage(H.ENTER_ANIMATION_COMPLETE, token);
}
@Override
public void notifyCleartextNetwork(byte[] firstPacket) {
if (StrictMode.vmCleartextNetworkEnabled()) {
StrictMode.onCleartextNetworkDetected(firstPacket);
}
}
@Override
public void startBinderTracking() {
sendMessage(H.START_BINDER_TRACKING, null);
}
@Override
public void stopBinderTrackingAndDump(ParcelFileDescriptor pfd) {
try {
sendMessage(H.STOP_BINDER_TRACKING_AND_DUMP, pfd.dup());
} catch (IOException e) {
} finally {
IoUtils.closeQuietly(pfd);
}
}
@Override
public void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
Configuration overrideConfig) throws RemoteException {
SomeArgs args = SomeArgs.obtain();
args.arg1 = token;
args.arg2 = overrideConfig;
args.argi1 = isInMultiWindowMode ? 1 : 0;
sendMessage(H.MULTI_WINDOW_MODE_CHANGED, args);
}
@Override
public void schedulePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
Configuration overrideConfig) throws RemoteException {
SomeArgs args = SomeArgs.obtain();
args.arg1 = token;
args.arg2 = overrideConfig;
args.argi1 = isInPipMode ? 1 : 0;
sendMessage(H.PICTURE_IN_PICTURE_MODE_CHANGED, args);
}
@Override
public void scheduleLocalVoiceInteractionStarted(IBinder token,
IVoiceInteractor voiceInteractor) throws RemoteException {
SomeArgs args = SomeArgs.obtain();
args.arg1 = token;
args.arg2 = voiceInteractor;
sendMessage(H.LOCAL_VOICE_INTERACTION_STARTED, args);
}
@Override
public void handleTrustStorageUpdate() {
NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate();
}
}
private int getLifecycleSeq() {
synchronized (mResourcesManager) {
return mLifecycleSeq++;
}
}
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int NEW_INTENT = 112;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
public static final int CONFIGURATION_CHANGED = 118;
public static final int CLEAN_UP_CONTEXT = 119;
public static final int GC_WHEN_IDLE = 120;
public static final int BIND_SERVICE = 121;
public static final int UNBIND_SERVICE = 122;
public static final int DUMP_SERVICE = 123;
public static final int LOW_MEMORY = 124;
public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
public static final int RELAUNCH_ACTIVITY = 126;
public static final int PROFILER_CONTROL = 127;
public static final int CREATE_BACKUP_AGENT = 128;
public static final int DESTROY_BACKUP_AGENT = 129;
public static final int SUICIDE = 130;
public static final int REMOVE_PROVIDER = 131;
public static final int ENABLE_JIT = 132;
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
public static final int SCHEDULE_CRASH = 134;
public static final int DUMP_HEAP = 135;
public static final int DUMP_ACTIVITY = 136;
public static final int SLEEPING = 137;
public static final int SET_CORE_SETTINGS = 138;
public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
public static final int TRIM_MEMORY = 140;
public static final int DUMP_PROVIDER = 141;
public static final int UNSTABLE_PROVIDER_DIED = 142;
public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
public static final int INSTALL_PROVIDER = 145;
public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
public static final int ENTER_ANIMATION_COMPLETE = 149;
public static final int START_BINDER_TRACKING = 150;
public static final int STOP_BINDER_TRACKING_AND_DUMP = 151;
public static final int MULTI_WINDOW_MODE_CHANGED = 152;
public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153;
public static final int LOCAL_VOICE_INTERACTION_STARTED = 154;
public static final int ATTACH_AGENT = 155;
public static final int APPLICATION_INFO_CHANGED = 156;
public static final int ACTIVITY_MOVED_TO_DISPLAY = 157;
String codeToString(int code) {
if (DEBUG_MESSAGES) {
switch (code) {
case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
case SHOW_WINDOW: return "SHOW_WINDOW";
case HIDE_WINDOW: return "HIDE_WINDOW";
case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
case SEND_RESULT: return "SEND_RESULT";
case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
case BIND_APPLICATION: return "BIND_APPLICATION";
case EXIT_APPLICATION: return "EXIT_APPLICATION";
case NEW_INTENT: return "NEW_INTENT";
case RECEIVER: return "RECEIVER";
case CREATE_SERVICE: return "CREATE_SERVICE";
case SERVICE_ARGS: return "SERVICE_ARGS";
case STOP_SERVICE: return "STOP_SERVICE";
case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
case BIND_SERVICE: return "BIND_SERVICE";
case UNBIND_SERVICE: return "UNBIND_SERVICE";
case DUMP_SERVICE: return "DUMP_SERVICE";
case LOW_MEMORY: return "LOW_MEMORY";
case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
case ACTIVITY_MOVED_TO_DISPLAY: return "ACTIVITY_MOVED_TO_DISPLAY";
case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
case PROFILER_CONTROL: return "PROFILER_CONTROL";
case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
case SUICIDE: return "SUICIDE";
case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
case ENABLE_JIT: return "ENABLE_JIT";
case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
case DUMP_HEAP: return "DUMP_HEAP";
case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
case SLEEPING: return "SLEEPING";
case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
case TRIM_MEMORY: return "TRIM_MEMORY";
case DUMP_PROVIDER: return "DUMP_PROVIDER";
case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS";
case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE";
case INSTALL_PROVIDER: return "INSTALL_PROVIDER";
case ON_NEW_ACTIVITY_OPTIONS: return "ON_NEW_ACTIVITY_OPTIONS";
case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE";
case MULTI_WINDOW_MODE_CHANGED: return "MULTI_WINDOW_MODE_CHANGED";
case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED";
case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED";
case ATTACH_AGENT: return "ATTACH_AGENT";
case APPLICATION_INFO_CHANGED: return "APPLICATION_INFO_CHANGED";
}
}
return Integer.toString(code);
}
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.loadedApk = getLoadedApkNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
SomeArgs args = (SomeArgs) msg.obj;
handlePauseActivity((IBinder) args.arg1, false,
(args.argi1 & USER_LEAVING) != 0, args.argi2,
(args.argi1 & DONT_REPORT) != 0, args.argi3);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY_FINISHING: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
SomeArgs args = (SomeArgs) msg.obj;
handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0,
args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case STOP_ACTIVITY_SHOW: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
SomeArgs args = (SomeArgs) msg.obj;
handleStopActivity((IBinder) args.arg1, true, args.argi2, args.argi3);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case STOP_ACTIVITY_HIDE: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
SomeArgs args = (SomeArgs) msg.obj;
handleStopActivity((IBinder) args.arg1, false, args.argi2, args.argi3);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case SHOW_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
handleWindowVisibility((IBinder)msg.obj, true);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case HIDE_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
handleWindowVisibility((IBinder)msg.obj, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RESUME_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
SomeArgs args = (SomeArgs) msg.obj;
handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true,
args.argi3, "RESUME_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SEND_RESULT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
handleSendResult((ResultData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case DESTROY_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
msg.arg2, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case EXIT_APPLICATION:
if (mInitialApplication != null) {
mInitialApplication.onTerminate();
}
Looper.myLooper().quit();
break;
case NEW_INTENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
handleNewIntent((NewIntentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UNBIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
handleUnbindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SERVICE_ARGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
handleServiceArgs((ServiceArgsData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
handleStopService((IBinder)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
mUpdatingSystemConfig = true;
try {
handleConfigurationChanged((Configuration) msg.obj, null);
} finally {
mUpdatingSystemConfig = false;
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CLEAN_UP_CONTEXT:
ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
cci.context.performFinalCleanup(cci.who, cci.what);
break;
case GC_WHEN_IDLE:
scheduleGcIdler();
break;
case DUMP_SERVICE:
handleDumpService((DumpComponentInfo)msg.obj);
break;
case LOW_MEMORY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
handleLowMemory();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ACTIVITY_CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
handleActivityConfigurationChanged((ActivityConfigChangeData) msg.obj,
INVALID_DISPLAY);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ACTIVITY_MOVED_TO_DISPLAY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityMovedToDisplay");
handleActivityConfigurationChanged((ActivityConfigChangeData) msg.obj,
msg.arg1 /* displayId */);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PROFILER_CONTROL:
handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2);
break;
case CREATE_BACKUP_AGENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case DESTROY_BACKUP_AGENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SUICIDE:
Process.killProcess(Process.myPid());
break;
case REMOVE_PROVIDER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
completeRemoveProvider((ProviderRefCount)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ENABLE_JIT:
ensureJitEnabled();
break;
case DISPATCH_PACKAGE_BROADCAST:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SCHEDULE_CRASH:
throw new RemoteServiceException((String)msg.obj);
case DUMP_HEAP:
handleDumpHeap((DumpHeapData) msg.obj);
break;
case DUMP_ACTIVITY:
handleDumpActivity((DumpComponentInfo)msg.obj);
break;
case DUMP_PROVIDER:
handleDumpProvider((DumpComponentInfo)msg.obj);
break;
case SLEEPING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SET_CORE_SETTINGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
handleSetCoreSettings((Bundle) msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UPDATE_PACKAGE_COMPATIBILITY_INFO:
handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
break;
case TRIM_MEMORY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
handleTrimMemory(msg.arg1);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UNSTABLE_PROVIDER_DIED:
handleUnstableProviderDied((IBinder)msg.obj, false);
break;
case REQUEST_ASSIST_CONTEXT_EXTRAS:
handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
break;
case TRANSLUCENT_CONVERSION_COMPLETE:
handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
break;
case INSTALL_PROVIDER:
handleInstallProvider((ProviderInfo) msg.obj);
break;
case ON_NEW_ACTIVITY_OPTIONS:
Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj;
onNewActivityOptions(pair.first, pair.second);
break;
case ENTER_ANIMATION_COMPLETE:
handleEnterAnimationComplete((IBinder) msg.obj);
break;
case START_BINDER_TRACKING:
handleStartBinderTracking();
break;
case STOP_BINDER_TRACKING_AND_DUMP:
handleStopBinderTrackingAndDump((ParcelFileDescriptor) msg.obj);
break;
case MULTI_WINDOW_MODE_CHANGED:
handleMultiWindowModeChanged((IBinder) ((SomeArgs) msg.obj).arg1,
((SomeArgs) msg.obj).argi1 == 1,
(Configuration) ((SomeArgs) msg.obj).arg2);
break;
case PICTURE_IN_PICTURE_MODE_CHANGED:
handlePictureInPictureModeChanged((IBinder) ((SomeArgs) msg.obj).arg1,
((SomeArgs) msg.obj).argi1 == 1,
(Configuration) ((SomeArgs) msg.obj).arg2);
break;
case LOCAL_VOICE_INTERACTION_STARTED:
handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
(IVoiceInteractor) ((SomeArgs) msg.obj).arg2);
break;
case ATTACH_AGENT: {
Application app = getApplication();
handleAttachAgent((String) msg.obj, app != null ? app.mLoadedApk : null);
break;
}
case APPLICATION_INFO_CHANGED:
mUpdatingSystemConfig = true;
try {
handleApplicationInfoChanged((ApplicationInfo) msg.obj);
} finally {
mUpdatingSystemConfig = false;
}
break;
}
Object obj = msg.obj;
if (obj instanceof SomeArgs) {
((SomeArgs) obj).recycle();
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}
}
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
if (mBoundApplication != null && mProfiler.profileFd != null
&& mProfiler.autoStopProfiler) {
stopProfiling = true;
}
if (a != null) {
mNewActivities = null;
IActivityManager am = ActivityManager.getService();
ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
}
if (stopProfiling) {
mProfiler.stopProfiling();
}
ensureJitEnabled();
return false;
}
}
final class GcIdler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
doGcIfNeeded();
return false;
}
}
public static ActivityThread currentActivityThread() {
return sCurrentActivityThread;
}
public static boolean isSystem() {
return (sCurrentActivityThread != null) ? sCurrentActivityThread.mSystemThread : false;
}
public static String currentOpPackageName() {
ActivityThread am = currentActivityThread();
return (am != null && am.getApplication() != null)
? am.getApplication().getOpPackageName() : null;
}
public static String currentPackageName() {
ActivityThread am = currentActivityThread();
return (am != null && am.mBoundApplication != null)
? am.mBoundApplication.appInfo.packageName : null;
}
public static String currentProcessName() {
ActivityThread am = currentActivityThread();
return (am != null && am.mBoundApplication != null)
? am.mBoundApplication.processName : null;
}
public static Application currentApplication() {
ActivityThread am = currentActivityThread();
return am != null ? am.mInitialApplication : null;
}
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
//Slog.v("PackageManager", "returning cur default = " + sPackageManager);
return sPackageManager;
}
IBinder b = ServiceManager.getService("package");
//Slog.v("PackageManager", "default service binder = " + b);
sPackageManager = IPackageManager.Stub.asInterface(b);
//Slog.v("PackageManager", "default service = " + sPackageManager);
return sPackageManager;
}
private Configuration mMainThreadConfig = new Configuration();
Configuration applyConfigCompatMainThread(int displayDensity, Configuration config,
CompatibilityInfo compat) {
if (config == null) {
return null;
}
if (!compat.supportsScreen()) {
mMainThreadConfig.setTo(config);
config = mMainThreadConfig;
compat.applyToConfiguration(displayDensity, config);
}
return config;
}
/**
* Creates the top level resources for the given package. Will return an existing
* Resources if one has already been created.
*/
Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
String[] libDirs, int displayId, LoadedApk pkgInfo) {
return mResourcesManager.getResources(null, resDir, splitResDirs, overlayDirs, libDirs,
displayId, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader());
}
final Handler getHandler() {
return mH;
}
public final LoadedApk getLoadedApkForPackageName(String packageName,
CompatibilityInfo compatInfo, int flags) {
return getLoadedApkForPackageName(packageName, compatInfo, flags, UserHandle.myUserId());
}
public final LoadedApk getLoadedApkForPackageName(String packageName,
CompatibilityInfo compatInfo, int flags, int userId) {
final boolean differentUser = (UserHandle.myUserId() != userId);
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (differentUser) {
// Caching not supported across users
ref = null;
} else if ((flags & Context.CONTEXT_INCLUDE_CODE) != 0) {
ref = mPackages.get(packageName);
} else {
ref = mResourcePackages.get(packageName);
}
LoadedApk loadedApk = ref != null ? ref.get() : null;
//Slog.i(TAG, "getLoadedApkForPackageName " + packageName + ": " + loadedApk);
//if (loadedApk != null) Slog.i(TAG, "isUptoDate " + loadedApk.mResDir
// + ": " + loadedApk.mResources.getAssets().isUpToDate());
if (loadedApk != null && (loadedApk.mResources == null
|| loadedApk.mResources.getAssets().isUpToDate())) {
if (loadedApk.isSecurityViolation()
&& (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
throw new SecurityException(
"Requesting code from " + packageName
+ " to be run in process "
+ mBoundApplication.processName
+ "/" + mBoundApplication.appInfo.uid);
}
return loadedApk;
}
}
ApplicationInfo ai = null;
try {
ai = getPackageManager().getApplicationInfo(packageName,
PackageManager.GET_SHARED_LIBRARY_FILES
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
if (ai != null) {
return getLoadedApk(ai, compatInfo, flags);
}
return null;
}
public final LoadedApk getLoadedApk(ApplicationInfo ai, CompatibilityInfo compatInfo,
int flags) {
boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
boolean securityViolation = includeCode && ai.uid != 0
&& ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
: true);
boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0;
if ((flags&(Context.CONTEXT_INCLUDE_CODE
|Context.CONTEXT_IGNORE_SECURITY))
== Context.CONTEXT_INCLUDE_CODE) {
if (securityViolation) {
String msg = "Requesting code from " + ai.packageName
+ " (with uid " + ai.uid + ")";
if (mBoundApplication != null) {
msg = msg + " to be run in process "
+ mBoundApplication.processName + " (with uid "
+ mBoundApplication.appInfo.uid + ")";
}
throw new SecurityException(msg);
}
}
return getLoadedApk(ai, compatInfo, null, securityViolation, includeCode,
registerPackage);
}
public final LoadedApk getLoadedApkNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
return getLoadedApk(ai, compatInfo, null, false, true, false);
}
public final LoadedApk peekLoadedApk(String packageName, boolean includeCode) {
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (includeCode) {
ref = mPackages.get(packageName);
} else {
ref = mResourcePackages.get(packageName);
}
return ref != null ? ref.get() : null;
}
}
private LoadedApk getLoadedApk(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (differentUser) {
// Caching not supported across users
ref = null;
} else if (includeCode) {
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}
LoadedApk loadedApk = ref != null ? ref.get() : null;
if (loadedApk == null || (loadedApk.mResources != null
&& !loadedApk.mResources.getAssets().isUpToDate())) {
if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
: "Loading resource-only package ") + aInfo.packageName
+ " (in " + (mBoundApplication != null
? mBoundApplication.processName : null)
+ ")");
loadedApk =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
if (mSystemThread && "android".equals(aInfo.packageName)) {
loadedApk.installSystemApplicationInfo(aInfo,
getSystemContext().mLoadedApk.getClassLoader());
}
if (differentUser) {
// Caching not supported across users
} else if (includeCode) {
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(loadedApk));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(loadedApk));
}
}
return loadedApk;
}
}
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();
}
public ApplicationThread getApplicationThread()
{
return mAppThread;
}
public Instrumentation getInstrumentation()
{
return mInstrumentation;
}
public boolean isProfiling() {
return mProfiler != null && mProfiler.profileFile != null
&& mProfiler.profileFd == null;
}
public String getProfileFilePath() {
return mProfiler.profileFile;
}
public Looper getLooper() {
return mLooper;
}
public Application getApplication() {
return mInitialApplication;
}
public String getProcessName() {
return mBoundApplication.processName;
}
public ContextImpl getSystemContext() {
synchronized (this) {
if (mSystemContext == null) {
mSystemContext = ContextImpl.createSystemContext(this);
}
return mSystemContext;
}
}
public ContextImpl getSystemUiContext() {
synchronized (this) {
if (mSystemUiContext == null) {
mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
}
return mSystemUiContext;
}
}
public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
synchronized (this) {
getSystemContext().installSystemApplicationInfo(info, classLoader);
getSystemUiContext().installSystemApplicationInfo(info, classLoader);
// give ourselves a default profiler
mProfiler = new Profiler();
}
}
void ensureJitEnabled() {
if (!mJitEnabled) {
mJitEnabled = true;
dalvik.system.VMRuntime.getRuntime().startJitCompilation();
}
}
void scheduleGcIdler() {
if (!mGcIdlerScheduled) {
mGcIdlerScheduled = true;
Looper.myQueue().addIdleHandler(mGcIdler);
}
mH.removeMessages(H.GC_WHEN_IDLE);
}
void unscheduleGcIdler() {
if (mGcIdlerScheduled) {
mGcIdlerScheduled = false;
Looper.myQueue().removeIdleHandler(mGcIdler);
}
mH.removeMessages(H.GC_WHEN_IDLE);
}
void doGcIfNeeded() {
mGcIdlerScheduled = false;
final long now = SystemClock.uptimeMillis();
//Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
// + "m now=" + now);
if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
//Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
BinderInternal.forceGc("bg");
}
}
private static final String HEAP_FULL_COLUMN
= "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
private static final String HEAP_COLUMN
= "%13s %8s %8s %8s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%21s %8d";
private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
private static final String ONE_COUNT_COLUMN_HEADER = "%21s %8s";
// Formatting for checkin service - update version if row format changes
private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 4;
static void printRow(PrintWriter pw, String format, Object...objs) {
pw.println(String.format(format, objs));
}
public static void dumpMemInfoTable(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
int pid, String processName,
long nativeMax, long nativeAllocated, long nativeFree,
long dalvikMax, long dalvikAllocated, long dalvikFree) {
// For checkin, we print one long comma-separated list of values
if (checkin) {
// NOTE: if you change anything significant below, also consider changing
// ACTIVITY_THREAD_CHECKIN_VERSION.
// Header
pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
pw.print(pid); pw.print(',');
pw.print(processName); pw.print(',');
// Heap info - max
pw.print(nativeMax); pw.print(',');
pw.print(dalvikMax); pw.print(',');
pw.print("N/A,");
pw.print(nativeMax + dalvikMax); pw.print(',');
// Heap info - allocated
pw.print(nativeAllocated); pw.print(',');
pw.print(dalvikAllocated); pw.print(',');
pw.print("N/A,");
pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
// Heap info - free
pw.print(nativeFree); pw.print(',');
pw.print(dalvikFree); pw.print(',');
pw.print("N/A,");
pw.print(nativeFree + dalvikFree); pw.print(',');
// Heap info - proportional set size
pw.print(memInfo.nativePss); pw.print(',');
pw.print(memInfo.dalvikPss); pw.print(',');
pw.print(memInfo.otherPss); pw.print(',');
pw.print(memInfo.getTotalPss()); pw.print(',');
// Heap info - swappable set size
pw.print(memInfo.nativeSwappablePss); pw.print(',');
pw.print(memInfo.dalvikSwappablePss); pw.print(',');
pw.print(memInfo.otherSwappablePss); pw.print(',');
pw.print(memInfo.getTotalSwappablePss()); pw.print(',');
// Heap info - shared dirty
pw.print(memInfo.nativeSharedDirty); pw.print(',');
pw.print(memInfo.dalvikSharedDirty); pw.print(',');
pw.print(memInfo.otherSharedDirty); pw.print(',');
pw.print(memInfo.getTotalSharedDirty()); pw.print(',');
// Heap info - shared clean
pw.print(memInfo.nativeSharedClean); pw.print(',');
pw.print(memInfo.dalvikSharedClean); pw.print(',');
pw.print(memInfo.otherSharedClean); pw.print(',');
pw.print(memInfo.getTotalSharedClean()); pw.print(',');
// Heap info - private Dirty
pw.print(memInfo.nativePrivateDirty); pw.print(',');
pw.print(memInfo.dalvikPrivateDirty); pw.print(',');
pw.print(memInfo.otherPrivateDirty); pw.print(',');
pw.print(memInfo.getTotalPrivateDirty()); pw.print(',');
// Heap info - private Clean
pw.print(memInfo.nativePrivateClean); pw.print(',');
pw.print(memInfo.dalvikPrivateClean); pw.print(',');
pw.print(memInfo.otherPrivateClean); pw.print(',');
pw.print(memInfo.getTotalPrivateClean()); pw.print(',');
// Heap info - swapped out
pw.print(memInfo.nativeSwappedOut); pw.print(',');
pw.print(memInfo.dalvikSwappedOut); pw.print(',');
pw.print(memInfo.otherSwappedOut); pw.print(',');
pw.print(memInfo.getTotalSwappedOut()); pw.print(',');
// Heap info - swapped out pss
if (memInfo.hasSwappedOutPss) {
pw.print(memInfo.nativeSwappedOutPss); pw.print(',');
pw.print(memInfo.dalvikSwappedOutPss); pw.print(',');
pw.print(memInfo.otherSwappedOutPss); pw.print(',');
pw.print(memInfo.getTotalSwappedOutPss()); pw.print(',');
} else {
pw.print("N/A,");
pw.print("N/A,");
pw.print("N/A,");
pw.print("N/A,");
}
// Heap info - other areas
for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
pw.print(Debug.MemoryInfo.getOtherLabel(i)); pw.print(',');
pw.print(memInfo.getOtherPss(i)); pw.print(',');
pw.print(memInfo.getOtherSwappablePss(i)); pw.print(',');
pw.print(memInfo.getOtherSharedDirty(i)); pw.print(',');
pw.print(memInfo.getOtherSharedClean(i)); pw.print(',');
pw.print(memInfo.getOtherPrivateDirty(i)); pw.print(',');
pw.print(memInfo.getOtherPrivateClean(i)); pw.print(',');
pw.print(memInfo.getOtherSwappedOut(i)); pw.print(',');
if (memInfo.hasSwappedOutPss) {
pw.print(memInfo.getOtherSwappedOutPss(i)); pw.print(',');
} else {
pw.print("N/A,");
}
}
return;
}
if (!dumpSummaryOnly) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
"Shared", "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
"Heap", "Heap", "Heap");
printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
"Clean", "Clean", "Dirty",
"Size", "Alloc", "Free");
printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
"------", "------", "------", "------", "------", "------");
printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss,
memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
memInfo.nativePrivateClean, memInfo.hasSwappedOutPss ?
memInfo.nativeSwappedOutPss : memInfo.nativeSwappedOut,
nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss ?