Loading src/java/com/android/internal/telephony/CarrierServiceBindHelper.java +52 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.content.pm.ResolveInfo; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; import android.os.Message; import android.os.Process; Loading @@ -47,6 +48,8 @@ import com.android.internal.telephony.util.TelephonyUtils; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; import java.util.Set; /** * Manages long-lived bindings to carrier services Loading @@ -71,6 +74,8 @@ public class CarrierServiceBindHelper { public SparseArray<AppBinding> mBindings = new SparseArray(); @VisibleForTesting public SparseArray<String> mLastSimState = new SparseArray<>(); // TODO(b/201423849): Clean up PackageChangeReceiver/UserUnlockedReceiver/SIM State change if // CarrierServiceChangeCallback can cover the cases private final PackageChangeReceiver mPackageMonitor = new CarrierServicePackageMonitor(); private final LocalLog mLocalLog = new LocalLog(100); Loading @@ -90,6 +95,30 @@ public class CarrierServiceBindHelper { } }; private class CarrierServiceChangeCallback implements TelephonyManager.CarrierPrivilegesCallback { final int mPhoneId; CarrierServiceChangeCallback(int phoneId) { this.mPhoneId = phoneId; } @Override public void onCarrierPrivilegesChanged(Set<String> privilegedPackageNames, Set<Integer> privilegedUids) { // Ignored, not interested here } @Override public void onCarrierServiceChanged(String carrierServicePackageName, int carrierServiceUid) { logdWithLocalLog("onCarrierServiceChanged, carrierServicePackageName=" + carrierServicePackageName + ", carrierServiceUid=" + carrierServiceUid + ", mPhoneId=" + mPhoneId); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REBIND, mPhoneId)); } } private static final int EVENT_REBIND = 0; @VisibleForTesting public static final int EVENT_PERFORM_IMMEDIATE_UNBIND = 1; Loading Loading @@ -123,6 +152,8 @@ public class CarrierServiceBindHelper { case EVENT_MULTI_SIM_CONFIG_CHANGED: updateBindingsAndSimStates(); break; default: Log.e(LOG_TAG, "Unsupported event received: " + msg.what); } } }; Loading Loading @@ -162,6 +193,7 @@ public class CarrierServiceBindHelper { // If prevLen > newLen, dispose AppBinding and simState objects. for (int phoneId = newLen; phoneId < prevLen; phoneId++) { mBindings.get(phoneId).tearDown(); mBindings.get(phoneId).unbind(true); mBindings.delete(phoneId); mLastSimState.delete(phoneId); Loading Loading @@ -193,9 +225,23 @@ public class CarrierServiceBindHelper { private String carrierPackage; private String carrierServiceClass; private long mUnbindScheduledUptimeMillis = -1; private final CarrierServiceChangeCallback mCarrierServiceChangeCallback; public AppBinding(int phoneId) { this.phoneId = phoneId; this.mCarrierServiceChangeCallback = new CarrierServiceChangeCallback(phoneId); TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); if (tm != null) { tm.registerCarrierPrivilegesCallback(phoneId, new HandlerExecutor(mHandler), mCarrierServiceChangeCallback); } } public void tearDown() { TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); if (tm != null && mCarrierServiceChangeCallback != null) { tm.unregisterCarrierPrivilegesCallback(mCarrierServiceChangeCallback); } } public int getPhoneId() { Loading Loading @@ -365,6 +411,7 @@ public class CarrierServiceBindHelper { pw.println(" unbindCount: " + unbindCount); pw.println(" lastUnbindMillis: " + lastUnbindMillis); pw.println(" mUnbindScheduledUptimeMillis: " + mUnbindScheduledUptimeMillis); pw.println(" mCarrierServiceChangeCallback: " + mCarrierServiceChangeCallback); pw.println(); } } Loading Loading @@ -405,27 +452,32 @@ public class CarrierServiceBindHelper { private class CarrierServicePackageMonitor extends PackageChangeReceiver { @Override public void onPackageAdded(String packageName) { logdWithLocalLog("onPackageAdded: " + packageName); evaluateBinding(packageName, true /* forceUnbind */); } @Override public void onPackageRemoved(String packageName) { logdWithLocalLog("onPackageRemoved: " + packageName); evaluateBinding(packageName, true /* forceUnbind */); } @Override public void onPackageUpdateFinished(String packageName) { logdWithLocalLog("onPackageUpdateFinished: " + packageName); evaluateBinding(packageName, true /* forceUnbind */); } @Override public void onPackageModified(String packageName) { logdWithLocalLog("onPackageModified: " + packageName); evaluateBinding(packageName, false /* forceUnbind */); } @Override public void onHandleForceStop(String[] packages, boolean doit) { if (doit) { logdWithLocalLog("onHandleForceStop: " + Arrays.toString(packages)); for (String packageName : packages) { evaluateBinding(packageName, true /* forceUnbind */); } Loading tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -18,10 +18,15 @@ package com.android.internal.telephony; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.os.Message; import android.telephony.TelephonyManager.CarrierPrivilegesCallback; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; Loading @@ -30,10 +35,14 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class CarrierServiceBindHelperTest extends TelephonyTest { private static final int PHONE_ID_0 = 0; private static final int PHONE_ID_1 = 1; CarrierServiceBindHelper mCarrierServiceBindHelper; @Before public void setUp() throws Exception { Loading Loading @@ -90,4 +99,38 @@ public class CarrierServiceBindHelperTest extends TelephonyTest { CarrierServiceBindHelper.EVENT_PERFORM_IMMEDIATE_UNBIND, new Integer(0))); } @Test public void testCarrierPrivilegesCallbackRegistration() { // Device starts with DSDS mode doReturn(2).when(mTelephonyManager).getActiveModemCount(); mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext); processAllMessages(); // Verify that CarrierPrivilegesCallbacks are registered on both phones. // Capture the callbacks for further verification ArgumentCaptor<CarrierPrivilegesCallback> phone0CallbackCaptor = ArgumentCaptor.forClass( CarrierPrivilegesCallback.class); verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_0), any(), phone0CallbackCaptor.capture()); CarrierPrivilegesCallback phone0Callback = phone0CallbackCaptor.getAllValues().get(0); assertNotNull(phone0Callback); ArgumentCaptor<CarrierPrivilegesCallback> phone1CallbackCaptor = ArgumentCaptor.forClass( CarrierPrivilegesCallback.class); verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_1), any(), phone1CallbackCaptor.capture()); CarrierPrivilegesCallback phone1Callback = phone1CallbackCaptor.getAllValues().get(0); assertNotNull(phone1Callback); // Switch back to single SIM. doReturn(1).when(mTelephonyManager).getActiveModemCount(); PhoneConfigurationManager.notifyMultiSimConfigChange(1); processAllMessages(); // Verify the callback for phone1 had been unregistered while phone0 didn't. verify(mTelephonyManager).unregisterCarrierPrivilegesCallback(eq(phone1Callback)); verify(mTelephonyManager, never()).unregisterCarrierPrivilegesCallback(eq(phone0Callback)); } // TODO (b/232461097): Add UT cases to cover more scenarios (user unlock, SIM state change...) } Loading
src/java/com/android/internal/telephony/CarrierServiceBindHelper.java +52 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.content.pm.ResolveInfo; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; import android.os.Message; import android.os.Process; Loading @@ -47,6 +48,8 @@ import com.android.internal.telephony.util.TelephonyUtils; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; import java.util.Set; /** * Manages long-lived bindings to carrier services Loading @@ -71,6 +74,8 @@ public class CarrierServiceBindHelper { public SparseArray<AppBinding> mBindings = new SparseArray(); @VisibleForTesting public SparseArray<String> mLastSimState = new SparseArray<>(); // TODO(b/201423849): Clean up PackageChangeReceiver/UserUnlockedReceiver/SIM State change if // CarrierServiceChangeCallback can cover the cases private final PackageChangeReceiver mPackageMonitor = new CarrierServicePackageMonitor(); private final LocalLog mLocalLog = new LocalLog(100); Loading @@ -90,6 +95,30 @@ public class CarrierServiceBindHelper { } }; private class CarrierServiceChangeCallback implements TelephonyManager.CarrierPrivilegesCallback { final int mPhoneId; CarrierServiceChangeCallback(int phoneId) { this.mPhoneId = phoneId; } @Override public void onCarrierPrivilegesChanged(Set<String> privilegedPackageNames, Set<Integer> privilegedUids) { // Ignored, not interested here } @Override public void onCarrierServiceChanged(String carrierServicePackageName, int carrierServiceUid) { logdWithLocalLog("onCarrierServiceChanged, carrierServicePackageName=" + carrierServicePackageName + ", carrierServiceUid=" + carrierServiceUid + ", mPhoneId=" + mPhoneId); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REBIND, mPhoneId)); } } private static final int EVENT_REBIND = 0; @VisibleForTesting public static final int EVENT_PERFORM_IMMEDIATE_UNBIND = 1; Loading Loading @@ -123,6 +152,8 @@ public class CarrierServiceBindHelper { case EVENT_MULTI_SIM_CONFIG_CHANGED: updateBindingsAndSimStates(); break; default: Log.e(LOG_TAG, "Unsupported event received: " + msg.what); } } }; Loading Loading @@ -162,6 +193,7 @@ public class CarrierServiceBindHelper { // If prevLen > newLen, dispose AppBinding and simState objects. for (int phoneId = newLen; phoneId < prevLen; phoneId++) { mBindings.get(phoneId).tearDown(); mBindings.get(phoneId).unbind(true); mBindings.delete(phoneId); mLastSimState.delete(phoneId); Loading Loading @@ -193,9 +225,23 @@ public class CarrierServiceBindHelper { private String carrierPackage; private String carrierServiceClass; private long mUnbindScheduledUptimeMillis = -1; private final CarrierServiceChangeCallback mCarrierServiceChangeCallback; public AppBinding(int phoneId) { this.phoneId = phoneId; this.mCarrierServiceChangeCallback = new CarrierServiceChangeCallback(phoneId); TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); if (tm != null) { tm.registerCarrierPrivilegesCallback(phoneId, new HandlerExecutor(mHandler), mCarrierServiceChangeCallback); } } public void tearDown() { TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); if (tm != null && mCarrierServiceChangeCallback != null) { tm.unregisterCarrierPrivilegesCallback(mCarrierServiceChangeCallback); } } public int getPhoneId() { Loading Loading @@ -365,6 +411,7 @@ public class CarrierServiceBindHelper { pw.println(" unbindCount: " + unbindCount); pw.println(" lastUnbindMillis: " + lastUnbindMillis); pw.println(" mUnbindScheduledUptimeMillis: " + mUnbindScheduledUptimeMillis); pw.println(" mCarrierServiceChangeCallback: " + mCarrierServiceChangeCallback); pw.println(); } } Loading Loading @@ -405,27 +452,32 @@ public class CarrierServiceBindHelper { private class CarrierServicePackageMonitor extends PackageChangeReceiver { @Override public void onPackageAdded(String packageName) { logdWithLocalLog("onPackageAdded: " + packageName); evaluateBinding(packageName, true /* forceUnbind */); } @Override public void onPackageRemoved(String packageName) { logdWithLocalLog("onPackageRemoved: " + packageName); evaluateBinding(packageName, true /* forceUnbind */); } @Override public void onPackageUpdateFinished(String packageName) { logdWithLocalLog("onPackageUpdateFinished: " + packageName); evaluateBinding(packageName, true /* forceUnbind */); } @Override public void onPackageModified(String packageName) { logdWithLocalLog("onPackageModified: " + packageName); evaluateBinding(packageName, false /* forceUnbind */); } @Override public void onHandleForceStop(String[] packages, boolean doit) { if (doit) { logdWithLocalLog("onHandleForceStop: " + Arrays.toString(packages)); for (String packageName : packages) { evaluateBinding(packageName, true /* forceUnbind */); } Loading
tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -18,10 +18,15 @@ package com.android.internal.telephony; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.os.Message; import android.telephony.TelephonyManager.CarrierPrivilegesCallback; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; Loading @@ -30,10 +35,14 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class CarrierServiceBindHelperTest extends TelephonyTest { private static final int PHONE_ID_0 = 0; private static final int PHONE_ID_1 = 1; CarrierServiceBindHelper mCarrierServiceBindHelper; @Before public void setUp() throws Exception { Loading Loading @@ -90,4 +99,38 @@ public class CarrierServiceBindHelperTest extends TelephonyTest { CarrierServiceBindHelper.EVENT_PERFORM_IMMEDIATE_UNBIND, new Integer(0))); } @Test public void testCarrierPrivilegesCallbackRegistration() { // Device starts with DSDS mode doReturn(2).when(mTelephonyManager).getActiveModemCount(); mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext); processAllMessages(); // Verify that CarrierPrivilegesCallbacks are registered on both phones. // Capture the callbacks for further verification ArgumentCaptor<CarrierPrivilegesCallback> phone0CallbackCaptor = ArgumentCaptor.forClass( CarrierPrivilegesCallback.class); verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_0), any(), phone0CallbackCaptor.capture()); CarrierPrivilegesCallback phone0Callback = phone0CallbackCaptor.getAllValues().get(0); assertNotNull(phone0Callback); ArgumentCaptor<CarrierPrivilegesCallback> phone1CallbackCaptor = ArgumentCaptor.forClass( CarrierPrivilegesCallback.class); verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_1), any(), phone1CallbackCaptor.capture()); CarrierPrivilegesCallback phone1Callback = phone1CallbackCaptor.getAllValues().get(0); assertNotNull(phone1Callback); // Switch back to single SIM. doReturn(1).when(mTelephonyManager).getActiveModemCount(); PhoneConfigurationManager.notifyMultiSimConfigChange(1); processAllMessages(); // Verify the callback for phone1 had been unregistered while phone0 didn't. verify(mTelephonyManager).unregisterCarrierPrivilegesCallback(eq(phone1Callback)); verify(mTelephonyManager, never()).unregisterCarrierPrivilegesCallback(eq(phone0Callback)); } // TODO (b/232461097): Add UT cases to cover more scenarios (user unlock, SIM state change...) }