Merge "Set attributionTag for noteOp(WRITE_SETTINGS) calls"

This commit is contained in:
Philip P. Moltmann
2020-04-22 14:58:13 +00:00
committed by Gerrit Code Review
4 changed files with 101 additions and 58 deletions

View File

@@ -22,25 +22,31 @@ import android.os.ResultReceiver;
/** @hide */ /** @hide */
oneway interface ITetheringConnector { oneway interface ITetheringConnector {
void tether(String iface, String callerPkg, IIntResultListener receiver); void tether(String iface, String callerPkg, String callingAttributionTag,
void untether(String iface, String callerPkg, IIntResultListener receiver);
void setUsbTethering(boolean enable, String callerPkg, IIntResultListener receiver);
void startTethering(in TetheringRequestParcel request, String callerPkg,
IIntResultListener receiver); IIntResultListener receiver);
void stopTethering(int type, String callerPkg, IIntResultListener receiver); void untether(String iface, String callerPkg, String callingAttributionTag,
IIntResultListener receiver);
void setUsbTethering(boolean enable, String callerPkg,
String callingAttributionTag, IIntResultListener receiver);
void startTethering(in TetheringRequestParcel request, String callerPkg,
String callingAttributionTag, IIntResultListener receiver);
void stopTethering(int type, String callerPkg, String callingAttributionTag,
IIntResultListener receiver);
void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver, void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
boolean showEntitlementUi, String callerPkg); boolean showEntitlementUi, String callerPkg, String callingAttributionTag);
void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg); void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg); void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
void isTetheringSupported(String callerPkg, IIntResultListener receiver); void isTetheringSupported(String callerPkg, String callingAttributionTag,
IIntResultListener receiver);
void stopAllTethering(String callerPkg, IIntResultListener receiver); void stopAllTethering(String callerPkg, String callingAttributionTag,
IIntResultListener receiver);
} }

View File

@@ -484,13 +484,20 @@ public class TetheringManager {
return dispatcher.waitForResult((connector, listener) -> { return dispatcher.waitForResult((connector, listener) -> {
try { try {
connector.tether(iface, callerPkg, listener); connector.tether(iface, callerPkg, getAttributionTag(), listener);
} catch (RemoteException e) { } catch (RemoteException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
}); });
} }
/**
* @return the context's attribution tag
*/
private @Nullable String getAttributionTag() {
return null;
}
/** /**
* Stop tethering the named interface. * Stop tethering the named interface.
* *
@@ -509,7 +516,7 @@ public class TetheringManager {
return dispatcher.waitForResult((connector, listener) -> { return dispatcher.waitForResult((connector, listener) -> {
try { try {
connector.untether(iface, callerPkg, listener); connector.untether(iface, callerPkg, getAttributionTag(), listener);
} catch (RemoteException e) { } catch (RemoteException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
@@ -536,7 +543,8 @@ public class TetheringManager {
return dispatcher.waitForResult((connector, listener) -> { return dispatcher.waitForResult((connector, listener) -> {
try { try {
connector.setUsbTethering(enable, callerPkg, listener); connector.setUsbTethering(enable, callerPkg, getAttributionTag(),
listener);
} catch (RemoteException e) { } catch (RemoteException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
@@ -735,7 +743,8 @@ public class TetheringManager {
}); });
} }
}; };
getConnector(c -> c.startTethering(request.getParcel(), callerPkg, listener)); getConnector(c -> c.startTethering(request.getParcel(), callerPkg,
getAttributionTag(), listener));
} }
/** /**
@@ -775,7 +784,8 @@ public class TetheringManager {
final String callerPkg = mContext.getOpPackageName(); final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "stopTethering caller:" + callerPkg); Log.i(TAG, "stopTethering caller:" + callerPkg);
getConnector(c -> c.stopTethering(type, callerPkg, new IIntResultListener.Stub() { getConnector(c -> c.stopTethering(type, callerPkg, getAttributionTag(),
new IIntResultListener.Stub() {
@Override @Override
public void onResult(int resultCode) { public void onResult(int resultCode) {
// TODO: provide an API to obtain result // TODO: provide an API to obtain result
@@ -861,7 +871,7 @@ public class TetheringManager {
Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg); Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg);
getConnector(c -> c.requestLatestTetheringEntitlementResult( getConnector(c -> c.requestLatestTetheringEntitlementResult(
type, receiver, showEntitlementUi, callerPkg)); type, receiver, showEntitlementUi, callerPkg, getAttributionTag()));
} }
/** /**
@@ -1312,7 +1322,7 @@ public class TetheringManager {
final RequestDispatcher dispatcher = new RequestDispatcher(); final RequestDispatcher dispatcher = new RequestDispatcher();
final int ret = dispatcher.waitForResult((connector, listener) -> { final int ret = dispatcher.waitForResult((connector, listener) -> {
try { try {
connector.isTetheringSupported(callerPkg, listener); connector.isTetheringSupported(callerPkg, getAttributionTag(), listener);
} catch (RemoteException e) { } catch (RemoteException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
@@ -1335,14 +1345,15 @@ public class TetheringManager {
final String callerPkg = mContext.getOpPackageName(); final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "stopAllTethering caller:" + callerPkg); Log.i(TAG, "stopAllTethering caller:" + callerPkg);
getConnector(c -> c.stopAllTethering(callerPkg, new IIntResultListener.Stub() { getConnector(c -> c.stopAllTethering(callerPkg, getAttributionTag(),
@Override new IIntResultListener.Stub() {
public void onResult(int resultCode) { @Override
// TODO: add an API parameter to send result to caller. public void onResult(int resultCode) {
// This has never been possible as stopAllTethering has always been void and never // TODO: add an API parameter to send result to caller.
// taken a callback object. The only indication that callers have is if the call // This has never been possible as stopAllTethering has always been void
// results in a TETHER_STATE_CHANGE broadcast. // and never taken a callback object. The only indication that callers have
} // is if the call results in a TETHER_STATE_CHANGE broadcast.
})); }
}));
} }
} }

View File

@@ -119,8 +119,9 @@ public class TetheringService extends Service {
} }
@Override @Override
public void tether(String iface, String callerPkg, IIntResultListener listener) { public void tether(String iface, String callerPkg, String callingAttributionTag,
if (checkAndNotifyCommonError(callerPkg, listener)) return; IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
try { try {
listener.onResult(mTethering.tether(iface)); listener.onResult(mTethering.tether(iface));
@@ -128,8 +129,9 @@ public class TetheringService extends Service {
} }
@Override @Override
public void untether(String iface, String callerPkg, IIntResultListener listener) { public void untether(String iface, String callerPkg, String callingAttributionTag,
if (checkAndNotifyCommonError(callerPkg, listener)) return; IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
try { try {
listener.onResult(mTethering.untether(iface)); listener.onResult(mTethering.untether(iface));
@@ -137,8 +139,9 @@ public class TetheringService extends Service {
} }
@Override @Override
public void setUsbTethering(boolean enable, String callerPkg, IIntResultListener listener) { public void setUsbTethering(boolean enable, String callerPkg, String callingAttributionTag,
if (checkAndNotifyCommonError(callerPkg, listener)) return; IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
try { try {
listener.onResult(mTethering.setUsbTethering(enable)); listener.onResult(mTethering.setUsbTethering(enable));
@@ -147,15 +150,16 @@ public class TetheringService extends Service {
@Override @Override
public void startTethering(TetheringRequestParcel request, String callerPkg, public void startTethering(TetheringRequestParcel request, String callerPkg,
IIntResultListener listener) { String callingAttributionTag, IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg, listener)) return; if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
mTethering.startTethering(request, listener); mTethering.startTethering(request, listener);
} }
@Override @Override
public void stopTethering(int type, String callerPkg, IIntResultListener listener) { public void stopTethering(int type, String callerPkg, String callingAttributionTag,
if (checkAndNotifyCommonError(callerPkg, listener)) return; IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
try { try {
mTethering.stopTethering(type); mTethering.stopTethering(type);
@@ -165,8 +169,8 @@ public class TetheringService extends Service {
@Override @Override
public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver, public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
boolean showEntitlementUi, String callerPkg) { boolean showEntitlementUi, String callerPkg, String callingAttributionTag) {
if (checkAndNotifyCommonError(callerPkg, receiver)) return; if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, receiver)) return;
mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi); mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
} }
@@ -196,8 +200,9 @@ public class TetheringService extends Service {
} }
@Override @Override
public void stopAllTethering(String callerPkg, IIntResultListener listener) { public void stopAllTethering(String callerPkg, String callingAttributionTag,
if (checkAndNotifyCommonError(callerPkg, listener)) return; IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
try { try {
mTethering.untetherAll(); mTethering.untetherAll();
@@ -206,8 +211,9 @@ public class TetheringService extends Service {
} }
@Override @Override
public void isTetheringSupported(String callerPkg, IIntResultListener listener) { public void isTetheringSupported(String callerPkg, String callingAttributionTag,
if (checkAndNotifyCommonError(callerPkg, listener)) return; IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
try { try {
listener.onResult(TETHER_ERROR_NO_ERROR); listener.onResult(TETHER_ERROR_NO_ERROR);
@@ -220,9 +226,10 @@ public class TetheringService extends Service {
mTethering.dump(fd, writer, args); mTethering.dump(fd, writer, args);
} }
private boolean checkAndNotifyCommonError(String callerPkg, IIntResultListener listener) { private boolean checkAndNotifyCommonError(String callerPkg, String callingAttributionTag,
IIntResultListener listener) {
try { try {
if (!mService.hasTetherChangePermission(callerPkg)) { if (!mService.hasTetherChangePermission(callerPkg, callingAttributionTag)) {
listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
return true; return true;
} }
@@ -237,8 +244,9 @@ public class TetheringService extends Service {
return false; return false;
} }
private boolean checkAndNotifyCommonError(String callerPkg, ResultReceiver receiver) { private boolean checkAndNotifyCommonError(String callerPkg, String callingAttributionTag,
if (!mService.hasTetherChangePermission(callerPkg)) { ResultReceiver receiver) {
if (!mService.hasTetherChangePermission(callerPkg, callingAttributionTag)) {
receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null); receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null);
return true; return true;
} }
@@ -266,7 +274,7 @@ public class TetheringService extends Service {
return tetherEnabledInSettings && mTethering.hasTetherableConfiguration(); return tetherEnabledInSettings && mTethering.hasTetherableConfiguration();
} }
private boolean hasTetherChangePermission(String callerPkg) { private boolean hasTetherChangePermission(String callerPkg, String callingAttributionTag) {
if (checkCallingOrSelfPermission( if (checkCallingOrSelfPermission(
android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) { android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {
return true; return true;
@@ -278,14 +286,28 @@ public class TetheringService extends Service {
int uid = Binder.getCallingUid(); int uid = Binder.getCallingUid();
// If callerPkg's uid is not same as Binder.getCallingUid(), // If callerPkg's uid is not same as Binder.getCallingUid(),
// checkAndNoteWriteSettingsOperation will return false and the operation will be denied. // checkAndNoteWriteSettingsOperation will return false and the operation will be denied.
if (Settings.checkAndNoteWriteSettingsOperation(mContext, uid, callerPkg, if (checkAndNoteWriteSettingsOperation(mContext, uid, callerPkg,
false /* throwException */)) { callingAttributionTag, false /* throwException */)) {
return true; return true;
} }
return false; return false;
} }
/**
* Check if the package is a allowed to write settings. This also accounts that such an access
* happened.
*
* @return {@code true} iff the package is allowed to write settings.
*/
// TODO: Remove method and replace with direct call once R code is pushed to AOSP
private static boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
@NonNull String callingPackage, @Nullable String callingAttributionTag,
boolean throwException) {
return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
throwException);
}
private boolean hasTetherAccessPermission() { private boolean hasTetherAccessPermission() {
if (checkCallingOrSelfPermission( if (checkCallingOrSelfPermission(
android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) { android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {

View File

@@ -52,6 +52,7 @@ import org.mockito.MockitoAnnotations;
public final class TetheringServiceTest { public final class TetheringServiceTest {
private static final String TEST_IFACE_NAME = "test_wlan0"; private static final String TEST_IFACE_NAME = "test_wlan0";
private static final String TEST_CALLER_PKG = "test_pkg"; private static final String TEST_CALLER_PKG = "test_pkg";
private static final String TEST_ATTRIBUTION_TAG = null;
@Mock private ITetheringEventCallback mITetheringEventCallback; @Mock private ITetheringEventCallback mITetheringEventCallback;
@Rule public ServiceTestRule mServiceTestRule; @Rule public ServiceTestRule mServiceTestRule;
private Tethering mTethering; private Tethering mTethering;
@@ -95,7 +96,7 @@ public final class TetheringServiceTest {
public void testTether() throws Exception { public void testTether() throws Exception {
when(mTethering.tether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR); when(mTethering.tether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
final TestTetheringResult result = new TestTetheringResult(); final TestTetheringResult result = new TestTetheringResult();
mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, result); mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
verify(mTethering).hasTetherableConfiguration(); verify(mTethering).hasTetherableConfiguration();
verify(mTethering).tether(TEST_IFACE_NAME); verify(mTethering).tether(TEST_IFACE_NAME);
verifyNoMoreInteractions(mTethering); verifyNoMoreInteractions(mTethering);
@@ -106,7 +107,8 @@ public final class TetheringServiceTest {
public void testUntether() throws Exception { public void testUntether() throws Exception {
when(mTethering.untether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR); when(mTethering.untether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
final TestTetheringResult result = new TestTetheringResult(); final TestTetheringResult result = new TestTetheringResult();
mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, result); mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
result);
verify(mTethering).hasTetherableConfiguration(); verify(mTethering).hasTetherableConfiguration();
verify(mTethering).untether(TEST_IFACE_NAME); verify(mTethering).untether(TEST_IFACE_NAME);
verifyNoMoreInteractions(mTethering); verifyNoMoreInteractions(mTethering);
@@ -117,7 +119,8 @@ public final class TetheringServiceTest {
public void testSetUsbTethering() throws Exception { public void testSetUsbTethering() throws Exception {
when(mTethering.setUsbTethering(true /* enable */)).thenReturn(TETHER_ERROR_NO_ERROR); when(mTethering.setUsbTethering(true /* enable */)).thenReturn(TETHER_ERROR_NO_ERROR);
final TestTetheringResult result = new TestTetheringResult(); final TestTetheringResult result = new TestTetheringResult();
mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG, result); mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
TEST_ATTRIBUTION_TAG, result);
verify(mTethering).hasTetherableConfiguration(); verify(mTethering).hasTetherableConfiguration();
verify(mTethering).setUsbTethering(true /* enable */); verify(mTethering).setUsbTethering(true /* enable */);
verifyNoMoreInteractions(mTethering); verifyNoMoreInteractions(mTethering);
@@ -129,7 +132,7 @@ public final class TetheringServiceTest {
final TestTetheringResult result = new TestTetheringResult(); final TestTetheringResult result = new TestTetheringResult();
final TetheringRequestParcel request = new TetheringRequestParcel(); final TetheringRequestParcel request = new TetheringRequestParcel();
request.tetheringType = TETHERING_WIFI; request.tetheringType = TETHERING_WIFI;
mTetheringConnector.startTethering(request, TEST_CALLER_PKG, result); mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
verify(mTethering).hasTetherableConfiguration(); verify(mTethering).hasTetherableConfiguration();
verify(mTethering).startTethering(eq(request), eq(result)); verify(mTethering).startTethering(eq(request), eq(result));
verifyNoMoreInteractions(mTethering); verifyNoMoreInteractions(mTethering);
@@ -138,7 +141,8 @@ public final class TetheringServiceTest {
@Test @Test
public void testStopTethering() throws Exception { public void testStopTethering() throws Exception {
final TestTetheringResult result = new TestTetheringResult(); final TestTetheringResult result = new TestTetheringResult();
mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG, result); mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
result);
verify(mTethering).hasTetherableConfiguration(); verify(mTethering).hasTetherableConfiguration();
verify(mTethering).stopTethering(TETHERING_WIFI); verify(mTethering).stopTethering(TETHERING_WIFI);
verifyNoMoreInteractions(mTethering); verifyNoMoreInteractions(mTethering);
@@ -149,7 +153,7 @@ public final class TetheringServiceTest {
public void testRequestLatestTetheringEntitlementResult() throws Exception { public void testRequestLatestTetheringEntitlementResult() throws Exception {
final ResultReceiver result = new ResultReceiver(null); final ResultReceiver result = new ResultReceiver(null);
mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result, mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
true /* showEntitlementUi */, TEST_CALLER_PKG); true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
verify(mTethering).hasTetherableConfiguration(); verify(mTethering).hasTetherableConfiguration();
verify(mTethering).requestLatestTetheringEntitlementResult(eq(TETHERING_WIFI), verify(mTethering).requestLatestTetheringEntitlementResult(eq(TETHERING_WIFI),
eq(result), eq(true) /* showEntitlementUi */); eq(result), eq(true) /* showEntitlementUi */);
@@ -176,7 +180,7 @@ public final class TetheringServiceTest {
@Test @Test
public void testStopAllTethering() throws Exception { public void testStopAllTethering() throws Exception {
final TestTetheringResult result = new TestTetheringResult(); final TestTetheringResult result = new TestTetheringResult();
mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, result); mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
verify(mTethering).hasTetherableConfiguration(); verify(mTethering).hasTetherableConfiguration();
verify(mTethering).untetherAll(); verify(mTethering).untetherAll();
verifyNoMoreInteractions(mTethering); verifyNoMoreInteractions(mTethering);
@@ -186,7 +190,7 @@ public final class TetheringServiceTest {
@Test @Test
public void testIsTetheringSupported() throws Exception { public void testIsTetheringSupported() throws Exception {
final TestTetheringResult result = new TestTetheringResult(); final TestTetheringResult result = new TestTetheringResult();
mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, result); mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
verify(mTethering).hasTetherableConfiguration(); verify(mTethering).hasTetherableConfiguration();
verifyNoMoreInteractions(mTethering); verifyNoMoreInteractions(mTethering);
result.assertResult(TETHER_ERROR_NO_ERROR); result.assertResult(TETHER_ERROR_NO_ERROR);