Merge "Create ServiceConnectivityResources"

This commit is contained in:
Remi NGUYEN VAN
2021-03-16 02:29:31 +00:00
committed by Gerrit Code Review
10 changed files with 289 additions and 22 deletions

View File

@@ -60,6 +60,7 @@ java_library {
"services.core",
"services.net",
"unsupportedappusage",
"ServiceConnectivityResources",
],
static_libs: [
"modules-utils-os",

View File

@@ -0,0 +1,35 @@
//
// Copyright (C) 2021 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.
//
// APK to hold all the wifi overlayable resources.
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
android_app {
name: "ServiceConnectivityResources",
sdk_version: "system_current",
resource_dirs: [
"res",
],
privileged: true,
export_package_resources: true,
apex_available: [
"com.android.tethering",
],
// TODO: use a dedicated cert once generated
certificate: "platform",
}

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2021 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.
*/
-->
<!-- Manifest for connectivity resources APK -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.connectivity.resources"
coreApp="true"
android:versionCode="1"
android:versionName="S-initial">
<application
android:label="@string/connectivityResourcesAppLabel"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
<!-- This is only used to identify this app by resolving the action.
The activity is never actually triggered. -->
<activity android:name="android.app.Activity" android:exported="true" android:enabled="true">
<intent-filter>
<action android:name="com.android.server.connectivity.intent.action.SERVICE_CONNECTIVITY_RESOURCES_APK" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<!-- Configuration values for ConnectivityService
DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources
Overlay package following the overlayable.xml configuration in the same directory:
https://source.android.com/devices/architecture/rros -->
<resources>
<!-- Configuration hook for the URL returned by ConnectivityManager#getCaptivePortalServerUrl.
If empty, the returned value is controlled by Settings.Global.CAPTIVE_PORTAL_HTTP_URL,
and if that value is empty, the framework will use a hard-coded default.
This is *NOT* a URL that will always be used by the system network validation to detect
captive portals: NetworkMonitor may use different strategies and will not necessarily use
this URL. NetworkMonitor behaviour should be configured with NetworkStack resource overlays
instead. -->
<!--suppress CheckTagEmptyBody -->
<string translatable="false" name="config_networkCaptivePortalServerUrl"></string>
<!-- The maximum duration (in milliseconds) we expect a network transition to take -->
<integer name="config_networkTransitionTimeout">60000</integer>
<!-- Configuration of network interfaces that support WakeOnLAN -->
<string-array translatable="false" name="config_wakeonlan_supported_interfaces">
<!--
<item>wlan0</item>
<item>eth0</item>
-->
</string-array>
</resources>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright (C) 2021 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.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<overlayable name="ServiceConnectivityResourcesConfig">
<policy type="product|system|vendor">
<!-- Configuration values for ConnectivityService -->
<item type="string" name="config_networkCaptivePortalServerUrl"/>
<item type="integer" name="config_networkTransitionTimeout"/>
<item type="array" name="config_wakeonlan_supported_interfaces"/>
</policy>
</overlayable>
</resources>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<resources>
<!-- The System Connectivity Resources package is an internal system package that provides
configuration values for system networking that were pre-configured in the device. This
is the name of the package to display in the list of system apps. [CHAR LIMIT=40] -->
<string name="connectivityResourcesAppLabel">System Connectivity Resources</string>
</resources>

View File

@@ -188,7 +188,6 @@ import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.connectivity.aidl.INetworkAgent;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
@@ -202,6 +201,7 @@ import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.PermissionUtils;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.ConnectivityResources;
import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
import com.android.server.connectivity.KeepaliveTracker;
@@ -317,6 +317,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private boolean mRestrictBackground;
private final Context mContext;
private final ConnectivityResources mResources;
// The Context is created for UserHandle.ALL.
private final Context mUserAllContext;
private final Dependencies mDeps;
@@ -604,7 +605,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
private Intent mInitialBroadcast;
private PowerManager.WakeLock mNetTransitionWakeLock;
private int mNetTransitionWakeLockTimeout;
private final PowerManager.WakeLock mPendingIntentWakeLock;
// A helper object to track the current default HTTP proxy. ConnectivityService needs to tell
@@ -1011,6 +1011,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
return new MockableSystemProperties();
}
/**
* Get the {@link ConnectivityResources} to use in ConnectivityService.
*/
public ConnectivityResources getResources(@NonNull Context ctx) {
return new ConnectivityResources(ctx);
}
/**
* Create a HandlerThread to use in ConnectivityService.
*/
@@ -1093,6 +1100,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mSystemProperties = mDeps.getSystemProperties();
mNetIdManager = mDeps.makeNetIdManager();
mContext = Objects.requireNonNull(context, "missing Context");
mResources = deps.getResources(mContext);
mNetworkRequestCounter = new PerUidCounter(MAX_NETWORK_REQUESTS_PER_UID);
mMetricsLog = logger;
@@ -1154,8 +1162,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
final PowerManager powerManager = (PowerManager) context.getSystemService(
Context.POWER_SERVICE);
mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
com.android.internal.R.integer.config_networkTransitionTimeout);
mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
@@ -1222,10 +1228,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
mWolSupportedInterfaces = new ArraySet(
mContext.getResources().getStringArray(
com.android.internal.R.array.config_wakeonlan_supported_interfaces));
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
@@ -4601,7 +4603,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
mWakelockLogs.log("ACQUIRE for " + forWhom);
Message msg = mHandler.obtainMessage(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
mHandler.sendMessageDelayed(msg, mNetTransitionWakeLockTimeout);
final int lockTimeout = mResources.get().getInteger(
com.android.connectivity.resources.R.integer.config_networkTransitionTimeout);
mHandler.sendMessageDelayed(msg, lockTimeout);
}
// Called when we gain a new default network to release the network transition wakelock in a
@@ -6515,6 +6519,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void updateWakeOnLan(@NonNull LinkProperties lp) {
if (mWolSupportedInterfaces == null) {
mWolSupportedInterfaces = new ArraySet<>(mResources.get().getStringArray(
com.android.connectivity.resources.R.array
.config_wakeonlan_supported_interfaces));
}
lp.setWakeOnLanSupported(mWolSupportedInterfaces.contains(lp.getInterfaceName()));
}
@@ -8076,8 +8085,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public String getCaptivePortalServerUrl() {
enforceNetworkStackOrSettingsPermission();
String settingUrl = mContext.getResources().getString(
R.string.config_networkCaptivePortalServerUrl);
String settingUrl = mResources.get().getString(
com.android.connectivity.resources.R.string.config_networkCaptivePortalServerUrl);
if (!TextUtils.isEmpty(settingUrl)) {
return settingUrl;

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2021 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 com.android.server.connectivity;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.util.Log;
import com.android.server.ConnectivityService;
import java.util.List;
/**
* Utility to obtain the {@link ConnectivityService} {@link Resources}, in the
* ServiceConnectivityResources APK.
*/
public class ConnectivityResources {
private static final String RESOURCES_APK_INTENT =
"com.android.server.connectivity.intent.action.SERVICE_CONNECTIVITY_RESOURCES_APK";
private static final String RES_PKG_DIR = "/apex/com.android.tethering/";
@NonNull
private final Context mContext;
@Nullable
private Resources mResources = null;
public ConnectivityResources(Context context) {
mContext = context;
}
/**
* Get the {@link Resources} of the ServiceConnectivityResources APK.
*/
public synchronized Resources get() {
if (mResources != null) {
return mResources;
}
final List<ResolveInfo> pkgs = mContext.getPackageManager()
.queryIntentActivities(new Intent(RESOURCES_APK_INTENT), MATCH_SYSTEM_ONLY);
pkgs.removeIf(pkg -> !pkg.activityInfo.applicationInfo.sourceDir.startsWith(RES_PKG_DIR));
if (pkgs.size() > 1) {
Log.wtf(ConnectivityResources.class.getSimpleName(),
"More than one package found: " + pkgs);
}
if (pkgs.isEmpty()) {
throw new IllegalStateException("No connectivity resource package found");
}
final Context pkgContext;
try {
pkgContext = mContext.createPackageContext(
pkgs.get(0).activityInfo.applicationInfo.packageName, 0 /* flags */);
} catch (PackageManager.NameNotFoundException e) {
throw new IllegalStateException("Resolved package not found", e);
}
mResources = pkgContext.getResources();
return mResources;
}
}

View File

@@ -79,6 +79,7 @@ android_test {
"android.test.runner",
"android.test.base",
"android.test.mock",
"ServiceConnectivityResources",
],
jni_libs: [
"libservice-connectivity",

View File

@@ -275,6 +275,7 @@ import com.android.internal.util.test.FakeSettingsProvider;
import com.android.net.module.util.ArrayTrackRecord;
import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
import com.android.server.connectivity.ConnectivityConstants;
import com.android.server.connectivity.ConnectivityResources;
import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.Nat464Xlat;
import com.android.server.connectivity.NetworkAgentInfo;
@@ -444,6 +445,7 @@ public class ConnectivityServiceTest {
@Mock NetworkPolicyManager mNetworkPolicyManager;
@Mock VpnProfileStore mVpnProfileStore;
@Mock SystemConfigManager mSystemConfigManager;
@Mock Resources mResources;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -471,7 +473,7 @@ public class ConnectivityServiceTest {
private class MockContext extends BroadcastInterceptingContext {
private final MockContentResolver mContentResolver;
@Spy private Resources mResources;
@Spy private Resources mInternalResources;
private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
// Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
@@ -480,21 +482,15 @@ public class ConnectivityServiceTest {
MockContext(Context base, ContentProvider settingsProvider) {
super(base);
mResources = spy(base.getResources());
when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
thenReturn(new String[] {
mInternalResources = spy(base.getResources());
when(mInternalResources.getStringArray(com.android.internal.R.array.networkAttributes))
.thenReturn(new String[] {
"wifi,1,1,1,-1,true",
"mobile,0,0,0,-1,true",
"mobile_mms,2,0,2,60000,true",
"mobile_supl,3,0,2,60000,true",
});
when(mResources.getStringArray(
com.android.internal.R.array.config_wakeonlan_supported_interfaces))
.thenReturn(new String[]{
WIFI_WOL_IFNAME,
});
mContentResolver = new MockContentResolver();
mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
}
@@ -559,7 +555,7 @@ public class ConnectivityServiceTest {
@Override
public Resources getResources() {
return mResources;
return mInternalResources;
}
@Override
@@ -1534,6 +1530,17 @@ public class ConnectivityServiceTest {
}).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
doReturn(true).when(deps).getCellular464XlatEnabled();
doReturn(60000).when(mResources).getInteger(
com.android.connectivity.resources.R.integer.config_networkTransitionTimeout);
doReturn("").when(mResources).getString(
com.android.connectivity.resources.R.string.config_networkCaptivePortalServerUrl);
doReturn(new String[]{ WIFI_WOL_IFNAME }).when(mResources).getStringArray(
com.android.connectivity.resources.R.array.config_wakeonlan_supported_interfaces);
final com.android.server.connectivity.ConnectivityResources connRes = mock(
ConnectivityResources.class);
doReturn(mResources).when(connRes).get();
doReturn(connRes).when(deps).getResources(any());
return deps;
}