Loading src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java +105 −13 Original line number Diff line number Diff line Loading @@ -16,10 +16,18 @@ package com.android.internal.telephony.dataconnection; import static android.telephony.AccessNetworkConstants.TransportType.WLAN; import static android.telephony.AccessNetworkConstants.TransportType.WWAN; import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.LinkProperties; import android.os.AsyncResult; import android.os.Handler; Loading @@ -28,7 +36,7 @@ import android.os.Message; import android.os.PersistableBundle; import android.os.RegistrantList; import android.os.RemoteException; import android.telephony.AccessNetworkConstants; import android.os.ServiceManager; import android.telephony.CarrierConfigManager; import android.telephony.Rlog; import android.telephony.data.DataCallResponse; Loading @@ -41,8 +49,10 @@ import android.text.TextUtils; import com.android.internal.telephony.Phone; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** Loading @@ -58,6 +68,8 @@ public class DataServiceManager { private final Phone mPhone; private final CarrierConfigManager mCarrierConfigManager; private final AppOpsManager mAppOps; private final IPackageManager mPackageManager; private final int mTransportType; Loading @@ -73,14 +85,10 @@ public class DataServiceManager { private final RegistrantList mDataCallListChangedRegistrants = new RegistrantList(); private class DataServiceManagerDeathRecipient implements IBinder.DeathRecipient { private final ComponentName mComponentName; DataServiceManagerDeathRecipient(ComponentName name) { mComponentName = name; } // not final because it is set by the onServiceConnected method private ComponentName mComponentName; private class DataServiceManagerDeathRecipient implements IBinder.DeathRecipient { @Override public void binderDied() { // TODO: try to rebind the service. Loading @@ -89,12 +97,53 @@ public class DataServiceManager { } } private void grantPermissionsToService(String packageName) { final String[] pkgToGrant = {packageName}; try { mPackageManager.grantDefaultPermissionsToEnabledTelephonyDataServices( pkgToGrant, mPhone.getContext().getUserId()); mAppOps.setMode(AppOpsManager.OP_MANAGE_IPSEC_TUNNELS, mPhone.getContext().getUserId(), pkgToGrant[0], AppOpsManager.MODE_ALLOWED); } catch (RemoteException e) { loge("Binder to package manager died, permission grant for DataService failed."); throw e.rethrowAsRuntimeException(); } } /** * Loop through all DataServices installed on the system and revoke permissions from any that * are not currently the WWAN or WLAN data service. */ private void revokePermissionsFromUnusedDataServices() { // Except the current data services from having their permissions removed. Set<String> dataServices = getAllDataServicePackageNames(); for (int transportType : new int[] {WWAN, WLAN}) { dataServices.remove(getDataServicePackageName(transportType)); } try { String[] dataServicesArray = new String[dataServices.size()]; dataServices.toArray(dataServicesArray); mPackageManager.revokeDefaultPermissionsFromDisabledTelephonyDataServices( dataServicesArray, mPhone.getContext().getUserId()); for (String pkg : dataServices) { mAppOps.setMode(AppOpsManager.OP_MANAGE_IPSEC_TUNNELS, mPhone.getContext().getUserId(), pkg, AppOpsManager.MODE_ERRORED); } } catch (RemoteException e) { loge("Binder to package manager died; failed to revoke DataService permissions."); throw e.rethrowAsRuntimeException(); } } private final class CellularDataServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (DBG) log("onServiceConnected"); mComponentName = name; mIDataService = IDataService.Stub.asInterface(service); mDeathRecipient = new DataServiceManagerDeathRecipient(name); mDeathRecipient = new DataServiceManagerDeathRecipient(); mBound = true; try { Loading Loading @@ -186,16 +235,22 @@ public class DataServiceManager { mBound = false; mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService( Context.CARRIER_CONFIG_SERVICE); mPackageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); mAppOps = (AppOpsManager) phone.getContext().getSystemService(Context.APP_OPS_SERVICE); bindDataService(); } private void bindDataService() { // Start by cleaning up all packages that *shouldn't* have permissions. revokePermissionsFromUnusedDataServices(); String packageName = getDataServicePackageName(); if (TextUtils.isEmpty(packageName)) { loge("Can't find the binding package"); return; } // Then pre-emptively grant the permissions to the package we will bind. grantPermissionsToService(packageName); try { if (!mPhone.getContext().bindService( Loading @@ -209,18 +264,55 @@ public class DataServiceManager { } } @NonNull private Set<String> getAllDataServicePackageNames() { // Cowardly using the public PackageManager interface here. // Note: This matches only packages that were installed on the system image. If we ever // expand the permissions model to allow CarrierPrivileged packages, then this will need // to be updated. List<ResolveInfo> dataPackages = mPhone.getContext().getPackageManager().queryIntentServices( new Intent(DataService.DATA_SERVICE_INTERFACE), PackageManager.MATCH_SYSTEM_ONLY); HashSet<String> packageNames = new HashSet<>(); for (ResolveInfo info : dataPackages) { if (info.serviceInfo == null) continue; packageNames.add(info.serviceInfo.packageName); } return packageNames; } /** * Get the data service package name for our current transport type. * * @return package name of the data service package for the the current transportType. */ private String getDataServicePackageName() { return getDataServicePackageName(mTransportType); } /** * Get the data service package by transport type. * * When we bind to a DataService package, we need to revoke permissions from stale * packages; we need to exclude data packages for all transport types, so we need to * to be able to query by transport type. * * @param transportType either WWAN or WLAN * @return package name of the data service package for the specified transportType. */ private String getDataServicePackageName(int transportType) { String packageName; int resourceId; String carrierConfig; switch (mTransportType) { case AccessNetworkConstants.TransportType.WWAN: switch (transportType) { case WWAN: resourceId = com.android.internal.R.string.config_wwan_data_service_package; carrierConfig = CarrierConfigManager .KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING; break; case AccessNetworkConstants.TransportType.WLAN: case WLAN: resourceId = com.android.internal.R.string.config_wlan_data_service_package; carrierConfig = CarrierConfigManager .KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING; Loading tests/telephonytests/Android.mk +3 −6 Original line number Diff line number Diff line Loading @@ -5,26 +5,23 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-subdir-java-files) #LOCAL_STATIC_JAVA_LIBRARIES := librilproto-java LOCAL_JAVA_LIBRARIES := \ android.test.runner \ telephony-common \ ims-common \ services.core \ bouncycastle \ android.test.base \ android.test.mock \ android.test.mock LOCAL_STATIC_JAVA_LIBRARIES := guava \ frameworks-base-testutils \ services.core \ telephony-common \ mockito-target-minus-junit4 \ android-support-test \ platform-test-annotations LOCAL_PACKAGE_NAME := FrameworksTelephonyTests LOCAL_PRIVATE_PLATFORM_APIS := true LOCAL_COMPATIBILITY_SUITE := device-tests # b/72575505 Loading tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java +4 −1 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import com.android.internal.telephony.dataconnection.DataConnection.DisconnectPa import com.android.internal.telephony.dataconnection.DataConnection.SetupResult; import com.android.internal.util.IState; import com.android.internal.util.StateMachine; import com.android.server.pm.PackageManagerService; import org.junit.After; import org.junit.Before; Loading @@ -93,6 +94,8 @@ public class DataConnectionTest extends TelephonyTest { ApnContext mApnContext; @Mock DcFailBringUp mDcFailBringUp; @Mock PackageManagerService mMockPackageManagerInternal; private DataConnection mDc; private DataConnectionTestHandler mDataConnectionTestHandler; Loading Loading @@ -164,7 +167,7 @@ public class DataConnectionTest extends TelephonyTest { public void setUp() throws Exception { logd("+Setup!"); super.setUp(getClass().getSimpleName()); mServiceManagerMockedServices.put("package", mMockPackageManagerInternal); doReturn("fake.action_detached").when(mPhone).getActionDetached(); replaceInstance(ConnectionParams.class, "mApnContext", mCp, mApnContext); replaceInstance(ConnectionParams.class, "mRilRat", mCp, Loading tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java +4 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ import com.android.internal.telephony.ISub; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyTest; import com.android.server.pm.PackageManagerService; import org.junit.After; import org.junit.Before; Loading Loading @@ -136,6 +137,8 @@ public class DcTrackerTest extends TelephonyTest { ApnSetting mApnSetting; @Mock DcAsyncChannel mDcac; @Mock PackageManagerService mMockPackageManagerInternal; private DcTracker mDct; private DcTrackerTestHandler mDcTrackerTestHandler; Loading Loading @@ -433,6 +436,7 @@ public class DcTrackerTest extends TelephonyTest { doReturn(1).when(mIsub).getDefaultDataSubId(); doReturn(mIsub).when(mBinder).queryLocalInterface(anyString()); mServiceManagerMockedServices.put("isub", mBinder); mServiceManagerMockedServices.put("package", mMockPackageManagerInternal); mContextFixture.putStringArrayResource( com.android.internal.R.array.config_cell_retries_per_error_code, Loading Loading
src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java +105 −13 Original line number Diff line number Diff line Loading @@ -16,10 +16,18 @@ package com.android.internal.telephony.dataconnection; import static android.telephony.AccessNetworkConstants.TransportType.WLAN; import static android.telephony.AccessNetworkConstants.TransportType.WWAN; import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.LinkProperties; import android.os.AsyncResult; import android.os.Handler; Loading @@ -28,7 +36,7 @@ import android.os.Message; import android.os.PersistableBundle; import android.os.RegistrantList; import android.os.RemoteException; import android.telephony.AccessNetworkConstants; import android.os.ServiceManager; import android.telephony.CarrierConfigManager; import android.telephony.Rlog; import android.telephony.data.DataCallResponse; Loading @@ -41,8 +49,10 @@ import android.text.TextUtils; import com.android.internal.telephony.Phone; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** Loading @@ -58,6 +68,8 @@ public class DataServiceManager { private final Phone mPhone; private final CarrierConfigManager mCarrierConfigManager; private final AppOpsManager mAppOps; private final IPackageManager mPackageManager; private final int mTransportType; Loading @@ -73,14 +85,10 @@ public class DataServiceManager { private final RegistrantList mDataCallListChangedRegistrants = new RegistrantList(); private class DataServiceManagerDeathRecipient implements IBinder.DeathRecipient { private final ComponentName mComponentName; DataServiceManagerDeathRecipient(ComponentName name) { mComponentName = name; } // not final because it is set by the onServiceConnected method private ComponentName mComponentName; private class DataServiceManagerDeathRecipient implements IBinder.DeathRecipient { @Override public void binderDied() { // TODO: try to rebind the service. Loading @@ -89,12 +97,53 @@ public class DataServiceManager { } } private void grantPermissionsToService(String packageName) { final String[] pkgToGrant = {packageName}; try { mPackageManager.grantDefaultPermissionsToEnabledTelephonyDataServices( pkgToGrant, mPhone.getContext().getUserId()); mAppOps.setMode(AppOpsManager.OP_MANAGE_IPSEC_TUNNELS, mPhone.getContext().getUserId(), pkgToGrant[0], AppOpsManager.MODE_ALLOWED); } catch (RemoteException e) { loge("Binder to package manager died, permission grant for DataService failed."); throw e.rethrowAsRuntimeException(); } } /** * Loop through all DataServices installed on the system and revoke permissions from any that * are not currently the WWAN or WLAN data service. */ private void revokePermissionsFromUnusedDataServices() { // Except the current data services from having their permissions removed. Set<String> dataServices = getAllDataServicePackageNames(); for (int transportType : new int[] {WWAN, WLAN}) { dataServices.remove(getDataServicePackageName(transportType)); } try { String[] dataServicesArray = new String[dataServices.size()]; dataServices.toArray(dataServicesArray); mPackageManager.revokeDefaultPermissionsFromDisabledTelephonyDataServices( dataServicesArray, mPhone.getContext().getUserId()); for (String pkg : dataServices) { mAppOps.setMode(AppOpsManager.OP_MANAGE_IPSEC_TUNNELS, mPhone.getContext().getUserId(), pkg, AppOpsManager.MODE_ERRORED); } } catch (RemoteException e) { loge("Binder to package manager died; failed to revoke DataService permissions."); throw e.rethrowAsRuntimeException(); } } private final class CellularDataServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (DBG) log("onServiceConnected"); mComponentName = name; mIDataService = IDataService.Stub.asInterface(service); mDeathRecipient = new DataServiceManagerDeathRecipient(name); mDeathRecipient = new DataServiceManagerDeathRecipient(); mBound = true; try { Loading Loading @@ -186,16 +235,22 @@ public class DataServiceManager { mBound = false; mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService( Context.CARRIER_CONFIG_SERVICE); mPackageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); mAppOps = (AppOpsManager) phone.getContext().getSystemService(Context.APP_OPS_SERVICE); bindDataService(); } private void bindDataService() { // Start by cleaning up all packages that *shouldn't* have permissions. revokePermissionsFromUnusedDataServices(); String packageName = getDataServicePackageName(); if (TextUtils.isEmpty(packageName)) { loge("Can't find the binding package"); return; } // Then pre-emptively grant the permissions to the package we will bind. grantPermissionsToService(packageName); try { if (!mPhone.getContext().bindService( Loading @@ -209,18 +264,55 @@ public class DataServiceManager { } } @NonNull private Set<String> getAllDataServicePackageNames() { // Cowardly using the public PackageManager interface here. // Note: This matches only packages that were installed on the system image. If we ever // expand the permissions model to allow CarrierPrivileged packages, then this will need // to be updated. List<ResolveInfo> dataPackages = mPhone.getContext().getPackageManager().queryIntentServices( new Intent(DataService.DATA_SERVICE_INTERFACE), PackageManager.MATCH_SYSTEM_ONLY); HashSet<String> packageNames = new HashSet<>(); for (ResolveInfo info : dataPackages) { if (info.serviceInfo == null) continue; packageNames.add(info.serviceInfo.packageName); } return packageNames; } /** * Get the data service package name for our current transport type. * * @return package name of the data service package for the the current transportType. */ private String getDataServicePackageName() { return getDataServicePackageName(mTransportType); } /** * Get the data service package by transport type. * * When we bind to a DataService package, we need to revoke permissions from stale * packages; we need to exclude data packages for all transport types, so we need to * to be able to query by transport type. * * @param transportType either WWAN or WLAN * @return package name of the data service package for the specified transportType. */ private String getDataServicePackageName(int transportType) { String packageName; int resourceId; String carrierConfig; switch (mTransportType) { case AccessNetworkConstants.TransportType.WWAN: switch (transportType) { case WWAN: resourceId = com.android.internal.R.string.config_wwan_data_service_package; carrierConfig = CarrierConfigManager .KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING; break; case AccessNetworkConstants.TransportType.WLAN: case WLAN: resourceId = com.android.internal.R.string.config_wlan_data_service_package; carrierConfig = CarrierConfigManager .KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING; Loading
tests/telephonytests/Android.mk +3 −6 Original line number Diff line number Diff line Loading @@ -5,26 +5,23 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-subdir-java-files) #LOCAL_STATIC_JAVA_LIBRARIES := librilproto-java LOCAL_JAVA_LIBRARIES := \ android.test.runner \ telephony-common \ ims-common \ services.core \ bouncycastle \ android.test.base \ android.test.mock \ android.test.mock LOCAL_STATIC_JAVA_LIBRARIES := guava \ frameworks-base-testutils \ services.core \ telephony-common \ mockito-target-minus-junit4 \ android-support-test \ platform-test-annotations LOCAL_PACKAGE_NAME := FrameworksTelephonyTests LOCAL_PRIVATE_PLATFORM_APIS := true LOCAL_COMPATIBILITY_SUITE := device-tests # b/72575505 Loading
tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java +4 −1 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import com.android.internal.telephony.dataconnection.DataConnection.DisconnectPa import com.android.internal.telephony.dataconnection.DataConnection.SetupResult; import com.android.internal.util.IState; import com.android.internal.util.StateMachine; import com.android.server.pm.PackageManagerService; import org.junit.After; import org.junit.Before; Loading @@ -93,6 +94,8 @@ public class DataConnectionTest extends TelephonyTest { ApnContext mApnContext; @Mock DcFailBringUp mDcFailBringUp; @Mock PackageManagerService mMockPackageManagerInternal; private DataConnection mDc; private DataConnectionTestHandler mDataConnectionTestHandler; Loading Loading @@ -164,7 +167,7 @@ public class DataConnectionTest extends TelephonyTest { public void setUp() throws Exception { logd("+Setup!"); super.setUp(getClass().getSimpleName()); mServiceManagerMockedServices.put("package", mMockPackageManagerInternal); doReturn("fake.action_detached").when(mPhone).getActionDetached(); replaceInstance(ConnectionParams.class, "mApnContext", mCp, mApnContext); replaceInstance(ConnectionParams.class, "mRilRat", mCp, Loading
tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java +4 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ import com.android.internal.telephony.ISub; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyTest; import com.android.server.pm.PackageManagerService; import org.junit.After; import org.junit.Before; Loading Loading @@ -136,6 +137,8 @@ public class DcTrackerTest extends TelephonyTest { ApnSetting mApnSetting; @Mock DcAsyncChannel mDcac; @Mock PackageManagerService mMockPackageManagerInternal; private DcTracker mDct; private DcTrackerTestHandler mDcTrackerTestHandler; Loading Loading @@ -433,6 +436,7 @@ public class DcTrackerTest extends TelephonyTest { doReturn(1).when(mIsub).getDefaultDataSubId(); doReturn(mIsub).when(mBinder).queryLocalInterface(anyString()); mServiceManagerMockedServices.put("isub", mBinder); mServiceManagerMockedServices.put("package", mMockPackageManagerInternal); mContextFixture.putStringArrayResource( com.android.internal.R.array.config_cell_retries_per_error_code, Loading