summaryrefslogtreecommitdiff
path: root/core/java/android/app/ActivityThread.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/app/ActivityThread.java')
-rw-r--r--core/java/android/app/ActivityThread.java761
1 files changed, 515 insertions, 246 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index c4281f0b8d28..812ca4aefb9b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -17,6 +17,8 @@
package android.app;
import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
@@ -41,8 +43,10 @@ import android.app.servertransaction.ActivityRelaunchItem;
import android.app.servertransaction.ActivityResultItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.ClientTransactionItem;
+import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.PendingTransactionActions.StopInfo;
+import android.app.servertransaction.ResumeActivityItem;
import android.app.servertransaction.TransactionExecutor;
import android.app.servertransaction.TransactionExecutorHelper;
import android.compat.annotation.UnsupportedAppUsage;
@@ -66,12 +70,14 @@ 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.ProviderInfoList;
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.content.res.loader.ResourcesLoader;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteDebug.DbStats;
@@ -80,6 +86,7 @@ import android.graphics.Canvas;
import android.graphics.HardwareRenderer;
import android.graphics.ImageDecoder;
import android.hardware.display.DisplayManagerGlobal;
+import android.inputmethodservice.InputMethodService;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.Proxy;
@@ -108,11 +115,16 @@ import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.StatsFrameworkInitializer;
+import android.os.StatsServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.TelephonyServiceManager;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.UserManager;
+import android.permission.IPermissionManager;
import android.provider.BlockedNumberContract;
import android.provider.CalendarContract;
import android.provider.CallLog;
@@ -126,6 +138,7 @@ import android.security.net.config.NetworkSecurityConfigProvider;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.system.StructStat;
+import android.telephony.TelephonyFrameworkInitializer;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
@@ -144,6 +157,8 @@ import android.util.proto.ProtoOutputStream;
import android.view.Choreographer;
import android.view.ContextThemeWrapper;
import android.view.Display;
+import android.view.DisplayAdjustments;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewDebug;
@@ -191,6 +206,7 @@ import java.lang.reflect.Method;
import java.net.InetAddress;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -202,6 +218,7 @@ import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
final class RemoteServiceException extends AndroidRuntimeException {
public RemoteServiceException(String msg) {
@@ -289,6 +306,7 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage
static volatile IPackageManager sPackageManager;
+ private static volatile IPermissionManager sPermissionManager;
@UnsupportedAppUsage
final ApplicationThread mAppThread = new ApplicationThread();
@@ -363,7 +381,6 @@ public final class ActivityThread extends ClientTransactionHandler {
String mInstrumentedLibDir = null;
boolean mSystemThread = false;
boolean mSomeActivitiesChanged = false;
- boolean mUpdatingSystemConfig = false;
/* package */ boolean mHiddenApiWarningShown = false;
// These can be accessed by multiple threads; mResourcesManager is the lock.
@@ -392,10 +409,16 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final ResourcesManager mResourcesManager;
+ /** The active adjustments that override the {@link DisplayAdjustments} in resources. */
+ private ArrayList<Pair<IBinder, Consumer<DisplayAdjustments>>> mActiveRotationAdjustments;
+
// Registry of remote cancellation transports pending a reply with reply handles.
@GuardedBy("this")
private @Nullable Map<SafeCancellationTransport, CancellationSignal> mRemoteCancellations;
+ private final Map<IBinder, Integer> mLastReportedWindowingMode = Collections.synchronizedMap(
+ new ArrayMap<>());
+
private static final class ProviderKey {
final String authority;
final int userId;
@@ -455,6 +478,8 @@ public final class ActivityThread extends ClientTransactionHandler {
Bundle mCoreSettings = null;
+ boolean mHasImeComponent = false;
+
/** Activity client record, used for bookkeeping for the real {@link Activity} instance. */
public static final class ActivityClientRecord {
@UnsupportedAppUsage
@@ -515,12 +540,20 @@ public final class ActivityThread extends ClientTransactionHandler {
boolean startsNotResumed;
public final boolean isForward;
int pendingConfigChanges;
+ // Whether we are in the process of performing on user leaving.
+ boolean mIsUserLeaving;
Window mPendingRemoveWindow;
WindowManager mPendingRemoveWindowManager;
@UnsupportedAppUsage
boolean mPreserveWindow;
+ /**
+ * If non-null, the activity is launching with a specified rotation, the adjustments should
+ * be consumed before activity creation.
+ */
+ FixedRotationAdjustments mPendingFixedRotationAdjustments;
+
@LifecycleState
private int mLifecycleState = PRE_ON_CREATE;
@@ -537,7 +570,7 @@ public final class ActivityThread extends ClientTransactionHandler {
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, boolean isForward,
ProfilerInfo profilerInfo, ClientTransactionHandler client,
- IBinder assistToken) {
+ IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) {
this.token = token;
this.assistToken = assistToken;
this.ident = ident;
@@ -555,6 +588,7 @@ public final class ActivityThread extends ClientTransactionHandler {
this.overrideConfig = overrideConfig;
this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo,
compatInfo);
+ mPendingFixedRotationAdjustments = fixedRotationAdjustments;
init();
}
@@ -913,10 +947,6 @@ public final class ActivityThread extends ClientTransactionHandler {
private class ApplicationThread extends IApplicationThread.Stub {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
- public final void scheduleSleeping(IBinder token, boolean sleeping) {
- sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
- }
-
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
@@ -1002,8 +1032,9 @@ public final class ActivityThread extends ClientTransactionHandler {
sendMessage(H.STOP_SERVICE, token);
}
+ @Override
public final void bindApplication(String processName, ApplicationInfo appInfo,
- List<ProviderInfo> providers, ComponentName instrumentationName,
+ ProviderInfoList providerList, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
@@ -1043,7 +1074,7 @@ public final class ActivityThread extends ClientTransactionHandler {
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
- data.providers = providers;
+ data.providers = providerList.getList();
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
@@ -1155,6 +1186,8 @@ public final class ActivityThread extends ClientTransactionHandler {
} catch (IOException e) {
Slog.e(TAG, "Failed to duplicate heap dump file descriptor", e);
return;
+ } finally {
+ IoUtils.closeQuietly(fd);
}
dhd.finishCallback = finishCallback;
sendMessage(H.DUMP_HEAP, dhd, 0, 0, true /*async*/);
@@ -1503,6 +1536,12 @@ public final class ActivityThread extends ClientTransactionHandler {
IoUtils.closeQuietly(pfd);
}
+ @Override
+ public void dumpCacheInfo(ParcelFileDescriptor pfd, String[] args) {
+ PropertyInvalidatedCache.dumpCacheInfo(pfd.getFileDescriptor(), args);
+ IoUtils.closeQuietly(pfd);
+ }
+
private File getDatabasesDir(Context context) {
// There's no simple way to get the databases/ path, so do it this way.
return context.getDatabasePath("a").getParentFile();
@@ -1844,7 +1883,6 @@ public final class ActivityThread extends ClientTransactionHandler {
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 DUMP_PROVIDER: return "DUMP_PROVIDER";
@@ -1887,7 +1925,10 @@ public final class ActivityThread extends ClientTransactionHandler {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CREATE_SERVICE:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ ("serviceCreate: " + String.valueOf(msg.obj)));
+ }
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
@@ -1903,7 +1944,10 @@ public final class ActivityThread extends ClientTransactionHandler {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SERVICE_ARGS:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ ("serviceStart: " + String.valueOf(msg.obj)));
+ }
handleServiceArgs((ServiceArgsData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
@@ -1968,11 +2012,6 @@ public final class ActivityThread extends ClientTransactionHandler {
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);
@@ -2016,12 +2055,7 @@ public final class ActivityThread extends ClientTransactionHandler {
break;
}
case APPLICATION_INFO_CHANGED:
- mUpdatingSystemConfig = true;
- try {
- handleApplicationInfoChanged((ApplicationInfo) msg.obj);
- } finally {
- mUpdatingSystemConfig = false;
- }
+ handleApplicationInfoChanged((ApplicationInfo) msg.obj);
break;
case RUN_ISOLATED_ENTRY_POINT:
handleRunIsolatedEntryPoint((String) ((SomeArgs) msg.obj).arg1,
@@ -2150,16 +2184,23 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage
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);
+ final IBinder b = ServiceManager.getService("package");
sPackageManager = IPackageManager.Stub.asInterface(b);
- //Slog.v("PackageManager", "default service = " + sPackageManager);
return sPackageManager;
}
+ /** Returns the permission manager */
+ public static IPermissionManager getPermissionManager() {
+ if (sPermissionManager != null) {
+ return sPermissionManager;
+ }
+ final IBinder b = ServiceManager.getService("permissionmgr");
+ sPermissionManager = IPermissionManager.Stub.asInterface(b);
+ return sPermissionManager;
+ }
+
private Configuration mMainThreadConfig = new Configuration();
Configuration applyConfigCompatMainThread(int displayDensity, Configuration config,
@@ -2182,7 +2223,7 @@ public final class ActivityThread extends ClientTransactionHandler {
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());
+ displayId, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader(), null);
}
@UnsupportedAppUsage
@@ -2199,16 +2240,11 @@ public final class ActivityThread extends ClientTransactionHandler {
public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
int flags, int userId) {
final boolean differentUser = (UserHandle.myUserId() != userId);
- ApplicationInfo ai;
- try {
- ai = getPackageManager().getApplicationInfo(packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES
- | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
- (userId < 0) ? UserHandle.myUserId() : userId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
-
+ ApplicationInfo ai = PackageManager.getApplicationInfoAsUserCached(
+ packageName,
+ PackageManager.GET_SHARED_LIBRARY_FILES
+ | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ (userId < 0) ? UserHandle.myUserId() : userId);
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (differentUser) {
@@ -2223,7 +2259,9 @@ public final class ActivityThread extends ClientTransactionHandler {
LoadedApk packageInfo = ref != null ? ref.get() : null;
if (ai != null && packageInfo != null) {
if (!isLoadedApkResourceDirsUpToDate(packageInfo, ai)) {
- packageInfo.updateApplicationInfo(ai, null);
+ List<String> oldPaths = new ArrayList<>();
+ LoadedApk.makePaths(this, ai, oldPaths);
+ packageInfo.updateApplicationInfo(ai, oldPaths);
}
if (packageInfo.isSecurityViolation()
@@ -2311,7 +2349,9 @@ public final class ActivityThread extends ClientTransactionHandler {
if (packageInfo != null) {
if (!isLoadedApkResourceDirsUpToDate(packageInfo, aInfo)) {
- packageInfo.updateApplicationInfo(aInfo, null);
+ List<String> oldPaths = new ArrayList<>();
+ LoadedApk.makePaths(this, aInfo, oldPaths);
+ packageInfo.updateApplicationInfo(aInfo, oldPaths);
}
return packageInfo;
@@ -2491,13 +2531,15 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- 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 HEAP_FULL_COLUMN =
+ "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
+ private static final String HEAP_COLUMN =
+ "%13s %8s %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";
+ private static final String THREE_COUNT_COLUMNS = "%21s %8d %21s %8s %21s %8d";
+ private static final String TWO_COUNT_COLUMN_HEADER = "%21s %8s %21s %8s";
+ private static final String ONE_ALT_COUNT_COLUMN = "%21s %8s %21s %8d";
// Formatting for checkin service - update version if row format changes
private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 4;
@@ -2618,43 +2660,43 @@ public final class ActivityThread extends ClientTransactionHandler {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
"Shared", "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
- "Heap", "Heap", "Heap");
+ "Rss", "Heap", "Heap", "Heap");
printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
- "Clean", "Clean", "Dirty",
+ "Clean", "Clean", "Dirty", "Total",
"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);
+ memInfo.nativeRss, nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss ?
memInfo.dalvikSwappedOutPss : memInfo.dalvikSwappedOut,
- dalvikMax, dalvikAllocated, dalvikFree);
+ memInfo.dalvikRss, dalvikMax, dalvikAllocated, dalvikFree);
} else {
printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
"Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
- "Heap", "Heap", "Heap");
+ "Rss", "Heap", "Heap", "Heap");
printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
- "Clean", "Dirty", "Size", "Alloc", "Free");
+ "Clean", "Dirty", "Total", "Size", "Alloc", "Free");
printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
- "------", "------", "------", "------", "------");
+ "------", "------", "------", "------", "------", "------");
printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
memInfo.nativePrivateDirty,
memInfo.nativePrivateClean,
memInfo.hasSwappedOutPss ? memInfo.nativeSwappedOutPss :
- memInfo.nativeSwappedOut,
+ memInfo.nativeSwappedOut, memInfo.nativeRss,
nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikPrivateDirty,
memInfo.dalvikPrivateClean,
memInfo.hasSwappedOutPss ? memInfo.dalvikSwappedOutPss :
- memInfo.dalvikSwappedOut,
+ memInfo.dalvikSwappedOut, memInfo.dalvikRss,
dalvikMax, dalvikAllocated, dalvikFree);
}
@@ -2666,6 +2708,7 @@ public final class ActivityThread extends ClientTransactionHandler {
int otherPrivateClean = memInfo.otherPrivateClean;
int otherSwappedOut = memInfo.otherSwappedOut;
int otherSwappedOutPss = memInfo.otherSwappedOutPss;
+ int otherRss = memInfo.otherRss;
for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
final int myPss = memInfo.getOtherPss(i);
@@ -2676,21 +2719,22 @@ public final class ActivityThread extends ClientTransactionHandler {
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+ final int myRss = memInfo.getOtherRss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
- || mySharedClean != 0 || myPrivateClean != 0
+ || mySharedClean != 0 || myPrivateClean != 0 || myRss != 0
|| (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean,
memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
- "", "", "");
+ myRss, "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, myPrivateDirty,
myPrivateClean,
memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
- "", "", "");
+ myRss, "", "", "");
}
otherPss -= myPss;
otherSwappablePss -= mySwappablePss;
@@ -2700,6 +2744,7 @@ public final class ActivityThread extends ClientTransactionHandler {
otherPrivateClean -= myPrivateClean;
otherSwappedOut -= mySwappedOut;
otherSwappedOutPss -= mySwappedOutPss;
+ otherRss -= myRss;
}
}
@@ -2707,25 +2752,25 @@ public final class ActivityThread extends ClientTransactionHandler {
printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss,
otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
- "", "", "");
+ otherRss, "", "", "");
printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(),
memInfo.getTotalSwappablePss(),
memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
- memInfo.getTotalSwappedOut(),
+ memInfo.getTotalSwappedOut(), memInfo.getTotalRss(),
nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
nativeFree+dalvikFree);
} else {
printRow(pw, HEAP_COLUMN, "Unknown", otherPss,
otherPrivateDirty, otherPrivateClean,
memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
- "", "", "");
+ otherRss, "", "", "");
printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
memInfo.getTotalPrivateDirty(),
memInfo.getTotalPrivateClean(),
memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
- memInfo.getTotalSwappedOut(),
+ memInfo.getTotalSwappedOut(), memInfo.getTotalPss(),
nativeMax+dalvikMax,
nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
}
@@ -2744,6 +2789,7 @@ public final class ActivityThread extends ClientTransactionHandler {
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+ final int myRss = memInfo.getOtherRss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
|| mySharedClean != 0 || myPrivateClean != 0
|| (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
@@ -2752,13 +2798,13 @@ public final class ActivityThread extends ClientTransactionHandler {
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean,
memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
- "", "", "");
+ myRss, "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, myPrivateDirty,
myPrivateClean,
memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
- "", "", "");
+ myRss, "", "", "");
}
}
}
@@ -2767,31 +2813,36 @@ public final class ActivityThread extends ClientTransactionHandler {
pw.println(" ");
pw.println(" App Summary");
- printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "Pss(KB)");
- printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "------");
- printRow(pw, ONE_COUNT_COLUMN,
- "Java Heap:", memInfo.getSummaryJavaHeap());
- printRow(pw, ONE_COUNT_COLUMN,
- "Native Heap:", memInfo.getSummaryNativeHeap());
- printRow(pw, ONE_COUNT_COLUMN,
- "Code:", memInfo.getSummaryCode());
+ printRow(pw, TWO_COUNT_COLUMN_HEADER, "", "Pss(KB)", "", "Rss(KB)");
+ printRow(pw, TWO_COUNT_COLUMN_HEADER, "", "------", "", "------");
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Java Heap:", memInfo.getSummaryJavaHeap(), "", memInfo.getSummaryJavaHeapRss());
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Native Heap:", memInfo.getSummaryNativeHeap(), "",
+ memInfo.getSummaryNativeHeapRss());
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Code:", memInfo.getSummaryCode(), "", memInfo.getSummaryCodeRss());
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Stack:", memInfo.getSummaryStack(), "", memInfo.getSummaryStackRss());
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "Graphics:", memInfo.getSummaryGraphics(), "", memInfo.getSummaryGraphicsRss());
printRow(pw, ONE_COUNT_COLUMN,
- "Stack:", memInfo.getSummaryStack());
+ "Private Other:", memInfo.getSummaryPrivateOther());
printRow(pw, ONE_COUNT_COLUMN,
- "Graphics:", memInfo.getSummaryGraphics());
- printRow(pw, ONE_COUNT_COLUMN,
- "Private Other:", memInfo.getSummaryPrivateOther());
- printRow(pw, ONE_COUNT_COLUMN,
- "System:", memInfo.getSummarySystem());
+ "System:", memInfo.getSummarySystem());
+ printRow(pw, ONE_ALT_COUNT_COLUMN,
+ "Unknown:", "", "", memInfo.getSummaryUnknownRss());
pw.println(" ");
if (memInfo.hasSwappedOutPss) {
- printRow(pw, TWO_COUNT_COLUMNS,
- "TOTAL:", memInfo.getSummaryTotalPss(),
- "TOTAL SWAP PSS:", memInfo.getSummaryTotalSwapPss());
+ printRow(pw, THREE_COUNT_COLUMNS,
+ "TOTAL PSS:", memInfo.getSummaryTotalPss(),
+ "TOTAL RSS:", memInfo.getTotalRss(),
+ "TOTAL SWAP PSS:", memInfo.getSummaryTotalSwapPss());
} else {
- printRow(pw, TWO_COUNT_COLUMNS,
- "TOTAL:", memInfo.getSummaryTotalPss(),
- "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
+ printRow(pw, THREE_COUNT_COLUMNS,
+ "TOTAL PSS:", memInfo.getSummaryTotalPss(),
+ "TOTAL RSS:", memInfo.getTotalRss(),
+ "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
}
}
@@ -2803,7 +2854,7 @@ public final class ActivityThread extends ClientTransactionHandler {
private static void dumpMemoryInfo(ProtoOutputStream proto, long fieldId, String name,
int pss, int cleanPss, int sharedDirty, int privateDirty,
int sharedClean, int privateClean,
- boolean hasSwappedOutPss, int dirtySwap, int dirtySwapPss) {
+ boolean hasSwappedOutPss, int dirtySwap, int dirtySwapPss, int rss) {
final long token = proto.start(fieldId);
proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.NAME, name);
@@ -2818,6 +2869,7 @@ public final class ActivityThread extends ClientTransactionHandler {
} else {
proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.DIRTY_SWAP_KB, dirtySwap);
}
+ proto.write(MemInfoDumpProto.ProcessMemory.MemoryInfo.TOTAL_RSS_KB, rss);
proto.end(token);
}
@@ -2836,7 +2888,8 @@ public final class ActivityThread extends ClientTransactionHandler {
memInfo.nativePss, memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
memInfo.nativePrivateClean, memInfo.hasSwappedOutPss,
- memInfo.nativeSwappedOut, memInfo.nativeSwappedOutPss);
+ memInfo.nativeSwappedOut, memInfo.nativeSwappedOutPss,
+ memInfo.nativeRss);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, nativeMax);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, nativeAllocated);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, nativeFree);
@@ -2847,7 +2900,8 @@ public final class ActivityThread extends ClientTransactionHandler {
memInfo.dalvikPss, memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss,
- memInfo.dalvikSwappedOut, memInfo.dalvikSwappedOutPss);
+ memInfo.dalvikSwappedOut, memInfo.dalvikSwappedOutPss,
+ memInfo.dalvikRss);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB, dalvikMax);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB, dalvikAllocated);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_FREE_KB, dalvikFree);
@@ -2861,6 +2915,7 @@ public final class ActivityThread extends ClientTransactionHandler {
int otherPrivateClean = memInfo.otherPrivateClean;
int otherSwappedOut = memInfo.otherSwappedOut;
int otherSwappedOutPss = memInfo.otherSwappedOutPss;
+ int otherRss = memInfo.otherRss;
for (int i = 0; i < Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
final int myPss = memInfo.getOtherPss(i);
@@ -2871,14 +2926,15 @@ public final class ActivityThread extends ClientTransactionHandler {
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+ final int myRss = memInfo.getOtherRss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
- || mySharedClean != 0 || myPrivateClean != 0
+ || mySharedClean != 0 || myPrivateClean != 0 || myRss != 0
|| (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.OTHER_HEAPS,
Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean,
- memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss);
+ memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss, myRss);
otherPss -= myPss;
otherSwappablePss -= mySwappablePss;
@@ -2888,20 +2944,21 @@ public final class ActivityThread extends ClientTransactionHandler {
otherPrivateClean -= myPrivateClean;
otherSwappedOut -= mySwappedOut;
otherSwappedOutPss -= mySwappedOutPss;
+ otherRss -= myRss;
}
}
dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.UNKNOWN_HEAP, "Unknown",
otherPss, otherSwappablePss,
otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
- memInfo.hasSwappedOutPss, otherSwappedOut, otherSwappedOutPss);
+ memInfo.hasSwappedOutPss, otherSwappedOut, otherSwappedOutPss, otherRss);
final long tToken = proto.start(MemInfoDumpProto.ProcessMemory.TOTAL_HEAP);
dumpMemoryInfo(proto, MemInfoDumpProto.ProcessMemory.HeapInfo.MEM_INFO, "TOTAL",
memInfo.getTotalPss(), memInfo.getTotalSwappablePss(),
memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
memInfo.hasSwappedOutPss, memInfo.getTotalSwappedOut(),
- memInfo.getTotalSwappedOutPss());
+ memInfo.getTotalSwappedOutPss(), memInfo.getTotalRss());
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_SIZE_KB,
nativeMax + dalvikMax);
proto.write(MemInfoDumpProto.ProcessMemory.HeapInfo.HEAP_ALLOC_KB,
@@ -2922,6 +2979,7 @@ public final class ActivityThread extends ClientTransactionHandler {
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+ final int myRss = memInfo.getOtherRss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
|| mySharedClean != 0 || myPrivateClean != 0
|| (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
@@ -2929,7 +2987,7 @@ public final class ActivityThread extends ClientTransactionHandler {
Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean,
- memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss);
+ memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss, myRss);
}
}
}
@@ -2957,6 +3015,19 @@ public final class ActivityThread extends ClientTransactionHandler {
proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.TOTAL_SWAP_PSS,
memInfo.getSummaryTotalSwap());
}
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.JAVA_HEAP_RSS_KB,
+ memInfo.getSummaryJavaHeapRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.NATIVE_HEAP_RSS_KB,
+ memInfo.getSummaryNativeHeapRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.CODE_RSS_KB,
+ memInfo.getSummaryCodeRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.STACK_RSS_KB,
+ memInfo.getSummaryStackRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.GRAPHICS_RSS_KB,
+ memInfo.getSummaryGraphicsRss());
+ proto.write(MemInfoDumpProto.ProcessMemory.AppSummary.UNKNOWN_RSS_KB,
+ memInfo.getSummaryUnknownRss());
+
proto.end(asToken);
}
@@ -3038,6 +3109,11 @@ public final class ActivityThread extends ClientTransactionHandler {
return mActivities.get(token);
}
+ @VisibleForTesting(visibility = PACKAGE)
+ public Configuration getConfiguration() {
+ return mConfiguration;
+ }
+
@Override
public void updatePendingConfiguration(Configuration config) {
synchronized (mResourcesManager) {
@@ -3174,6 +3250,82 @@ public final class ActivityThread extends ClientTransactionHandler {
sendMessage(H.CLEAN_UP_CONTEXT, cci);
}
+ @Override
+ public void handleFixedRotationAdjustments(@NonNull IBinder token,
+ @Nullable FixedRotationAdjustments fixedRotationAdjustments) {
+ handleFixedRotationAdjustments(token, fixedRotationAdjustments, null /* overrideConfig */);
+ }
+
+ /**
+ * Applies the rotation adjustments to override display information in resources belong to the
+ * provided token. If the token is activity token, the adjustments also apply to application
+ * because the appearance of activity is usually more sensitive to the application resources.
+ *
+ * @param token The token to apply the adjustments.
+ * @param fixedRotationAdjustments The information to override the display adjustments of
+ * corresponding resources. If it is null, the exiting override
+ * will be cleared.
+ * @param overrideConfig The override configuration of activity. It is used to override
+ * application configuration. If it is non-null, it means the token is
+ * confirmed as activity token. Especially when launching new activity,
+ * {@link #mActivities} hasn't put the new token.
+ */
+ private void handleFixedRotationAdjustments(@NonNull IBinder token,
+ @Nullable FixedRotationAdjustments fixedRotationAdjustments,
+ @Nullable Configuration overrideConfig) {
+ // The element of application configuration override is set only if the application
+ // adjustments are needed, because activity already has its own override configuration.
+ final Configuration[] appConfigOverride;
+ final Consumer<DisplayAdjustments> override;
+ if (fixedRotationAdjustments != null) {
+ appConfigOverride = new Configuration[1];
+ override = displayAdjustments -> {
+ displayAdjustments.setFixedRotationAdjustments(fixedRotationAdjustments);
+ if (appConfigOverride[0] != null) {
+ displayAdjustments.getConfiguration().updateFrom(appConfigOverride[0]);
+ }
+ };
+ } else {
+ appConfigOverride = null;
+ override = null;
+ }
+ if (!mResourcesManager.overrideTokenDisplayAdjustments(token, override)) {
+ // No resources are associated with the token.
+ return;
+ }
+ if (overrideConfig == null) {
+ final ActivityClientRecord r = mActivities.get(token);
+ if (r == null) {
+ // It is not an activity token. Nothing to do for application.
+ return;
+ }
+ overrideConfig = r.overrideConfig;
+ }
+ if (appConfigOverride != null) {
+ appConfigOverride[0] = overrideConfig;
+ }
+
+ // Apply the last override to application resources for compatibility. Because the Resources
+ // of Display can be from application, e.g.
+ // applicationContext.getSystemService(DisplayManager.class).getDisplay(displayId)
+ // and the deprecated usage:
+ // applicationContext.getSystemService(WindowManager.class).getDefaultDisplay();
+ final Consumer<DisplayAdjustments> appOverride;
+ if (mActiveRotationAdjustments == null) {
+ mActiveRotationAdjustments = new ArrayList<>(2);
+ }
+ if (override != null) {
+ mActiveRotationAdjustments.add(Pair.create(token, override));
+ appOverride = override;
+ } else {
+ mActiveRotationAdjustments.removeIf(adjustmentsPair -> adjustmentsPair.first == token);
+ appOverride = mActiveRotationAdjustments.isEmpty()
+ ? null
+ : mActiveRotationAdjustments.get(mActiveRotationAdjustments.size() - 1).second;
+ }
+ mInitialApplication.getResources().overrideDisplayAdjustments(appOverride);
+ }
+
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
@@ -3239,6 +3391,12 @@ public final class ActivityThread extends ClientTransactionHandler {
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
+
+ // Activity resources must be initialized with the same loaders as the
+ // application context.
+ appContext.getResources().addLoaders(
+ app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
+
appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
@@ -3269,6 +3427,8 @@ public final class ActivityThread extends ClientTransactionHandler {
" did not call through to super.onCreate()");
}
r.activity = activity;
+ mLastReportedWindowingMode.put(activity.getActivityToken(),
+ config.windowConfiguration.getWindowingMode());
}
r.setState(ON_CREATE);
@@ -3294,8 +3454,8 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleStartActivity(ActivityClientRecord r,
- PendingTransactionActions pendingActions) {
+ public void handleStartActivity(IBinder token, PendingTransactionActions pendingActions) {
+ final ActivityClientRecord r = mActivities.get(token);
final Activity activity = r.activity;
if (r.activity == null) {
// TODO(lifecycler): What do we do in this case?
@@ -3309,6 +3469,8 @@ public final class ActivityThread extends ClientTransactionHandler {
return;
}
+ unscheduleGcIdler();
+
// Start
activity.performStart("handleStartActivity");
r.setState(ON_START);
@@ -3345,6 +3507,9 @@ public final class ActivityThread extends ClientTransactionHandler {
+ " did not call through to super.onPostCreate()");
}
}
+
+ updateVisibility(r, true /* show */);
+ mSomeActivitiesChanged = true;
}
/**
@@ -3366,7 +3531,7 @@ public final class ActivityThread extends ClientTransactionHandler {
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
final int displayId;
try {
- displayId = ActivityTaskManager.getService().getActivityDisplayId(r.token);
+ displayId = ActivityTaskManager.getService().getDisplayId(r.token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3374,6 +3539,14 @@ public final class ActivityThread extends ClientTransactionHandler {
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
+ // The rotation adjustments must be applied before creating the activity, so the activity
+ // can get the adjusted display info during creation.
+ if (r.mPendingFixedRotationAdjustments != null) {
+ handleFixedRotationAdjustments(r.token, r.mPendingFixedRotationAdjustments,
+ r.overrideConfig);
+ r.mPendingFixedRotationAdjustments = null;
+ }
+
final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
// For debugging purposes, if the activity's package name contains the value of
// the "debug.use-second-display" system property as a substring, then show
@@ -3604,7 +3777,7 @@ public final class ActivityThread extends ClientTransactionHandler {
r.activity, Looper.myLooper());
}
r.activity.onGetDirectActions(cancellationSignal, (actions) -> {
- Preconditions.checkNotNull(actions);
+ Objects.requireNonNull(actions);
Preconditions.checkCollectionElementsNotNull(actions, "actions");
if (!actions.isEmpty()) {
final int actionCount = actions.size();
@@ -3687,31 +3860,62 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
- Configuration overrideConfig) {
+ public void handlePictureInPictureRequested(IBinder token) {
final ActivityClientRecord r = mActivities.get(token);
- if (r != null) {
- final Configuration newConfig = new Configuration(mConfiguration);
- if (overrideConfig != null) {
- newConfig.updateFrom(overrideConfig);
- }
- r.activity.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ if (r == null) {
+ Log.w(TAG, "Activity to request PIP to no longer exists");
+ return;
+ }
+
+ final boolean receivedByApp = r.activity.onPictureInPictureRequested();
+ if (!receivedByApp) {
+ // Previous recommendation was for apps to enter picture-in-picture in
+ // onUserLeavingHint() for cases such as the app being put into the background. For
+ // backwards compatibility with apps that are not using the newer
+ // onPictureInPictureRequested() callback, we schedule the life cycle events needed to
+ // trigger onUserLeavingHint(), then we return the activity to its previous state.
+ schedulePauseWithUserLeaveHintAndReturnToCurrentState(r);
}
}
- @Override
- public void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
- Configuration overrideConfig) {
- final ActivityClientRecord r = mActivities.get(token);
- if (r != null) {
- final Configuration newConfig = new Configuration(mConfiguration);
- if (overrideConfig != null) {
- newConfig.updateFrom(overrideConfig);
- }
- r.activity.dispatchPictureInPictureModeChanged(isInPipMode, newConfig);
+ /**
+ * Cycle activity through onPause and onUserLeaveHint so that PIP is entered if supported, then
+ * return to its previous state. This allows activities that rely on onUserLeaveHint instead of
+ * onPictureInPictureRequested to enter picture-in-picture.
+ */
+ private void schedulePauseWithUserLeaveHintAndReturnToCurrentState(ActivityClientRecord r) {
+ final int prevState = r.getLifecycleState();
+ if (prevState != ON_RESUME && prevState != ON_PAUSE) {
+ return;
+ }
+
+ switch (prevState) {
+ case ON_RESUME:
+ // Schedule a PAUSE then return to RESUME.
+ schedulePauseWithUserLeavingHint(r);
+ scheduleResume(r);
+ break;
+ case ON_PAUSE:
+ // Schedule a RESUME then return to PAUSE.
+ scheduleResume(r);
+ schedulePauseWithUserLeavingHint(r);
+ break;
}
}
+ private void schedulePauseWithUserLeavingHint(ActivityClientRecord r) {
+ final ClientTransaction transaction = ClientTransaction.obtain(this.mAppThread, r.token);
+ transaction.setLifecycleStateRequest(PauseActivityItem.obtain(r.activity.isFinishing(),
+ /* userLeaving */ true, r.activity.mConfigChangeFlags, /* dontReport */ false));
+ executeTransaction(transaction);
+ }
+
+ private void scheduleResume(ActivityClientRecord r) {
+ final ClientTransaction transaction = ClientTransaction.obtain(this.mAppThread, r.token);
+ transaction.setLifecycleStateRequest(ResumeActivityItem.obtain(/* isForward */ false));
+ executeTransaction(transaction);
+ }
+
private void handleLocalVoiceInteractionStarted(IBinder token, IVoiceInteractor interactor) {
final ActivityClientRecord r = mActivities.get(token);
if (r != null) {
@@ -3970,24 +4174,19 @@ public final class ActivityThread extends ClientTransactionHandler {
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
+ if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
+
+ ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
+ Application app = packageInfo.makeApplication(false, mInstrumentation);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
- } catch (Exception e) {
- if (!mInstrumentation.onException(service, e)) {
- throw new RuntimeException(
- "Unable to instantiate service " + data.info.name
- + ": " + e.toString(), e);
- }
- }
+ // Service resources must be initialized with the same loaders as the application
+ // context.
+ context.getResources().addLoaders(
+ app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
- try {
- if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
-
- ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
-
- Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
@@ -4366,7 +4565,9 @@ public final class ActivityThread extends ClientTransactionHandler {
r.newConfig = null;
}
if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
- WindowManager.LayoutParams l = r.window.getAttributes();
+ ViewRootImpl impl = r.window.getDecorView().getViewRootImpl();
+ WindowManager.LayoutParams l = impl != null
+ ? impl.mWindowAttributes : r.window.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
!= forwardBit) {
@@ -4454,6 +4655,7 @@ public final class ActivityThread extends ClientTransactionHandler {
}
final void performUserLeavingActivity(ActivityClientRecord r) {
+ mInstrumentation.callActivityOnPictureInPictureRequested(r.activity);
mInstrumentation.callActivityOnUserLeaving(r.activity);
}
@@ -4550,8 +4752,8 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage
final void performStopActivity(IBinder token, boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
- performStopActivityInner(r, null /* stopInfo */, false /* keepShown */, saveState,
- false /* finalStateRequest */, reason);
+ performStopActivityInner(r, null /* stopInfo */, saveState, false /* finalStateRequest */,
+ reason);
}
private static final class ProviderRefCount {
@@ -4577,25 +4779,19 @@ public final class ActivityThread extends ClientTransactionHandler {
}
/**
- * Core implementation of stopping an activity. Note this is a little
- * tricky because the server's meaning of stop is slightly different
- * than our client -- for the server, stop means to save state and give
- * it the result when it is done, but the window may still be visible.
- * For the client, we want to call onStop()/onStart() to indicate when
- * the activity's UI visibility changes.
+ * Core implementation of stopping an activity.
* @param r Target activity client record.
* @param info Action that will report activity stop to server.
- * @param keepShown Flag indicating whether the activity is still shown.
* @param saveState Flag indicating whether the activity state should be saved.
* @param finalStateRequest Flag indicating if this call is handling final lifecycle state
* request for a transaction.
* @param reason Reason for performing this operation.
*/
- private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown,
+ private void performStopActivityInner(ActivityClientRecord r, StopInfo info,
boolean saveState, boolean finalStateRequest, String reason) {
if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
if (r != null) {
- if (!keepShown && r.stopped) {
+ if (r.stopped) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain
// cases. So here we likewise don't want to call onStop()
@@ -4630,9 +4826,7 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- if (!keepShown) {
- callActivityOnStop(r, saveState, reason);
- }
+ callActivityOnStop(r, saveState, reason);
}
}
@@ -4700,20 +4894,19 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleStopActivity(IBinder token, boolean show, int configChanges,
+ public void handleStopActivity(IBinder token, int configChanges,
PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) {
final ActivityClientRecord r = mActivities.get(token);
r.activity.mConfigChangeFlags |= configChanges;
final StopInfo stopInfo = new StopInfo();
- performStopActivityInner(r, stopInfo, show, true /* saveState */, finalStateRequest,
+ performStopActivityInner(r, stopInfo, true /* saveState */, finalStateRequest,
reason);
if (localLOGV) Slog.v(
- TAG, "Finishing stop of " + r + ": show=" + show
- + " win=" + r.window);
+ TAG, "Finishing stop of " + r + ": win=" + r.window);
- updateVisibility(r, show);
+ updateVisibility(r, false);
// Make sure any pending writes are now committed.
if (!r.isPreHoneycomb()) {
@@ -4749,69 +4942,6 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- @Override
- public void handleWindowVisibility(IBinder token, boolean show) {
- ActivityClientRecord r = mActivities.get(token);
-
- if (r == null) {
- Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
- return;
- }
-
- if (!show && !r.stopped) {
- performStopActivityInner(r, null /* stopInfo */, show, false /* saveState */,
- false /* finalStateRequest */, "handleWindowVisibility");
- } else if (show && r.getLifecycleState() == ON_STOP) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
-
- r.activity.performRestart(true /* start */, "handleWindowVisibility");
- r.setState(ON_START);
- }
- if (r.activity.mDecor != null) {
- if (false) Slog.v(
- TAG, "Handle window " + r + " visibility: " + show);
- updateVisibility(r, show);
- }
- mSomeActivitiesChanged = true;
- }
-
- // TODO: This method should be changed to use {@link #performStopActivityInner} to perform to
- // stop operation on the activity to reduce code duplication and the chance of fixing a bug in
- // one place and missing the other.
- private void handleSleeping(IBinder token, boolean sleeping) {
- ActivityClientRecord r = mActivities.get(token);
-
- if (r == null) {
- Log.w(TAG, "handleSleeping: no activity for token " + token);
- return;
- }
-
- if (sleeping) {
- if (!r.stopped && !r.isPreHoneycomb()) {
- callActivityOnStop(r, true /* saveState */, "sleeping");
- }
-
- // Make sure any pending writes are now committed.
- if (!r.isPreHoneycomb()) {
- QueuedWork.waitToFinish();
- }
-
- // Tell activity manager we slept.
- try {
- ActivityTaskManager.getService().activitySlept(r.token);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- } else {
- if (r.stopped && r.activity.mVisibleFromServer) {
- r.activity.performRestart(true /* start */, "handleSleeping");
- r.setState(ON_START);
- }
- }
- }
-
private void handleSetCoreSettings(Bundle coreSettings) {
synchronized (mResourcesManager) {
mCoreSettings = coreSettings;
@@ -4832,7 +4962,7 @@ public final class ActivityThread extends ClientTransactionHandler {
View.sDebugViewAttributesApplicationPackage = mCoreSettings.getString(
Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, "");
String currentPackage = (mBoundApplication != null && mBoundApplication.appInfo != null)
- ? mBoundApplication.appInfo.packageName : "";
+ ? mBoundApplication.appInfo.packageName : "<unknown-app>";
View.sDebugViewAttributes =
mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0
|| View.sDebugViewAttributesApplicationPackage.equals(currentPackage);
@@ -5224,8 +5354,15 @@ public final class ActivityThread extends ClientTransactionHandler {
throw e.rethrowFromSystemServer();
}
+ // Save the current windowing mode to be restored and compared to the new configuration's
+ // windowing mode (needed because we update the last reported windowing mode when launching
+ // an activity and we can't tell inside performLaunchActivity whether we are relaunching)
+ final int oldWindowingMode = mLastReportedWindowingMode.getOrDefault(
+ r.activity.getActivityToken(), WINDOWING_MODE_UNDEFINED);
handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
+ mLastReportedWindowingMode.put(r.activity.getActivityToken(), oldWindowingMode);
+ handleWindowingModeChangeIfNeeded(r.activity, r.activity.mCurrentConfig);
if (pendingActions != null) {
// Only report a successful relaunch to WindowManager.
@@ -5383,7 +5520,11 @@ public final class ActivityThread extends ClientTransactionHandler {
}
final int NSVC = mServices.size();
for (int i=0; i<NSVC; i++) {
- callbacks.add(mServices.valueAt(i));
+ final ComponentCallbacks2 serviceComp = mServices.valueAt(i);
+ if (serviceComp instanceof InputMethodService) {
+ mHasImeComponent = true;
+ }
+ callbacks.add(serviceComp);
}
}
synchronized (mProviderMap) {
@@ -5407,8 +5548,8 @@ public final class ActivityThread extends ClientTransactionHandler {
*/
private void performConfigurationChangedForActivity(ActivityClientRecord r,
Configuration newBaseConfig) {
- performConfigurationChangedForActivity(r, newBaseConfig,
- r.activity.getDisplayId(), false /* movedToDifferentDisplay */);
+ performConfigurationChangedForActivity(r, newBaseConfig, r.activity.getDisplayId(),
+ false /* movedToDifferentDisplay */);
}
/**
@@ -5499,31 +5640,31 @@ public final class ActivityThread extends ClientTransactionHandler {
throw new IllegalArgumentException("Activity token not set. Is the activity attached?");
}
- boolean shouldChangeConfig = false;
+ // multi-window / pip mode changes, if any, should be sent before the configuration change
+ // callback, see also PinnedStackTests#testConfigurationChangeOrderDuringTransition
+ handleWindowingModeChangeIfNeeded(activity, newConfig);
+
+ boolean shouldReportChange = false;
if (activity.mCurrentConfig == null) {
- shouldChangeConfig = true;
+ shouldReportChange = true;
} else {
// If the new config is the same as the config this Activity is already running with and
// the override config also didn't change, then don't bother calling
// onConfigurationChanged.
final int diff = activity.mCurrentConfig.diffPublicOnly(newConfig);
-
- if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken,
+ if (diff == 0 && !movedToDifferentDisplay
+ && mResourcesManager.isSameResourcesOverrideConfig(activityToken,
amOverrideConfig)) {
- // Always send the task-level config changes. For system-level configuration, if
- // this activity doesn't handle any of the config changes, then don't bother
- // calling onConfigurationChanged as we're going to destroy it.
- if (!mUpdatingSystemConfig
- || (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
- || !REPORT_TO_ACTIVITY) {
- shouldChangeConfig = true;
- }
+ // Nothing significant, don't proceed with updating and reporting.
+ return null;
+ } else if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
+ || !REPORT_TO_ACTIVITY) {
+ // If this activity doesn't handle any of the config changes, then don't bother
+ // calling onConfigurationChanged. Otherwise, report to the activity for the
+ // changes.
+ shouldReportChange = true;
}
}
- if (!shouldChangeConfig && !movedToDifferentDisplay) {
- // Nothing significant, don't proceed with updating and reporting.
- return null;
- }
// Propagate the configuration change to ResourcesManager and Activity.
@@ -5560,7 +5701,7 @@ public final class ActivityThread extends ClientTransactionHandler {
activity.dispatchMovedToDisplay(displayId, configToReport);
}
- if (shouldChangeConfig) {
+ if (shouldReportChange) {
activity.mCalled = false;
activity.onConfigurationChanged(configToReport);
if (!activity.mCalled) {
@@ -5595,12 +5736,7 @@ public final class ActivityThread extends ClientTransactionHandler {
public void handleConfigurationChanged(Configuration config) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
mCurDefaultDisplayDpi = config.densityDpi;
- mUpdatingSystemConfig = true;
- try {
- handleConfigurationChanged(config, null /* compat */);
- } finally {
- mUpdatingSystemConfig = false;
- }
+ handleConfigurationChanged(config, null /* compat */);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -5623,6 +5759,10 @@ public final class ActivityThread extends ClientTransactionHandler {
}
if (config == null) {
+ // TODO (b/135719017): Temporary log for debugging IME service.
+ if (Build.IS_DEBUGGABLE && mHasImeComponent) {
+ Log.w(TAG, "handleConfigurationChanged for IME app but config is null");
+ }
return;
}
@@ -5644,6 +5784,12 @@ public final class ActivityThread extends ClientTransactionHandler {
mConfiguration = new Configuration();
}
if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
+ // TODO (b/135719017): Temporary log for debugging IME service.
+ if (Build.IS_DEBUGGABLE && mHasImeComponent) {
+ Log.w(TAG, "handleConfigurationChanged for IME app but config seq is obsolete "
+ + ", config=" + config
+ + ", mConfiguration=" + mConfiguration);
+ }
return;
}
@@ -5675,12 +5821,48 @@ public final class ActivityThread extends ClientTransactionHandler {
config);
} else if (!equivalent) {
performConfigurationChanged(cb, config);
+ } else {
+ // TODO (b/135719017): Temporary log for debugging IME service.
+ if (Build.IS_DEBUGGABLE && cb instanceof InputMethodService) {
+ Log.w(TAG, "performConfigurationChanged didn't callback to IME "
+ + ", configDiff=" + configDiff
+ + ", mConfiguration=" + mConfiguration);
+ }
}
}
}
}
/**
+ * Sends windowing mode change callbacks to {@link Activity} if applicable.
+ *
+ * See also {@link Activity#onMultiWindowModeChanged(boolean, Configuration)} and
+ * {@link Activity#onPictureInPictureModeChanged(boolean, Configuration)}
+ */
+ private void handleWindowingModeChangeIfNeeded(Activity activity,
+ Configuration newConfiguration) {
+ final int newWindowingMode = newConfiguration.windowConfiguration.getWindowingMode();
+ final IBinder token = activity.getActivityToken();
+ final int oldWindowingMode = mLastReportedWindowingMode.getOrDefault(token,
+ WINDOWING_MODE_UNDEFINED);
+ if (oldWindowingMode == newWindowingMode) return;
+ // PiP callback is sent before the MW one.
+ if (newWindowingMode == WINDOWING_MODE_PINNED) {
+ activity.dispatchPictureInPictureModeChanged(true, newConfiguration);
+ } else if (oldWindowingMode == WINDOWING_MODE_PINNED) {
+ activity.dispatchPictureInPictureModeChanged(false, newConfiguration);
+ }
+ final boolean wasInMultiWindowMode = WindowConfiguration.inMultiWindowMode(
+ oldWindowingMode);
+ final boolean nowInMultiWindowMode = WindowConfiguration.inMultiWindowMode(
+ newWindowingMode);
+ if (wasInMultiWindowMode != nowInMultiWindowMode) {
+ activity.dispatchMultiWindowModeChanged(nowInMultiWindowMode, newConfiguration);
+ }
+ mLastReportedWindowingMode.put(token, newWindowingMode);
+ }
+
+ /**
* Updates the application info.
*
* This only works in the system process. Must be called on the main thread.
@@ -5752,6 +5934,12 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
+ /**
+ * Sets the supplied {@code overrideConfig} as pending for the {@code activityToken}. Calling
+ * this method prevents any calls to
+ * {@link #handleActivityConfigurationChanged(IBinder, Configuration, int, boolean)} from
+ * processing any configurations older than {@code overrideConfig}.
+ */
@Override
public void updatePendingActivityConfiguration(IBinder activityToken,
Configuration overrideConfig) {
@@ -5768,12 +5956,24 @@ public final class ActivityThread extends ClientTransactionHandler {
}
synchronized (r) {
+ if (r.mPendingOverrideConfig != null
+ && !r.mPendingOverrideConfig.isOtherSeqNewer(overrideConfig)) {
+ if (DEBUG_CONFIGURATION) {
+ Slog.v(TAG, "Activity has newer configuration pending so drop this"
+ + " transaction. overrideConfig=" + overrideConfig
+ + " r.mPendingOverrideConfig=" + r.mPendingOverrideConfig);
+ }
+ return;
+ }
r.mPendingOverrideConfig = overrideConfig;
}
}
/**
- * Handle new activity configuration and/or move to a different display.
+ * Handle new activity configuration and/or move to a different display. This method is a noop
+ * if {@link #updatePendingActivityConfiguration(IBinder, Configuration)} has been called with
+ * a newer config than {@code overrideConfig}.
+ *
* @param activityToken Target activity token.
* @param overrideConfig Activity override config.
* @param displayId Id of the display where activity was moved to, -1 if there was no move and
@@ -5781,7 +5981,7 @@ public final class ActivityThread extends ClientTransactionHandler {
*/
@Override
public void handleActivityConfigurationChanged(IBinder activityToken,
- Configuration overrideConfig, int displayId) {
+ @NonNull Configuration overrideConfig, int displayId) {
ActivityClientRecord r = mActivities.get(activityToken);
// Check input params.
if (r == null || r.activity == null) {
@@ -5792,9 +5992,13 @@ public final class ActivityThread extends ClientTransactionHandler {
&& displayId != r.activity.getDisplayId();
synchronized (r) {
- if (r.mPendingOverrideConfig != null
- && !r.mPendingOverrideConfig.isOtherSeqNewer(overrideConfig)) {
- overrideConfig = r.mPendingOverrideConfig;
+ if (overrideConfig.isOtherSeqNewer(r.mPendingOverrideConfig)) {
+ if (DEBUG_CONFIGURATION) {
+ Slog.v(TAG, "Activity has newer configuration pending so drop this"
+ + " transaction. overrideConfig=" + overrideConfig
+ + " r.mPendingOverrideConfig=" + r.mPendingOverrideConfig);
+ }
+ return;
}
r.mPendingOverrideConfig = null;
}
@@ -6039,6 +6243,12 @@ public final class ActivityThread extends ClientTransactionHandler {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
+ if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
+ for (PropertyInvalidatedCache pic : PropertyInvalidatedCache.getActiveCaches()) {
+ pic.clear();
+ }
+ }
+
ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
final int N = callbacks.size();
@@ -6194,6 +6404,7 @@ public final class ActivityThread extends ClientTransactionHandler {
// send up app name; do this *before* waiting for debugger
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
+ data.appInfo.packageName,
UserHandle.myUserId());
VMRuntime.setProcessPackageName(data.appInfo.packageName);
@@ -6314,7 +6525,7 @@ public final class ActivityThread extends ClientTransactionHandler {
// Allow binder tracing, and application-generated systrace messages if we're profileable.
boolean isAppProfileable = data.appInfo.isProfileableByShell();
Trace.setAppTracingAllowed(isAppProfileable);
- if (isAppProfileable && data.enableBinderTracking) {
+ if ((isAppProfileable || Build.IS_DEBUGGABLE) && data.enableBinderTracking) {
Binder.enableTracing();
}
@@ -6352,7 +6563,8 @@ public final class ActivityThread extends ClientTransactionHandler {
final InstrumentationInfo ii;
if (data.instrumentationName != null) {
try {
- ii = new ApplicationPackageManager(null, getPackageManager())
+ ii = new ApplicationPackageManager(
+ null, getPackageManager(), getPermissionManager())
.getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
@@ -6605,7 +6817,11 @@ public final class ActivityThread extends ClientTransactionHandler {
throw ex.rethrowFromSystemServer();
}
if (holder == null) {
- Slog.e(TAG, "Failed to find provider info for " + auth);
+ if (UserManager.get(c).isUserUnlocked(userId)) {
+ Slog.e(TAG, "Failed to find provider info for " + auth);
+ } else {
+ Slog.w(TAG, "Failed to find provider info for " + auth + " (user not unlocked)");
+ }
return null;
}
@@ -7164,6 +7380,12 @@ public final class ActivityThread extends ClientTransactionHandler {
ViewRootImpl.ConfigChangedCallback configChangedCallback
= (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
+ // TODO (b/135719017): Temporary log for debugging IME service.
+ if (Build.IS_DEBUGGABLE && mHasImeComponent) {
+ Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, "
+ + "config=" + globalConfig);
+ }
+
// We need to apply this change to the resources immediately, because upon returning
// the view hierarchy will be informed about it.
if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
@@ -7210,6 +7432,10 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
+ public Bundle getCoreSettings() {
+ return mCoreSettings;
+ }
+
public int getIntCoreSetting(String key, int defaultValue) {
synchronized (mResourcesManager) {
if (mCoreSettings != null) {
@@ -7219,6 +7445,27 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
+ /**
+ * Get the string value of the given key from core settings.
+ */
+ public String getStringCoreSetting(String key, String defaultValue) {
+ synchronized (mResourcesManager) {
+ if (mCoreSettings != null) {
+ return mCoreSettings.getString(key, defaultValue);
+ }
+ return defaultValue;
+ }
+ }
+
+ float getFloatCoreSetting(String key, float defaultValue) {
+ synchronized (mResourcesManager) {
+ if (mCoreSettings != null) {
+ return mCoreSettings.getFloat(key, defaultValue);
+ }
+ return defaultValue;
+ }
+ }
+
private static class AndroidOs extends ForwardingOs {
/**
* Install selective syscall interception. For example, this is used to
@@ -7333,11 +7580,21 @@ public final class ActivityThread extends ClientTransactionHandler {
try {
super.rename(oldPath, newPath);
} catch (ErrnoException e) {
- if (e.errno == OsConstants.EXDEV) {
+ // On emulated volumes, we have bind mounts for /Android/data and
+ // /Android/obb, which prevents move from working across those directories
+ // and other directories on the filesystem. To work around that, try to
+ // recover by doing a copy instead.
+ // Note that we only do this for "/storage/emulated", because public volumes
+ // don't have these bind mounts, neither do private volumes that are not
+ // the primary storage.
+ if (e.errno == OsConstants.EXDEV && oldPath.startsWith("/storage/emulated")
+ && newPath.startsWith("/storage/emulated")) {
Log.v(TAG, "Recovering failed rename " + oldPath + " to " + newPath);
try {
- Files.move(new File(oldPath).toPath(), new File(newPath).toPath());
+ Files.move(new File(oldPath).toPath(), new File(newPath).toPath(),
+ StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e2) {
+ Log.e(TAG, "Rename recovery failed ", e);
throw e;
}
} else {
@@ -7364,6 +7621,9 @@ public final class ActivityThread extends ClientTransactionHandler {
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
+ // Call per-process mainline module initialization.
+ initializeMainlineModules();
+
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
@@ -7398,6 +7658,15 @@ public final class ActivityThread extends ClientTransactionHandler {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
+ /**
+ * Call various initializer APIs in mainline modules that need to be called when each process
+ * starts.
+ */
+ public static void initializeMainlineModules() {
+ TelephonyFrameworkInitializer.setTelephonyServiceManager(new TelephonyServiceManager());
+ StatsFrameworkInitializer.setStatsServiceManager(new StatsServiceManager());
+ }
+
private void purgePendingResources() {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "purgePendingResources");
nPurgePendingResources();