From a1b39023d8c53ec516ccb5772b75569ab4af7829 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Mon, 24 Jun 2019 12:07:22 +0100 Subject: [PATCH] Compatibility API implementation for app processes. Pass the set of disabled changes from the system server into the app in the bindApplication() call. Use this to instantiate an implementation of Compatibility.Callbacks() to implement the API. Test: Manual. Bug: 135010838 Merged-In: I2fcf25264c62acc801f9e62967072cd04e4641e7 Change-Id: I2fcf25264c62acc801f9e62967072cd04e4641e7 --- core/java/android/app/ActivityThread.java | 7 +- core/java/android/app/AppCompatCallbacks.java | 64 +++++++++++++++++++ core/java/android/app/IApplicationThread.aidl | 3 +- .../content/res/CompatibilityInfo.java | 4 +- .../TransactionParcelTests.java | 3 +- .../server/am/ActivityManagerService.java | 23 ++----- 6 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 core/java/android/app/AppCompatCallbacks.java diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index d9c82ea31537c..6c67191eb3eb1 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -703,6 +703,8 @@ public final class ActivityThread extends ClientTransactionHandler { boolean autofillCompatibilityEnabled; + long[] disabledCompatChanges; + public String toString() { return "AppBindData{appInfo=" + appInfo + "}"; } @@ -920,7 +922,8 @@ public final class ActivityThread extends ClientTransactionHandler { boolean enableBinderTracking, boolean trackAllocation, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map services, Bundle coreSettings, - String buildSerial, boolean autofillCompatibilityEnabled) { + String buildSerial, boolean autofillCompatibilityEnabled, + long[] disabledCompatChanges) { if (services != null) { if (false) { @@ -968,6 +971,7 @@ public final class ActivityThread extends ClientTransactionHandler { data.initProfilerInfo = profilerInfo; data.buildSerial = buildSerial; data.autofillCompatibilityEnabled = autofillCompatibilityEnabled; + data.disabledCompatChanges = disabledCompatChanges; sendMessage(H.BIND_APPLICATION, data); } @@ -5670,6 +5674,7 @@ public final class ActivityThread extends ClientTransactionHandler { // Note when this process has started. Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); + AppCompatCallbacks.install(data.disabledCompatChanges); mBoundApplication = data; mConfiguration = new Configuration(data.config); mCompatConfiguration = new Configuration(data.config); diff --git a/core/java/android/app/AppCompatCallbacks.java b/core/java/android/app/AppCompatCallbacks.java new file mode 100644 index 0000000000000..17697dba9ccd8 --- /dev/null +++ b/core/java/android/app/AppCompatCallbacks.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 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 android.compat.Compatibility; +import android.os.Process; +import android.util.Log; + +import java.util.Arrays; + +/** + * App process implementation of the {@link Compatibility} API. + * + * @hide + */ +public final class AppCompatCallbacks extends Compatibility.Callbacks { + + private static final String TAG = "Compatibility"; + + private final long[] mDisabledChanges; + + /** + * Install this class into the current process. + * + * @param disabledChanges Set of compatibility changes that are disabled for this process. + */ + public static void install(long[] disabledChanges) { + Compatibility.setCallbacks(new AppCompatCallbacks(disabledChanges)); + } + + private AppCompatCallbacks(long[] disabledChanges) { + mDisabledChanges = Arrays.copyOf(disabledChanges, disabledChanges.length); + Arrays.sort(mDisabledChanges); + } + + protected void reportChange(long changeId) { + Log.d(TAG, "Compat change reported: " + changeId + "; UID " + Process.myUid()); + // TODO log via StatsLog + } + + protected boolean isChangeEnabled(long changeId) { + if (Arrays.binarySearch(mDisabledChanges, changeId) < 0) { + // Not present in the disabled array + reportChange(changeId); + return true; + } + return false; + } + +} diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index d478cd6e59465..1f45fc5b8752d 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -67,7 +67,8 @@ oneway interface IApplicationThread { int debugMode, boolean enableBinderTracking, boolean trackAllocation, boolean restrictedBackupMode, boolean persistent, in Configuration config, in CompatibilityInfo compatInfo, in Map services, - in Bundle coreSettings, in String buildSerial, boolean isAutofillCompatEnabled); + in Bundle coreSettings, in String buildSerial, boolean isAutofillCompatEnabled, + in long[] disabledCompatChanges); void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs); void scheduleExit(); void scheduleServiceArgs(IBinder token, in ParceledListSlice args); diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index 7d101b8f78e54..888380b41e58c 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -32,8 +32,8 @@ import android.view.WindowManager; import android.view.WindowManager.LayoutParams; /** - * CompatibilityInfo class keeps the information about compatibility mode that the application is - * running under. + * CompatibilityInfo class keeps the information about the screen compatibility mode that the + * application is running under. * * {@hide} */ diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index d922c16a92973..b9f5ef996fc5e 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -412,7 +412,8 @@ public class TransactionParcelTests { IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1, boolean b2, boolean b3, Configuration configuration, CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1, - boolean autofillCompatEnabled) throws RemoteException { + boolean autofillCompatEnabled, long[] disableCompatChanges) + throws RemoteException { } @Override diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4eafe7c3eca0d..27ef4a7c54a8b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -452,20 +452,10 @@ import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.ThreadPriorityBooster; import com.android.server.Watchdog; -import com.android.server.am.ActivityManagerServiceDumpActivitiesProto; -import com.android.server.am.ActivityManagerServiceDumpBroadcastsProto; -import com.android.server.am.ActivityManagerServiceDumpProcessesProto; import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto; -import com.android.server.am.ActivityManagerServiceDumpServicesProto; import com.android.server.am.ActivityStack.ActivityState; -import com.android.server.am.GrantUriProto; -import com.android.server.am.ImportanceTokenProto; -import com.android.server.am.MemInfoDumpProto; import com.android.server.am.MemoryStatUtil.MemoryStat; -import com.android.server.am.NeededUriGrantsProto; -import com.android.server.am.ProcessOomProto; -import com.android.server.am.ProcessToGcProto; -import com.android.server.am.StickyBroadcastProto; +import com.android.server.compat.CompatConfig; import com.android.server.firewall.IntentFirewall; import com.android.server.job.JobSchedulerInternal; import com.android.server.pm.Installer; @@ -478,12 +468,12 @@ import com.android.server.wm.WindowManagerService; import dalvik.system.VMRuntime; -import com.google.android.collect.Lists; -import com.google.android.collect.Maps; - import libcore.io.IoUtils; import libcore.util.EmptyArray; +import com.google.android.collect.Lists; +import com.google.android.collect.Maps; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -7673,6 +7663,7 @@ public class ActivityManagerService extends IActivityManager.Stub checkTime(startTime, "attachApplicationLocked: immediately before bindApplication"); bindApplicationTimeMillis = SystemClock.elapsedRealtime(); mStackSupervisor.getActivityMetricsLogger().notifyBindApplication(app); + long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info); if (app.isolatedEntryPoint != null) { // This is an isolated process which should just call an entry point instead of // being bound to an application. @@ -7688,7 +7679,7 @@ public class ActivityManagerService extends IActivityManager.Stub new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), - buildSerial, isAutofillCompatEnabled); + buildSerial, isAutofillCompatEnabled, disabledCompatChanges); } else { thread.bindApplication(processName, appInfo, providers, null, profilerInfo, null, null, null, testMode, @@ -7697,7 +7688,7 @@ public class ActivityManagerService extends IActivityManager.Stub new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), - buildSerial, isAutofillCompatEnabled); + buildSerial, isAutofillCompatEnabled, disabledCompatChanges); } if (profilerInfo != null) { profilerInfo.closeFd();