Merge "Allow enabling component-alias via device config, on userdebug or eng devices"

This commit is contained in:
Makoto Onuki
2022-02-04 16:29:32 +00:00
committed by Android (Google) Code Review
7 changed files with 165 additions and 11 deletions

View File

@@ -123,6 +123,7 @@ final class ActivityManagerConstants extends ContentObserver {
static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE = "kill_bg_restricted_cached_idle";
static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME =
"kill_bg_restricted_cached_idle_settle_time";
static final String KEY_ENABLE_COMPONENT_ALIAS = "enable_experimental_component_alias";
static final String KEY_COMPONENT_ALIAS_OVERRIDES = "component_alias_overrides";
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
@@ -199,6 +200,7 @@ final class ActivityManagerConstants extends ContentObserver {
* Whether or not to enable the extra delays to service restarts on memory pressure.
*/
private static final boolean DEFAULT_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE = true;
private static final boolean DEFAULT_ENABLE_COMPONENT_ALIAS = false;
private static final String DEFAULT_COMPONENT_ALIAS_OVERRIDES = "";
// Flag stored in the DeviceConfig API.
@@ -594,6 +596,12 @@ final class ActivityManagerConstants extends ContentObserver {
boolean mEnableExtraServiceRestartDelayOnMemPressure =
DEFAULT_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE;
/**
* Whether to enable "component alias" experimental feature. This can only be enabled
* on userdebug or eng builds.
*/
volatile boolean mEnableComponentAlias = DEFAULT_ENABLE_COMPONENT_ALIAS;
/**
* Defines component aliases. Format
* ComponentName ":" ComponentName ( "," ComponentName ":" ComponentName )*
@@ -831,6 +839,7 @@ final class ActivityManagerConstants extends ContentObserver {
case KEY_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE:
updateEnableExtraServiceRestartDelayOnMemPressure();
break;
case KEY_ENABLE_COMPONENT_ALIAS:
case KEY_COMPONENT_ALIAS_OVERRIDES:
updateComponentAliases();
break;
@@ -1269,11 +1278,15 @@ final class ActivityManagerConstants extends ContentObserver {
}
private void updateComponentAliases() {
mEnableComponentAlias = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_ENABLE_COMPONENT_ALIAS,
DEFAULT_ENABLE_COMPONENT_ALIAS);
mComponentAliasOverrides = DeviceConfig.getString(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_COMPONENT_ALIAS_OVERRIDES,
DEFAULT_COMPONENT_ALIAS_OVERRIDES);
mService.mComponentAliasResolver.update(mComponentAliasOverrides);
mService.mComponentAliasResolver.update(mEnableComponentAlias, mComponentAliasOverrides);
}
private void updateProcessKillTimeout() {
@@ -1512,6 +1525,8 @@ final class ActivityManagerConstants extends ContentObserver {
pw.print("="); pw.println(mPushMessagingOverQuotaBehavior);
pw.print(" "); pw.print(KEY_FGS_ALLOW_OPT_OUT);
pw.print("="); pw.println(mFgsAllowOptOut);
pw.print(" "); pw.print(KEY_ENABLE_COMPONENT_ALIAS);
pw.print("="); pw.println(mEnableComponentAlias);
pw.print(" "); pw.print(KEY_COMPONENT_ALIAS_OVERRIDES);
pw.print("="); pw.println(mComponentAliasOverrides);

View File

@@ -8066,7 +8066,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// Load the component aliases.
t.traceBegin("componentAlias");
mComponentAliasResolver.onSystemReady(mConstants.mComponentAliasOverrides);
mComponentAliasResolver.onSystemReady(mConstants.mEnableComponentAlias,
mConstants.mComponentAliasOverrides);
t.traceEnd(); // componentAlias
t.traceEnd(); // PhaseActivityManagerReady

View File

@@ -30,6 +30,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.os.Build;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -56,6 +57,8 @@ import java.util.function.Supplier;
* "quick & dirty". For example, to define aliases, we use a regular intent filter and meta-data
* in the manifest, instead of adding proper tags/attributes to AndroidManifest.xml.
*
* Because it's an experimental feature, it can't be enabled on a user build.
*
* Also, for now, aliases can be defined across any packages, but in the final version, there'll
* be restrictions:
* - We probably should only allow either privileged or preinstalled apps.
@@ -77,6 +80,9 @@ public class ComponentAliasResolver {
private final ActivityManagerService mAm;
private final Context mContext;
@GuardedBy("mLock")
private boolean mEnabledByDeviceConfig;
@GuardedBy("mLock")
private boolean mEnabled;
@@ -141,7 +147,7 @@ public class ComponentAliasResolver {
/**
* Call this on systemRead().
*/
public void onSystemReady(String overrides) {
public void onSystemReady(boolean enabledByDeviceConfig, String overrides) {
synchronized (mLock) {
mPlatformCompat = (PlatformCompat) ServiceManager.getService(
Context.PLATFORM_COMPAT_SERVICE);
@@ -149,19 +155,21 @@ public class ComponentAliasResolver {
mCompatChangeListener);
}
if (DEBUG) Slog.d(TAG, "Compat listener set.");
update(overrides);
update(enabledByDeviceConfig, overrides);
}
/**
* (Re-)loads aliases from <meta-data> and the device config override.
*/
public void update(String overrides) {
public void update(boolean enabledByDeviceConfig, String overrides) {
synchronized (mLock) {
if (mPlatformCompat == null) {
return; // System not ready.
}
final boolean enabled = mPlatformCompat.isChangeEnabledByPackageName(
USE_EXPERIMENTAL_COMPONENT_ALIAS, "android", UserHandle.USER_SYSTEM);
final boolean enabled = Build.isDebuggable()
&& (enabledByDeviceConfig
|| mPlatformCompat.isChangeEnabledByPackageName(
USE_EXPERIMENTAL_COMPONENT_ALIAS, "android", UserHandle.USER_SYSTEM));
if (enabled != mEnabled) {
Slog.i(TAG, (enabled ? "Enabling" : "Disabling") + " component aliases...");
if (enabled) {
@@ -172,6 +180,7 @@ public class ComponentAliasResolver {
}
}
mEnabled = enabled;
mEnabledByDeviceConfig = enabledByDeviceConfig;
mOverrideString = overrides;
if (mEnabled) {
@@ -184,7 +193,7 @@ public class ComponentAliasResolver {
private void refresh() {
synchronized (mLock) {
update(mOverrideString);
update(mEnabledByDeviceConfig, mOverrideString);
}
}

View File

@@ -21,8 +21,6 @@
<option name="test-file-name" value="ComponentAliasTests2.apk" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="am compat enable --no-kill USE_EXPERIMENTAL_COMPONENT_ALIAS android" />
<!-- Exempt the helper APKs from the BG restriction, so they can start BG services. -->
<option name="run-command" value="cmd deviceidle whitelist +android.content.componentalias.tests" />
<option name="run-command" value="cmd deviceidle whitelist +android.content.componentalias.tests.sub1" />

View File

@@ -17,6 +17,7 @@ package android.content.componentalias.tests;
import android.content.ComponentName;
import android.content.Context;
import android.os.Build;
import android.provider.DeviceConfig;
import android.util.Log;
@@ -27,6 +28,7 @@ import com.android.compatibility.common.util.ShellUtils;
import com.android.compatibility.common.util.TestUtils;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.Before;
import java.util.function.Consumer;
@@ -37,7 +39,11 @@ public class BaseComponentAliasTest {
protected static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER);
@Before
public void enableComponentAlias() throws Exception {
public void enableComponentAliasWithCompatFlag() throws Exception {
Assume.assumeTrue(Build.isDebuggable());
ShellUtils.runShellCommand(
"am compat enable --no-kill USE_EXPERIMENTAL_COMPONENT_ALIAS android");
sDeviceConfig.set("enable_experimental_component_alias", "");
sDeviceConfig.set("component_alias_overrides", "");
// Make sure the feature is actually enabled.
@@ -49,6 +55,8 @@ public class BaseComponentAliasTest {
@AfterClass
public static void restoreDeviceConfig() throws Exception {
ShellUtils.runShellCommand(
"am compat disable --no-kill USE_EXPERIMENTAL_COMPONENT_ALIAS android");
sDeviceConfig.close();
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2022 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.content.componentalias.tests;
import android.os.Build;
import android.provider.DeviceConfig;
import com.android.compatibility.common.util.DeviceConfigStateHelper;
import com.android.compatibility.common.util.ShellUtils;
import com.android.compatibility.common.util.TestUtils;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.Test;
public class ComponentAliasEnableWithDeviceConfigTest {
protected static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER);
@AfterClass
public static void restoreDeviceConfig() throws Exception {
sDeviceConfig.close();
}
@Test
public void enableComponentAliasWithCompatFlag() throws Exception {
Assume.assumeTrue(Build.isDebuggable());
sDeviceConfig.set("component_alias_overrides", "");
// First, disable with both compat-id and device config.
ShellUtils.runShellCommand(
"am compat disable --no-kill USE_EXPERIMENTAL_COMPONENT_ALIAS android");
sDeviceConfig.set("enable_experimental_component_alias", "");
TestUtils.waitUntil("Wait until component alias is actually enabled", () -> {
return ShellUtils.runShellCommand("dumpsys activity component-alias")
.indexOf("Enabled: false") > 0;
});
// Then, enable by device config.
sDeviceConfig.set("enable_experimental_component_alias", "true");
// Make sure the feature is actually enabled.
TestUtils.waitUntil("Wait until component alias is actually enabled", () -> {
return ShellUtils.runShellCommand("dumpsys activity component-alias")
.indexOf("Enabled: true") > 0;
});
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2022 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.content.componentalias.tests;
import static com.google.common.truth.Truth.assertThat;
import android.os.Build;
import android.provider.DeviceConfig;
import com.android.compatibility.common.util.DeviceConfigStateHelper;
import com.android.compatibility.common.util.ShellUtils;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.Test;
/**
* Test to make sure component-alias can't be enabled on user builds.
*/
public class ComponentAliasNotSupportedOnUserBuildTest {
protected static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER);
@AfterClass
public static void restoreDeviceConfig() throws Exception {
sDeviceConfig.close();
}
@Test
public void enableComponentAliasWithCompatFlag() throws Exception {
Assume.assumeFalse(Build.isDebuggable());
// Try to enable it by both the device config and compat-id.
sDeviceConfig.set("enable_experimental_component_alias", "true");
ShellUtils.runShellCommand(
"am compat enable --no-kill USE_EXPERIMENTAL_COMPONENT_ALIAS android");
// Sleep for an arbitrary amount of time, so the config would sink in, if there was
// no "not on user builds" check.
Thread.sleep(5000);
// Make sure the feature is still disabled.
assertThat(ShellUtils.runShellCommand("dumpsys activity component-alias")
.indexOf("Enabled: false") > 0).isTrue();
}
}