Loading src/java/com/android/internal/telephony/IccSmsInterfaceManager.java +70 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,8 @@ public class IccSmsInterfaceManager { @UnsupportedAppUsage private List<SmsRawData> mSms; private String mSmsc; @UnsupportedAppUsage private CellBroadcastRangeManager mCellBroadcastRangeManager = new CellBroadcastRangeManager(); Loading @@ -82,6 +84,8 @@ public class IccSmsInterfaceManager { private static final int EVENT_UPDATE_DONE = 2; protected static final int EVENT_SET_BROADCAST_ACTIVATION_DONE = 3; protected static final int EVENT_SET_BROADCAST_CONFIG_DONE = 4; private static final int EVENT_GET_SMSC_DONE = 5; private static final int EVENT_SET_SMSC_DONE = 6; private static final int SMS_CB_CODE_SCHEME_MIN = 0; private static final int SMS_CB_CODE_SCHEME_MAX = 255; public static final int SMS_MESSAGE_PRIORITY_NOT_SPECIFIED = -1; Loading Loading @@ -137,6 +141,25 @@ public class IccSmsInterfaceManager { mLock.notifyAll(); } break; case EVENT_GET_SMSC_DONE: ar = (AsyncResult) msg.obj; synchronized (mLock) { if (ar.exception == null) { mSmsc = (String) ar.result; } else { log("Cannot read SMSC"); mSmsc = null; } mLock.notifyAll(); } break; case EVENT_SET_SMSC_DONE: ar = (AsyncResult) msg.obj; synchronized (mLock) { mSuccess = (ar.exception == null); mLock.notifyAll(); } break; } } }; Loading Loading @@ -799,6 +822,53 @@ public class IccSmsInterfaceManager { return data; } /** * Gets the SMSC address from (U)SIM. * * @return the SMSC address string, null if failed. */ public String getSmscAddressFromIccEf(String callingPackage) { if (!mSmsPermissions.checkCallingOrSelfCanGetSmscAddress( callingPackage, "getSmscAddressFromIccEf")) { return null; } synchronized (mLock) { mSmsc = null; Message response = mHandler.obtainMessage(EVENT_GET_SMSC_DONE); mPhone.mCi.getSmscAddress(response); try { mLock.wait(); } catch (InterruptedException e) { log("interrupted while trying to read SMSC"); } } return mSmsc; } /** * Sets the SMSC address on (U)SIM. * * @param smsc the SMSC address string. * @return true for success, false otherwise. */ public boolean setSmscAddressOnIccEf(String callingPackage, String smsc) { if (!mSmsPermissions.checkCallingOrSelfCanSetSmscAddress( callingPackage, "setSmscAddressOnIccEf")) { return false; } synchronized (mLock) { mSuccess = false; Message response = mHandler.obtainMessage(EVENT_SET_SMSC_DONE); mPhone.mCi.setSmscAddress(smsc, response); try { mLock.wait(); } catch (InterruptedException e) { log("interrupted while trying to write SMSC"); } } return mSuccess; } public boolean enableCellBroadcast(int messageIdentifier, int ranType) { return enableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType); } Loading src/java/com/android/internal/telephony/SmsController.java +25 −0 Original line number Diff line number Diff line Loading @@ -554,6 +554,31 @@ public class SmsController extends ISmsImplBase { /** * Triggered by `adb shell dumpsys isms` */ @Override public String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage) { IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId); if (iccSmsIntMgr != null) { return iccSmsIntMgr.getSmscAddressFromIccEf(callingPackage); } else { Rlog.e(LOG_TAG, "getSmscAddressFromIccEfForSubscriber iccSmsIntMgr is null" + " for Subscription: " + subId); return null; } } @Override public boolean setSmscAddressOnIccEfForSubscriber( String smsc, int subId, String callingPackage) { IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId); if (iccSmsIntMgr != null) { return iccSmsIntMgr.setSmscAddressOnIccEf(callingPackage, smsc); } else { Rlog.e(LOG_TAG, "setSmscAddressOnIccEfForSubscriber iccSmsIntMgr is null" + " for Subscription: " + subId); return false; } } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!checkDumpPermission(mContext, LOG_TAG, pw)) { Loading src/java/com/android/internal/telephony/SmsPermissions.java +61 −3 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ public class SmsPermissions { * Check that the caller can send text messages. * * For persisted messages, the caller just needs the SEND_SMS permission. For unpersisted * For persisted messages, the caller just needs the SEND_SMS permission. For unpersisted * messages, the caller must either be the IMS app or a carrier-privileged app, or they must * have both the MODIFY_PHONE_STATE and SEND_SMS permissions. * Loading @@ -74,7 +73,6 @@ public class SmsPermissions { return checkCallingCanSendSms(callingPackage, message); } /** * Enforces that the caller is one of the following apps: * <ul> Loading @@ -101,7 +99,6 @@ public class SmsPermissions { TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mPhone.getSubId(), message); } /** * Check that the caller has SEND_SMS permissions. Can only be called during an IPC. * Loading @@ -128,6 +125,67 @@ public class SmsPermissions { == AppOpsManager.MODE_ALLOWED; } /** * Check that the caller (or self, if this is not an IPC) can get SMSC address from (U)SIM. * * The default SMS application can get SMSC address, otherwise the caller must have * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or carrier privileges. * * @return true if the caller is default SMS app or has the required permission and privileges. * Otherwise, false; */ public boolean checkCallingOrSelfCanGetSmscAddress(String callingPackage, String message) { // Allow it to the default SMS app always. if (!isDefaultSmsPackage(callingPackage)) { try { // Allow it with READ_PRIVILEGED_PHONE_STATE or Carrier Privileges TelephonyPermissions .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( mContext, mPhone.getSubId(), message); } catch (SecurityException e) { // To avoid crashing applications Log.e(LOG_TAG, message + ": Neither " + callingPackage + " is the default SMS app" + " nor the caller has " + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE + ", or carrier privileges", e); return false; } } return true; } /** * Check that the caller (or self, if this is not an IPC) can set SMSC address on (U)SIM. * * The default SMS application can set SMSC address, otherwise the caller must have * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier privileges. * * @return true if the caller is default SMS app or has the required permission and privileges. * Otherwise, false. */ public boolean checkCallingOrSelfCanSetSmscAddress(String callingPackage, String message) { // Allow it to the default SMS app always. if (!isDefaultSmsPackage(callingPackage)) { try { // Allow it with MODIFY_PHONE_STATE or Carrier Privileges TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( mContext, mPhone.getSubId(), message); } catch (SecurityException e) { // To avoid crashing applications Log.e(LOG_TAG, message + ": Neither " + callingPackage + " is the default SMS app" + " nor the caller has " + android.Manifest.permission.MODIFY_PHONE_STATE + ", or carrier privileges", e); return false; } } return true; } /** Check if a package is default SMS app. */ public boolean isDefaultSmsPackage(String packageName) { return SmsApplication.isDefaultSmsApplication(mContext, packageName); } @UnsupportedAppUsage protected void log(String msg) { Log.d(LOG_TAG, "[IccSmsInterfaceManager] " + msg); Loading tests/telephonytests/src/com/android/internal/telephony/SmsPermissionsTest.java +60 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ */ package com.android.internal.telephony; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; Loading Loading @@ -52,6 +55,7 @@ public class SmsPermissionsTest { private SmsPermissions mSmsPermissionsTest; private boolean mCallerHasCarrierPrivileges; private boolean mCallerIsDefaultSmsPackage; @Before public void setUp() throws Exception { Loading @@ -68,6 +72,11 @@ public class SmsPermissionsTest { throw new SecurityException(message); } } @Override public boolean isDefaultSmsPackage(String packageName) { return mCallerIsDefaultSmsPackage; } }; initialized.countDown(); }); Loading Loading @@ -166,4 +175,55 @@ public class SmsPermissionsTest { assertFalse(mSmsPermissionsTest.checkCallingCanSendText( false /* persistMessageForNonDefaultSmsApp */, PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanGetSmscAddressPermissions_defaultSmsApp() { mCallerIsDefaultSmsPackage = true; // Other permissions shouldn't matter. Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); assertTrue(mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanGetSmscAddressPermissions_hasReadPrivilegedPhoneState() { Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) .thenReturn(PERMISSION_GRANTED); assertTrue(mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanGetSmscAddressPermissions_noPermissions() { Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanSetSmscAddressPermissions_defaultSmsApp() { mCallerIsDefaultSmsPackage = true; // Other permissions shouldn't matter. Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.MODIFY_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); assertTrue(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanSetSmscAddressPermissions_hasModifyPhoneState() { Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.MODIFY_PHONE_STATE)) .thenReturn(PERMISSION_GRANTED); assertTrue(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanSetSmscAddressPermissions_noPermissions() { Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.MODIFY_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); } } Loading
src/java/com/android/internal/telephony/IccSmsInterfaceManager.java +70 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,8 @@ public class IccSmsInterfaceManager { @UnsupportedAppUsage private List<SmsRawData> mSms; private String mSmsc; @UnsupportedAppUsage private CellBroadcastRangeManager mCellBroadcastRangeManager = new CellBroadcastRangeManager(); Loading @@ -82,6 +84,8 @@ public class IccSmsInterfaceManager { private static final int EVENT_UPDATE_DONE = 2; protected static final int EVENT_SET_BROADCAST_ACTIVATION_DONE = 3; protected static final int EVENT_SET_BROADCAST_CONFIG_DONE = 4; private static final int EVENT_GET_SMSC_DONE = 5; private static final int EVENT_SET_SMSC_DONE = 6; private static final int SMS_CB_CODE_SCHEME_MIN = 0; private static final int SMS_CB_CODE_SCHEME_MAX = 255; public static final int SMS_MESSAGE_PRIORITY_NOT_SPECIFIED = -1; Loading Loading @@ -137,6 +141,25 @@ public class IccSmsInterfaceManager { mLock.notifyAll(); } break; case EVENT_GET_SMSC_DONE: ar = (AsyncResult) msg.obj; synchronized (mLock) { if (ar.exception == null) { mSmsc = (String) ar.result; } else { log("Cannot read SMSC"); mSmsc = null; } mLock.notifyAll(); } break; case EVENT_SET_SMSC_DONE: ar = (AsyncResult) msg.obj; synchronized (mLock) { mSuccess = (ar.exception == null); mLock.notifyAll(); } break; } } }; Loading Loading @@ -799,6 +822,53 @@ public class IccSmsInterfaceManager { return data; } /** * Gets the SMSC address from (U)SIM. * * @return the SMSC address string, null if failed. */ public String getSmscAddressFromIccEf(String callingPackage) { if (!mSmsPermissions.checkCallingOrSelfCanGetSmscAddress( callingPackage, "getSmscAddressFromIccEf")) { return null; } synchronized (mLock) { mSmsc = null; Message response = mHandler.obtainMessage(EVENT_GET_SMSC_DONE); mPhone.mCi.getSmscAddress(response); try { mLock.wait(); } catch (InterruptedException e) { log("interrupted while trying to read SMSC"); } } return mSmsc; } /** * Sets the SMSC address on (U)SIM. * * @param smsc the SMSC address string. * @return true for success, false otherwise. */ public boolean setSmscAddressOnIccEf(String callingPackage, String smsc) { if (!mSmsPermissions.checkCallingOrSelfCanSetSmscAddress( callingPackage, "setSmscAddressOnIccEf")) { return false; } synchronized (mLock) { mSuccess = false; Message response = mHandler.obtainMessage(EVENT_SET_SMSC_DONE); mPhone.mCi.setSmscAddress(smsc, response); try { mLock.wait(); } catch (InterruptedException e) { log("interrupted while trying to write SMSC"); } } return mSuccess; } public boolean enableCellBroadcast(int messageIdentifier, int ranType) { return enableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType); } Loading
src/java/com/android/internal/telephony/SmsController.java +25 −0 Original line number Diff line number Diff line Loading @@ -554,6 +554,31 @@ public class SmsController extends ISmsImplBase { /** * Triggered by `adb shell dumpsys isms` */ @Override public String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage) { IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId); if (iccSmsIntMgr != null) { return iccSmsIntMgr.getSmscAddressFromIccEf(callingPackage); } else { Rlog.e(LOG_TAG, "getSmscAddressFromIccEfForSubscriber iccSmsIntMgr is null" + " for Subscription: " + subId); return null; } } @Override public boolean setSmscAddressOnIccEfForSubscriber( String smsc, int subId, String callingPackage) { IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId); if (iccSmsIntMgr != null) { return iccSmsIntMgr.setSmscAddressOnIccEf(callingPackage, smsc); } else { Rlog.e(LOG_TAG, "setSmscAddressOnIccEfForSubscriber iccSmsIntMgr is null" + " for Subscription: " + subId); return false; } } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!checkDumpPermission(mContext, LOG_TAG, pw)) { Loading
src/java/com/android/internal/telephony/SmsPermissions.java +61 −3 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ public class SmsPermissions { * Check that the caller can send text messages. * * For persisted messages, the caller just needs the SEND_SMS permission. For unpersisted * For persisted messages, the caller just needs the SEND_SMS permission. For unpersisted * messages, the caller must either be the IMS app or a carrier-privileged app, or they must * have both the MODIFY_PHONE_STATE and SEND_SMS permissions. * Loading @@ -74,7 +73,6 @@ public class SmsPermissions { return checkCallingCanSendSms(callingPackage, message); } /** * Enforces that the caller is one of the following apps: * <ul> Loading @@ -101,7 +99,6 @@ public class SmsPermissions { TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mPhone.getSubId(), message); } /** * Check that the caller has SEND_SMS permissions. Can only be called during an IPC. * Loading @@ -128,6 +125,67 @@ public class SmsPermissions { == AppOpsManager.MODE_ALLOWED; } /** * Check that the caller (or self, if this is not an IPC) can get SMSC address from (U)SIM. * * The default SMS application can get SMSC address, otherwise the caller must have * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or carrier privileges. * * @return true if the caller is default SMS app or has the required permission and privileges. * Otherwise, false; */ public boolean checkCallingOrSelfCanGetSmscAddress(String callingPackage, String message) { // Allow it to the default SMS app always. if (!isDefaultSmsPackage(callingPackage)) { try { // Allow it with READ_PRIVILEGED_PHONE_STATE or Carrier Privileges TelephonyPermissions .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( mContext, mPhone.getSubId(), message); } catch (SecurityException e) { // To avoid crashing applications Log.e(LOG_TAG, message + ": Neither " + callingPackage + " is the default SMS app" + " nor the caller has " + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE + ", or carrier privileges", e); return false; } } return true; } /** * Check that the caller (or self, if this is not an IPC) can set SMSC address on (U)SIM. * * The default SMS application can set SMSC address, otherwise the caller must have * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier privileges. * * @return true if the caller is default SMS app or has the required permission and privileges. * Otherwise, false. */ public boolean checkCallingOrSelfCanSetSmscAddress(String callingPackage, String message) { // Allow it to the default SMS app always. if (!isDefaultSmsPackage(callingPackage)) { try { // Allow it with MODIFY_PHONE_STATE or Carrier Privileges TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( mContext, mPhone.getSubId(), message); } catch (SecurityException e) { // To avoid crashing applications Log.e(LOG_TAG, message + ": Neither " + callingPackage + " is the default SMS app" + " nor the caller has " + android.Manifest.permission.MODIFY_PHONE_STATE + ", or carrier privileges", e); return false; } } return true; } /** Check if a package is default SMS app. */ public boolean isDefaultSmsPackage(String packageName) { return SmsApplication.isDefaultSmsApplication(mContext, packageName); } @UnsupportedAppUsage protected void log(String msg) { Log.d(LOG_TAG, "[IccSmsInterfaceManager] " + msg); Loading
tests/telephonytests/src/com/android/internal/telephony/SmsPermissionsTest.java +60 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ */ package com.android.internal.telephony; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; Loading Loading @@ -52,6 +55,7 @@ public class SmsPermissionsTest { private SmsPermissions mSmsPermissionsTest; private boolean mCallerHasCarrierPrivileges; private boolean mCallerIsDefaultSmsPackage; @Before public void setUp() throws Exception { Loading @@ -68,6 +72,11 @@ public class SmsPermissionsTest { throw new SecurityException(message); } } @Override public boolean isDefaultSmsPackage(String packageName) { return mCallerIsDefaultSmsPackage; } }; initialized.countDown(); }); Loading Loading @@ -166,4 +175,55 @@ public class SmsPermissionsTest { assertFalse(mSmsPermissionsTest.checkCallingCanSendText( false /* persistMessageForNonDefaultSmsApp */, PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanGetSmscAddressPermissions_defaultSmsApp() { mCallerIsDefaultSmsPackage = true; // Other permissions shouldn't matter. Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); assertTrue(mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanGetSmscAddressPermissions_hasReadPrivilegedPhoneState() { Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) .thenReturn(PERMISSION_GRANTED); assertTrue(mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanGetSmscAddressPermissions_noPermissions() { Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanSetSmscAddressPermissions_defaultSmsApp() { mCallerIsDefaultSmsPackage = true; // Other permissions shouldn't matter. Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.MODIFY_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); assertTrue(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanSetSmscAddressPermissions_hasModifyPhoneState() { Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.MODIFY_PHONE_STATE)) .thenReturn(PERMISSION_GRANTED); assertTrue(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); } @Test public void testCheckCallingOrSelfCanSetSmscAddressPermissions_noPermissions() { Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.MODIFY_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); } }