Snap for 6474498 from 8005ccfc8374dab945fb9d3509fa1760f5950e5b to mainline-release

Change-Id: I1a59765b4208f24bf955226db358a6566ef2f6d9
This commit is contained in:
android-build-team Robot
2020-05-08 07:02:24 +00:00
6 changed files with 120 additions and 67 deletions

View File

@@ -27,7 +27,7 @@ java_defaults {
"androidx.annotation_annotation",
"netd_aidl_interface-V3-java",
"netlink-client",
"networkstack-aidl-interfaces-unstable-java",
"networkstack-aidl-interfaces-java",
"android.hardware.tetheroffload.config-V1.0-java",
"android.hardware.tetheroffload.control-V1.0-java",
"net-utils-framework-common",
@@ -109,6 +109,7 @@ android_app {
manifest: "AndroidManifest_InProcess.xml",
// InProcessTethering is a replacement for Tethering
overrides: ["Tethering"],
apex_available: ["com.android.tethering"],
}
// Updatable tethering packaged as an application

View File

@@ -36,3 +36,12 @@ android_app_certificate {
name: "com.android.tethering.certificate",
certificate: "com.android.tethering",
}
override_apex {
name: "com.android.tethering.inprocess",
base: "com.android.tethering",
package_name: "com.android.tethering.inprocess",
apps: [
"InProcessTethering",
],
}

View File

@@ -45,13 +45,13 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.util.ArraySet;
import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine;
import java.io.PrintWriter;
import java.util.BitSet;
/**
* Re-check tethering provisioning for enabled downstream tether types.
@@ -74,11 +74,11 @@ public class EntitlementManager {
private final ComponentName mSilentProvisioningService;
private static final int MS_PER_HOUR = 60 * 60 * 1000;
// The ArraySet contains enabled downstream types, ex:
// The BitSet is the bit map of each enabled downstream types, ex:
// {@link TetheringManager.TETHERING_WIFI}
// {@link TetheringManager.TETHERING_USB}
// {@link TetheringManager.TETHERING_BLUETOOTH}
private final ArraySet<Integer> mCurrentTethers;
private final BitSet mCurrentDownstreams;
private final Context mContext;
private final int mPermissionChangeMessageCode;
private final SharedLog mLog;
@@ -87,9 +87,9 @@ public class EntitlementManager {
private final StateMachine mTetherMasterSM;
// Key: TetheringManager.TETHERING_*(downstream).
// Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
private final SparseIntArray mCellularPermitted;
private final SparseIntArray mCurrentEntitlementResults;
private PendingIntent mProvisioningRecheckAlarm;
private boolean mCellularUpstreamPermitted = true;
private boolean mLastCellularUpstreamPermitted = true;
private boolean mUsingCellularAsUpstream = false;
private boolean mNeedReRunProvisioningUi = false;
private OnUiEntitlementFailedListener mListener;
@@ -97,11 +97,10 @@ public class EntitlementManager {
public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
int permissionChangeMessageCode) {
mContext = ctx;
mLog = log.forSubComponent(TAG);
mCurrentTethers = new ArraySet<Integer>();
mCellularPermitted = new SparseIntArray();
mCurrentDownstreams = new BitSet();
mCurrentEntitlementResults = new SparseIntArray();
mEntitlementCacheValue = new SparseIntArray();
mTetherMasterSM = tetherMasterSM;
mPermissionChangeMessageCode = permissionChangeMessageCode;
@@ -144,13 +143,19 @@ public class EntitlementManager {
* Check if cellular upstream is permitted.
*/
public boolean isCellularUpstreamPermitted() {
// If provisioning is required and EntitlementManager don't know any downstream,
// cellular upstream should not be allowed.
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
if (mCurrentTethers.size() == 0 && isTetherProvisioningRequired(config)) {
return false;
}
return mCellularUpstreamPermitted;
return isCellularUpstreamPermitted(config);
}
private boolean isCellularUpstreamPermitted(final TetheringConfiguration config) {
if (!isTetherProvisioningRequired(config)) return true;
// If provisioning is required and EntitlementManager doesn't know any downstreams,
// cellular upstream should not be allowed.
if (mCurrentDownstreams.isEmpty()) return false;
return mCurrentEntitlementResults.indexOfValue(TETHER_ERROR_NO_ERROR) > -1;
}
/**
@@ -164,29 +169,22 @@ public class EntitlementManager {
public void startProvisioningIfNeeded(int downstreamType, boolean showProvisioningUi) {
if (!isValidDownstreamType(downstreamType)) return;
if (!mCurrentTethers.contains(downstreamType)) mCurrentTethers.add(downstreamType);
mCurrentDownstreams.set(downstreamType, true);
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
if (isTetherProvisioningRequired(config)) {
// If provisioning is required and the result is not available yet,
// cellular upstream should not be allowed.
if (mCellularPermitted.size() == 0) {
mCellularUpstreamPermitted = false;
}
// If upstream is not cellular, provisioning app would not be launched
// till upstream change to cellular.
if (mUsingCellularAsUpstream) {
if (showProvisioningUi) {
runUiTetherProvisioning(downstreamType, config.activeDataSubId);
} else {
runSilentTetherProvisioning(downstreamType, config.activeDataSubId);
}
mNeedReRunProvisioningUi = false;
if (!isTetherProvisioningRequired(config)) return;
// If upstream is not cellular, provisioning app would not be launched
// till upstream change to cellular.
if (mUsingCellularAsUpstream) {
if (showProvisioningUi) {
runUiTetherProvisioning(downstreamType, config.activeDataSubId);
} else {
mNeedReRunProvisioningUi |= showProvisioningUi;
runSilentTetherProvisioning(downstreamType, config.activeDataSubId);
}
mNeedReRunProvisioningUi = false;
} else {
mCellularUpstreamPermitted = true;
mNeedReRunProvisioningUi |= showProvisioningUi;
}
}
@@ -195,14 +193,14 @@ public class EntitlementManager {
*
* @param type tethering type from TetheringManager.TETHERING_{@code *}
*/
public void stopProvisioningIfNeeded(int type) {
if (!isValidDownstreamType(type)) return;
public void stopProvisioningIfNeeded(int downstreamType) {
if (!isValidDownstreamType(downstreamType)) return;
mCurrentTethers.remove(type);
mCurrentDownstreams.set(downstreamType, false);
// There are lurking bugs where the notion of "provisioning required" or
// "tethering supported" may change without without tethering being notified properly.
// Remove the mapping all the time no matter provisioning is required or not.
removeDownstreamMapping(type);
removeDownstreamMapping(downstreamType);
}
/**
@@ -213,7 +211,7 @@ public class EntitlementManager {
public void notifyUpstream(boolean isCellular) {
if (DBG) {
mLog.i("notifyUpstream: " + isCellular
+ ", mCellularUpstreamPermitted: " + mCellularUpstreamPermitted
+ ", mLastCellularUpstreamPermitted: " + mLastCellularUpstreamPermitted
+ ", mNeedReRunProvisioningUi: " + mNeedReRunProvisioningUi);
}
mUsingCellularAsUpstream = isCellular;
@@ -231,7 +229,7 @@ public class EntitlementManager {
}
private void maybeRunProvisioning(final TetheringConfiguration config) {
if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired(config)) {
if (mCurrentDownstreams.isEmpty() || !isTetherProvisioningRequired(config)) {
return;
}
@@ -239,8 +237,9 @@ public class EntitlementManager {
// are allowed. Therefore even if the silent check here ends in a failure and the UI later
// yields success, then the downstream that got a failure will re-evaluate as a result of
// the change and get the new correct value.
for (Integer downstream : mCurrentTethers) {
if (mCellularPermitted.indexOfKey(downstream) < 0) {
for (int downstream = mCurrentDownstreams.nextSetBit(0); downstream >= 0;
downstream = mCurrentDownstreams.nextSetBit(downstream + 1)) {
if (mCurrentEntitlementResults.indexOfKey(downstream) < 0) {
if (mNeedReRunProvisioningUi) {
mNeedReRunProvisioningUi = false;
runUiTetherProvisioning(downstream, config.activeDataSubId);
@@ -286,7 +285,7 @@ public class EntitlementManager {
mLog.log("reevaluateSimCardProvisioning() don't run in TetherMaster thread");
}
mEntitlementCacheValue.clear();
mCellularPermitted.clear();
mCurrentEntitlementResults.clear();
// TODO: refine provisioning check to isTetherProvisioningRequired() ??
if (!config.hasMobileHotspotProvisionApp()
@@ -410,22 +409,21 @@ public class EntitlementManager {
}
private void evaluateCellularPermission(final TetheringConfiguration config) {
final boolean oldPermitted = mCellularUpstreamPermitted;
mCellularUpstreamPermitted = (!isTetherProvisioningRequired(config)
|| mCellularPermitted.indexOfValue(TETHER_ERROR_NO_ERROR) > -1);
final boolean oldPermitted = mLastCellularUpstreamPermitted;
mLastCellularUpstreamPermitted = isCellularUpstreamPermitted(config);
if (DBG) {
mLog.i("Cellular permission change from " + oldPermitted
+ " to " + mCellularUpstreamPermitted);
+ " to " + mLastCellularUpstreamPermitted);
}
if (mCellularUpstreamPermitted != oldPermitted) {
mLog.log("Cellular permission change: " + mCellularUpstreamPermitted);
if (mLastCellularUpstreamPermitted != oldPermitted) {
mLog.log("Cellular permission change: " + mLastCellularUpstreamPermitted);
mTetherMasterSM.sendMessage(mPermissionChangeMessageCode);
}
// Only schedule periodic re-check when tether is provisioned
// and the result is ok.
if (mCellularUpstreamPermitted && mCellularPermitted.size() > 0) {
if (mLastCellularUpstreamPermitted && mCurrentEntitlementResults.size() > 0) {
scheduleProvisioningRechecks(config);
} else {
cancelTetherProvisioningRechecks();
@@ -441,10 +439,10 @@ public class EntitlementManager {
*/
protected void addDownstreamMapping(int type, int resultCode) {
mLog.i("addDownstreamMapping: " + type + ", result: " + resultCode
+ " ,TetherTypeRequested: " + mCurrentTethers.contains(type));
if (!mCurrentTethers.contains(type)) return;
+ " ,TetherTypeRequested: " + mCurrentDownstreams.get(type));
if (!mCurrentDownstreams.get(type)) return;
mCellularPermitted.put(type, resultCode);
mCurrentEntitlementResults.put(type, resultCode);
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
evaluateCellularPermission(config);
}
@@ -455,7 +453,7 @@ public class EntitlementManager {
*/
protected void removeDownstreamMapping(int type) {
mLog.i("removeDownstreamMapping: " + type);
mCellularPermitted.delete(type);
mCurrentEntitlementResults.delete(type);
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
evaluateCellularPermission(config);
}
@@ -488,14 +486,15 @@ public class EntitlementManager {
* @param pw {@link PrintWriter} is used to print formatted
*/
public void dump(PrintWriter pw) {
pw.print("mCellularUpstreamPermitted: ");
pw.println(mCellularUpstreamPermitted);
for (Integer type : mCurrentTethers) {
pw.print("isCellularUpstreamPermitted: ");
pw.println(isCellularUpstreamPermitted());
for (int type = mCurrentDownstreams.nextSetBit(0); type >= 0;
type = mCurrentDownstreams.nextSetBit(type + 1)) {
pw.print("Type: ");
pw.print(typeString(type));
if (mCellularPermitted.indexOfKey(type) > -1) {
if (mCurrentEntitlementResults.indexOfKey(type) > -1) {
pw.print(", Value: ");
pw.println(errorString(mCellularPermitted.get(type)));
pw.println(errorString(mCurrentEntitlementResults.get(type)));
} else {
pw.println(", Value: empty");
}

View File

@@ -62,7 +62,6 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE;
import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
@@ -268,12 +267,9 @@ public class Tethering {
mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps);
mTetherMasterSM.start();
final NetworkStatsManager statsManager =
(NetworkStatsManager) mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
mHandler = mTetherMasterSM.getHandler();
mOffloadController = new OffloadController(mHandler,
mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(),
statsManager, mLog, new OffloadController.Dependencies() {
mOffloadController = mDeps.getOffloadController(mHandler, mLog,
new OffloadController.Dependencies() {
@Override
public TetheringConfiguration getTetherConfig() {

View File

@@ -16,6 +16,7 @@
package com.android.networkstack.tethering;
import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.net.INetd;
@@ -46,6 +47,19 @@ public abstract class TetheringDependencies {
return new OffloadHardwareInterface(h, log);
}
/**
* Get a reference to the offload controller to be used by tethering.
*/
@NonNull
public OffloadController getOffloadController(@NonNull Handler h,
@NonNull SharedLog log, @NonNull OffloadController.Dependencies deps) {
final NetworkStatsManager statsManager =
(NetworkStatsManager) getContext().getSystemService(Context.NETWORK_STATS_SERVICE);
return new OffloadController(h, getOffloadHardwareInterface(h, log),
getContext().getContentResolver(), statsManager, log, deps);
}
/**
* Get a reference to the UpstreamNetworkMonitor to be used by tethering.
*/

View File

@@ -150,6 +150,8 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.util.ArrayList;
@@ -212,6 +214,9 @@ public class TetheringTest {
private Tethering mTethering;
private PhoneStateListener mPhoneStateListener;
private InterfaceConfigurationParcel mInterfaceConfiguration;
private TetheringConfiguration mConfig;
private EntitlementManager mEntitleMgr;
private OffloadController mOffloadCtrl;
private class TestContext extends BroadcastInterceptingContext {
TestContext(Context base) {
@@ -297,8 +302,9 @@ public class TetheringTest {
}
}
private class MockTetheringConfiguration extends TetheringConfiguration {
MockTetheringConfiguration(Context ctx, SharedLog log, int id) {
// MyTetheringConfiguration is used to override static method for testing.
private class MyTetheringConfiguration extends TetheringConfiguration {
MyTetheringConfiguration(Context ctx, SharedLog log, int id) {
super(ctx, log, id);
}
@@ -327,6 +333,15 @@ public class TetheringTest {
return mOffloadHardwareInterface;
}
@Override
public OffloadController getOffloadController(Handler h, SharedLog log,
OffloadController.Dependencies deps) {
mOffloadCtrl = spy(super.getOffloadController(h, log, deps));
// Return real object here instead of mock because
// testReportFailCallbackIfOffloadNotSupported depend on real OffloadController object.
return mOffloadCtrl;
}
@Override
public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
StateMachine target, SharedLog log, int what) {
@@ -351,6 +366,13 @@ public class TetheringTest {
return mNetworkRequest;
}
@Override
public EntitlementManager getEntitlementManager(Context ctx, StateMachine target,
SharedLog log, int what) {
mEntitleMgr = spy(super.getEntitlementManager(ctx, target, log, what));
return mEntitleMgr;
}
@Override
public boolean isTetheringSupported() {
return true;
@@ -359,7 +381,8 @@ public class TetheringTest {
@Override
public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log,
int subId) {
return new MockTetheringConfiguration(ctx, log, subId);
mConfig = spy(new MyTetheringConfiguration(ctx, log, subId));
return mConfig;
}
@Override
@@ -1726,6 +1749,17 @@ public class TetheringTest {
verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any());
}
@Test
public void testDumpTetheringLog() throws Exception {
final FileDescriptor mockFd = mock(FileDescriptor.class);
final PrintWriter mockPw = mock(PrintWriter.class);
runUsbTethering(null);
mTethering.dump(mockFd, mockPw, new String[0]);
verify(mConfig).dump(any());
verify(mEntitleMgr).dump(any());
verify(mOffloadCtrl).dump(any());
}
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
}