diff options
20 files changed, 343 insertions, 89 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 0b8cdf29a8f4..a135f55b0428 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1371,6 +1371,10 @@ package android.bluetooth.le { package android.content { + public abstract class BroadcastReceiver { + method @NonNull public final android.os.UserHandle getSendingUser(); + } + public class ContentProviderClient implements java.lang.AutoCloseable { method @RequiresPermission(android.Manifest.permission.REMOVE_TASKS) public void setDetectNotResponding(long); } @@ -1387,6 +1391,7 @@ package android.content { method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; method @Nullable public abstract java.io.File getPreloadsFileCache(); method public abstract boolean isCredentialProtectedStorage(); + method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public android.content.Intent registerReceiverForAllUsers(@Nullable android.content.BroadcastReceiver, @NonNull android.content.IntentFilter, @Nullable String, @Nullable android.os.Handler); method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle); method public abstract void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable android.os.Bundle, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); @@ -8632,6 +8637,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isInEmergencySmsMode(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 794ffcb83078..0e0e7f769651 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -127,6 +127,13 @@ class ReceiverRestrictedContext extends ContextWrapper { } @Override + public Intent registerReceiverForAllUsers(BroadcastReceiver receiver, IntentFilter filter, + String broadcastPermission, Handler scheduler) { + return registerReceiverAsUser( + receiver, UserHandle.ALL, filter, broadcastPermission, scheduler); + } + + @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { if (receiver == null) { @@ -1520,6 +1527,13 @@ class ContextImpl extends Context { } @Override + public Intent registerReceiverForAllUsers(BroadcastReceiver receiver, + IntentFilter filter, String broadcastPermission, Handler scheduler) { + return registerReceiverAsUser(receiver, UserHandle.ALL, + filter, broadcastPermission, scheduler); + } + + @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, user.getIdentifier(), diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java index 8691ed43ac81..f73a376dfc69 100644 --- a/core/java/android/content/BroadcastReceiver.java +++ b/core/java/android/content/BroadcastReceiver.java @@ -16,6 +16,8 @@ package android.content; +import android.annotation.NonNull; +import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.app.ActivityManager; import android.app.ActivityThread; @@ -25,6 +27,7 @@ import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Log; import android.util.Slog; @@ -623,6 +626,20 @@ public abstract class BroadcastReceiver { return mPendingResult; } + /** + * Returns the user that the broadcast was sent to. + * + * <p>It can be used in a receiver registered by + * {@link Context#registerReceiverForAllUsers Context.registerReceiverForAllUsers()} + * to determine on which user the broadcast was sent. + * + * @hide + */ + @SystemApi + public final @NonNull UserHandle getSendingUser() { + return UserHandle.of(getSendingUserId()); + } + /** @hide */ public int getSendingUserId() { return mPendingResult.mSendingUser; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 4b22166a9688..507d1d82330c 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2795,6 +2795,37 @@ public abstract class Context { @Nullable Handler scheduler, @RegisterReceiverFlags int flags); /** + * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)} + * but this receiver will receive broadcasts that are sent to all users. The receiver can + * use {@link BroadcastReceiver#getSendingUser} to determine on which user the broadcast + * was sent. + * + * @param receiver The BroadcastReceiver to handle the broadcast. + * @param filter Selects the Intent broadcasts to be received. + * @param broadcastPermission String naming a permissions that a + * broadcaster must hold in order to send an Intent to you. If {@code null}, + * no permission is required. + * @param scheduler Handler identifying the thread that will receive + * the Intent. If {@code null}, the main thread of the process will be used. + * + * @return The first sticky intent found that matches <var>filter</var>, + * or {@code null} if there are none. + * + * @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) + * @see #sendBroadcast + * @see #unregisterReceiver + * @hide + */ + @Nullable + @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) + @SystemApi + public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver, + @NonNull IntentFilter filter, @Nullable String broadcastPermission, + @Nullable Handler scheduler) { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + + /** * @hide * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) * but for a specific user. This receiver will receiver broadcasts that diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 428aadb5c3f6..497e2fd60447 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -664,6 +664,17 @@ public class ContextWrapper extends Context { /** @hide */ @Override + @Nullable + @SystemApi + public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver, + @NonNull IntentFilter filter, @Nullable String broadcastPermission, + @Nullable Handler scheduler) { + return mBase.registerReceiverForAllUsers(receiver, filter, broadcastPermission, + scheduler); + } + + /** @hide */ + @Override @UnsupportedAppUsage public Intent registerReceiverAsUser( BroadcastReceiver receiver, UserHandle user, IntentFilter filter, diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 3d91c37272ad..00ab45ec3537 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -891,9 +891,9 @@ public final class Zygote { } } - private static void callPostForkSystemServerHooks() { + private static void callPostForkSystemServerHooks(int runtimeFlags) { // SystemServer specific post fork hooks run before child post fork hooks. - ZygoteHooks.postForkSystemServer(); + ZygoteHooks.postForkSystemServer(runtimeFlags); } private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer, diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 1a81e3d104ba..a3f5311e49c4 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -1108,7 +1108,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, UnsetChldSignalHandler(); if (is_system_server) { - env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks); + env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks, runtime_flags); if (env->ExceptionCheck()) { fail_fn("Error calling post fork system server hooks."); } @@ -1741,7 +1741,7 @@ int register_com_android_internal_os_Zygote(JNIEnv* env) { gZygoteClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kZygoteClassName)); gCallPostForkSystemServerHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkSystemServerHooks", - "()V"); + "(I)V"); gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkChildHooks", "(IZZLjava/lang/String;)V"); diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java index b48ac3347093..9f70538191c2 100644 --- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java +++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java @@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit; public class SystemPropertiesTest extends TestCase { private static final String KEY = "sys.testkey"; + private static final String UNSET_KEY = "Aiw7woh6ie4toh7W"; private static final String PERSIST_KEY = "persist.sys.testkey"; @SmallTest @@ -133,6 +134,15 @@ public class SystemPropertiesTest extends TestCase { } @SmallTest + public void testUnset() throws Exception { + assertEquals("abc", SystemProperties.get(UNSET_KEY, "abc")); + assertEquals(true, SystemProperties.getBoolean(UNSET_KEY, true)); + assertEquals(false, SystemProperties.getBoolean(UNSET_KEY, false)); + assertEquals(5, SystemProperties.getInt(UNSET_KEY, 5)); + assertEquals(-10, SystemProperties.getLong(UNSET_KEY, -10)); + } + + @SmallTest @SuppressWarnings("null") public void testNullKey() throws Exception { try { diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java index 0efc5bf411f3..2f4406b5cc11 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java @@ -171,14 +171,17 @@ public class CarrierTextController { mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); mSeparator = separator; mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class); - mSimSlotsNumber = ((TelephonyManager) context.getSystemService( - Context.TELEPHONY_SERVICE)).getSupportedModemCount(); + mSimSlotsNumber = getTelephonyManager().getSupportedModemCount(); mSimErrorState = new boolean[mSimSlotsNumber]; updateDisplayOpportunisticSubscriptionCarrierText(SystemProperties.getBoolean( TelephonyProperties.DISPLAY_OPPORTUNISTIC_SUBSCRIPTION_CARRIER_TEXT_PROPERTY_NAME, false)); } + private TelephonyManager getTelephonyManager() { + return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + } + /** * Checks if there are faulty cards. Adds the text depending on the slot of the card * @@ -194,7 +197,7 @@ public class CarrierTextController { CharSequence carrierTextForSimIOError = getCarrierTextForSimState( IccCardConstants.State.CARD_IO_ERROR, carrier); // mSimErrorState has the state of each sim indexed by slotID. - for (int index = 0; index < mSimErrorState.length; index++) { + for (int index = 0; index < getTelephonyManager().getActiveModemCount(); index++) { if (!mSimErrorState[index]) { continue; } @@ -227,8 +230,7 @@ public class CarrierTextController { * @param callback Callback to provide text updates */ public void setListening(CarrierTextCallback callback) { - TelephonyManager telephonyManager = ((TelephonyManager) mContext - .getSystemService(Context.TELEPHONY_SERVICE)); + TelephonyManager telephonyManager = getTelephonyManager(); if (callback != null) { mCarrierTextCallback = callback; if (ConnectivityManager.from(mContext).isNetworkSupported( diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java index 528625ee4dc8..e74cc8e6d44e 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java @@ -120,6 +120,7 @@ public class CarrierTextControllerTest extends SysuiTestCase { mCarrierTextCallbackInfo = new CarrierTextController.CarrierTextCallbackInfo("", new CharSequence[]{}, false, new int[]{}); when(mTelephonyManager.getSupportedModemCount()).thenReturn(3); + when(mTelephonyManager.getActiveModemCount()).thenReturn(3); mCarrierTextController = new TestCarrierTextController(mContext, SEPARATOR, true, true, mKeyguardUpdateMonitor); @@ -173,6 +174,15 @@ public class CarrierTextControllerTest extends SysuiTestCase { // There's only one subscription in the list assertEquals(1, captor.getValue().listOfCarriers.length); assertEquals(TEST_CARRIER, captor.getValue().listOfCarriers[0]); + + // Now it becomes single SIM active mode. + reset(mCarrierTextCallback); + when(mTelephonyManager.getActiveModemCount()).thenReturn(1); + // Update carrier text. It should ignore error state of subId 3 in inactive slotId. + mCarrierTextController.updateCarrierText(); + mTestableLooper.processAllMessages(); + verify(mCarrierTextCallback).updateCarrierInfo(captor.capture()); + assertEquals("TEST_CARRIER", captor.getValue().carrierText); } @Test diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 208b63888efb..798a4c663c51 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -98,7 +98,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind //Maximum msec to wait for service restart - private static final int SERVICE_RESTART_TIME_MS = 200; + private static final int SERVICE_RESTART_TIME_MS = 400; //Maximum msec to wait for restart due to error private static final int ERROR_RESTART_TIME_MS = 3000; //Maximum msec to delay MESSAGE_USER_SWITCHED @@ -1635,13 +1635,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // ActivityManager detects it. // The waiting for (b) and (c) is accomplished by // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE - // message. On slower devices, that delay needs to be - // on the order of (2 * SERVICE_RESTART_TIME_MS). + // message. The delay time is backed off if Bluetooth + // continuously failed to turn on itself. // waitForOnOff(false, true); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); } break; @@ -1820,7 +1820,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { waitForOnOff(false, true); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); } } if (newState == BluetoothAdapter.STATE_ON @@ -1863,7 +1863,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Send a Bluetooth Restart message Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, SERVICE_RESTART_TIME_MS); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); } sendBluetoothServiceDownCallback(); @@ -1886,14 +1886,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; } case MESSAGE_RESTART_BLUETOOTH_SERVICE: { - Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE"); - /* Enable without persisting the setting as - it doesnt change when IBluetooth - service restarts */ - mEnable = true; - addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED, - mContext.getPackageName(), true); - handleEnable(mQuietEnable); + mErrorRecoveryRetryCounter++; + Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count=" + + mErrorRecoveryRetryCounter); + if (mErrorRecoveryRetryCounter < MAX_ERROR_RESTART_RETRIES) { + /* Enable without persisting the setting as + it doesnt change when IBluetooth + service restarts */ + mEnable = true; + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED, + mContext.getPackageName(), true); + handleEnable(mQuietEnable); + } else { + Slog.e(TAG, "Reach maximum retry to restart Bluetooth!"); + } break; } case MESSAGE_TIMEOUT_BIND: { @@ -2332,13 +2338,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mEnable = false; - if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { - // Send a Bluetooth Restart message to reenable bluetooth - Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); - } else { - // todo: notify user to power down and power up phone to make bluetooth work. - } + // Send a Bluetooth Restart message to reenable bluetooth + Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); } private boolean isBluetoothDisallowed() { @@ -2374,6 +2376,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + private int getServiceRestartMs() { + return (mErrorRecoveryRetryCounter + 1) * SERVICE_RESTART_TIME_MS; + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) { diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 447ed59a775e..f8b0072e0017 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -16,6 +16,10 @@ package com.android.server; +import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED; + +import static java.util.Arrays.copyOf; + import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.BroadcastReceiver; @@ -286,7 +290,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { switch (msg.what) { case MSG_USER_SWITCHED: { if (VDBG) log("MSG_USER_SWITCHED userId=" + msg.arg1); - int numPhones = TelephonyManager.getDefault().getPhoneCount(); + int numPhones = getTelephonyManager().getPhoneCount(); for (int sub = 0; sub < numPhones; sub++) { TelephonyRegistry.this.notifyCellLocationForSubscriber(sub, mCellLocation[sub]); @@ -367,10 +371,111 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_DEFAULT_SUB, newDefaultPhoneId, newDefaultSubId)); } + } else if (action.equals(ACTION_MULTI_SIM_CONFIG_CHANGED)) { + onMultiSimConfigChanged(); } } }; + private TelephonyManager getTelephonyManager() { + return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + } + + private void onMultiSimConfigChanged() { + int oldNumPhones = mNumPhones; + mNumPhones = getTelephonyManager().getActiveModemCount(); + if (oldNumPhones == mNumPhones) return; + + if (DBG) { + log("TelephonyRegistry: activeModemCount changed from " + oldNumPhones + + " to " + mNumPhones); + } + mCallState = copyOf(mCallState, mNumPhones); + mDataActivity = copyOf(mCallState, mNumPhones); + mDataConnectionState = copyOf(mCallState, mNumPhones); + mDataConnectionNetworkType = copyOf(mCallState, mNumPhones); + mCallIncomingNumber = copyOf(mCallIncomingNumber, mNumPhones); + mServiceState = copyOf(mServiceState, mNumPhones); + mVoiceActivationState = copyOf(mVoiceActivationState, mNumPhones); + mDataActivationState = copyOf(mDataActivationState, mNumPhones); + mUserMobileDataState = copyOf(mUserMobileDataState, mNumPhones); + mSignalStrength = copyOf(mSignalStrength, mNumPhones); + mMessageWaiting = copyOf(mMessageWaiting, mNumPhones); + mCallForwarding = copyOf(mCallForwarding, mNumPhones); + mCellLocation = copyOf(mCellLocation, mNumPhones); + mSrvccState = copyOf(mSrvccState, mNumPhones); + mOtaspMode = copyOf(mOtaspMode, mNumPhones); + mPreciseCallState = copyOf(mPreciseCallState, mNumPhones); + mForegroundCallState = copyOf(mForegroundCallState, mNumPhones); + mBackgroundCallState = copyOf(mBackgroundCallState, mNumPhones); + mRingingCallState = copyOf(mRingingCallState, mNumPhones); + mCallDisconnectCause = copyOf(mCallDisconnectCause, mNumPhones); + mCallPreciseDisconnectCause = copyOf(mCallPreciseDisconnectCause, mNumPhones); + mCallQuality = copyOf(mCallQuality, mNumPhones); + mCallNetworkType = copyOf(mCallNetworkType, mNumPhones); + mCallAttributes = copyOf(mCallAttributes, mNumPhones); + mPreciseDataConnectionState = copyOf(mPreciseDataConnectionState, mNumPhones); + mOutgoingCallEmergencyNumber = copyOf(mOutgoingCallEmergencyNumber, mNumPhones); + mOutgoingSmsEmergencyNumber = copyOf(mOutgoingSmsEmergencyNumber, mNumPhones); + + // ds -> ss switch. + if (mNumPhones < oldNumPhones) { + cutListToSize(mCellInfo, mNumPhones); + cutListToSize(mImsReasonInfo, mNumPhones); + cutListToSize(mPhysicalChannelConfigs, mNumPhones); + return; + } + + // mNumPhones > oldNumPhones: ss -> ds switch + for (int i = oldNumPhones; i < mNumPhones; i++) { + mCallState[i] = TelephonyManager.CALL_STATE_IDLE; + mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE; + mDataConnectionState[i] = TelephonyManager.DATA_UNKNOWN; + mVoiceActivationState[i] = TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN; + mDataActivationState[i] = TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN; + mCallIncomingNumber[i] = ""; + mServiceState[i] = new ServiceState(); + mSignalStrength[i] = new SignalStrength(); + mUserMobileDataState[i] = false; + mMessageWaiting[i] = false; + mCallForwarding[i] = false; + mCellLocation[i] = new Bundle(); + mCellInfo.add(i, null); + mImsReasonInfo.add(i, null); + mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE; + mPhysicalChannelConfigs.add(i, new ArrayList<>()); + mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN; + mCallDisconnectCause[i] = DisconnectCause.NOT_VALID; + mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID; + mCallQuality[i] = new CallQuality(); + mCallAttributes[i] = new CallAttributes(new PreciseCallState(), + TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality()); + mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN; + mPreciseCallState[i] = new PreciseCallState(); + mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; + mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; + mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; + mPreciseDataConnectionState[i] = new PreciseDataConnectionState(); + } + + // Note that location can be null for non-phone builds like + // like the generic one. + CellLocation location = CellLocation.getEmpty(); + if (location != null) { + for (int i = oldNumPhones; i < mNumPhones; i++) { + location.fillInNotifierBundle(mCellLocation[i]); + } + } + } + + private void cutListToSize(List list, int size) { + if (list == null) return; + + while (list.size() > size) { + list.remove(list.size() - 1); + } + } + // we keep a copy of all of the state so we can send it out when folks // register for it // @@ -385,7 +490,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mContext = context; mBatteryStats = BatteryStatsService.getService(); - int numPhones = TelephonyManager.getDefault().getSupportedModemCount(); + int numPhones = getTelephonyManager().getActiveModemCount(); if (DBG) log("TelephonyRegistry: ctor numPhones=" + numPhones); mNumPhones = numPhones; mCallState = new int[numPhones]; @@ -467,6 +572,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED); + filter.addAction(ACTION_MULTI_SIM_CONFIG_CHANGED); log("systemRunning register for intents"); mContext.registerReceiver(mBroadcastReceiver, filter); } @@ -2014,7 +2120,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { final int recordCount = mRecords.size(); pw.println("last known state:"); pw.increaseIndent(); - for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) { + for (int i = 0; i < getTelephonyManager().getPhoneCount(); i++) { pw.println("Phone Id=" + i); pw.increaseIndent(); pw.println("mCallState=" + mCallState[i]); diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java index fe18fbf2a782..fdb14be6b1a4 100644 --- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java @@ -400,13 +400,9 @@ public class RecoverySystemService extends IRecoverySystem.Stub { * Sends a command to the uncrypt service. * * @param command command to send to the uncrypt service - * @throws IOException if the socket is closed or there was an error writing to the socket + * @throws IOException if there was an error writing to the socket */ public void sendCommand(String command) throws IOException { - if (mLocalSocket.isClosed()) { - throw new IOException("socket is closed"); - } - byte[] cmdUtf8 = command.getBytes(StandardCharsets.UTF_8); mOutputStream.writeInt(cmdUtf8.length); mOutputStream.write(cmdUtf8, 0, cmdUtf8.length); @@ -415,25 +411,17 @@ public class RecoverySystemService extends IRecoverySystem.Stub { /** * Reads the status from the uncrypt service which is usually represented as a percentage. * @return an integer representing the percentage completed - * @throws IOException if the socket was closed or there was an error reading the socket + * @throws IOException if there was an error reading the socket */ public int getPercentageUncrypted() throws IOException { - if (mLocalSocket.isClosed()) { - throw new IOException("socket is closed"); - } - return mInputStream.readInt(); } /** * Sends a confirmation to the uncrypt service. - * @throws IOException if the socket was closed or there was an error writing to the socket + * @throws IOException if there was an error writing to the socket */ public void sendAck() throws IOException { - if (mLocalSocket.isClosed()) { - throw new IOException("socket is closed"); - } - mOutputStream.writeInt(0); } diff --git a/telephony/java/com/android/internal/telephony/SmsConstants.java b/telephony/common/com/android/internal/telephony/SmsConstants.java index 19f52b0ef429..19f52b0ef429 100644 --- a/telephony/java/com/android/internal/telephony/SmsConstants.java +++ b/telephony/common/com/android/internal/telephony/SmsConstants.java diff --git a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java index 0d33af639113..367aad1837ce 100644 --- a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java +++ b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java @@ -359,15 +359,41 @@ public class SmsNumberUtils { return NP_NONE; } + /** + * This function checks if the passed in string conforms to the NANP format + * i.e. NXX-NXX-XXXX, N is any digit 2-9 and X is any digit 0-9 + */ private static boolean isNANP(String number) { + boolean retVal = false; + if (number.length() == NANP_MEDIUM_LENGTH || (number.length() == NANP_LONG_LENGTH && number.startsWith(NANP_NDD))) { + if (number.length() == NANP_LONG_LENGTH) { number = number.substring(1); } - return (PhoneNumberUtils.isNanp(number)); + + if (isTwoToNine(number.charAt(0)) && + isTwoToNine(number.charAt(3))) { + retVal = true; + for (int i=1; i<NANP_MEDIUM_LENGTH; i++ ) { + char c=number.charAt(i); + if (!PhoneNumberUtils.isISODigit(c)) { + retVal = false; + break; + } + } + } + } + return retVal; + } + + private static boolean isTwoToNine (char c) { + if (c >= '2' && c <= '9') { + return true; + } else { + return false; } - return false; } /** @@ -573,9 +599,9 @@ public class SmsNumberUtils { int networkType = -1; int phoneType = telephonyManager.getPhoneType(); - if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { + if (phoneType == TelephonyManager.PHONE_TYPE_GSM) { networkType = GSM_UMTS_NETWORK; - } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { + } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) { if (isInternationalRoaming(telephonyManager)) { networkType = CDMA_ROAMING_NETWORK; } else { diff --git a/telephony/common/com/google/android/mms/pdu/PduPersister.java b/telephony/common/com/google/android/mms/pdu/PduPersister.java index 95ae4096ed86..b237705274da 100755 --- a/telephony/common/com/google/android/mms/pdu/PduPersister.java +++ b/telephony/common/com/google/android/mms/pdu/PduPersister.java @@ -291,15 +291,11 @@ public class PduPersister { @UnsupportedAppUsage private final ContentResolver mContentResolver; private final DrmManagerClient mDrmManagerClient; - @UnsupportedAppUsage - private final TelephonyManager mTelephonyManager; private PduPersister(Context context) { mContext = context; mContentResolver = context.getContentResolver(); mDrmManagerClient = new DrmManagerClient(context); - mTelephonyManager = (TelephonyManager)context - .getSystemService(Context.TELEPHONY_SERVICE); } /** Get(or create if not exist) an instance of PduPersister */ @@ -1453,7 +1449,8 @@ public class PduPersister { if (excludeMyNumber) { // Build a list of my phone numbers from the various sims. for (int subid : subscriptionManager.getActiveSubscriptionIdList()) { - final String myNumber = mTelephonyManager.getLine1Number(subid); + final String myNumber = mContext.getSystemService(TelephonyManager.class). + createForSubscriptionId(subid).getLine1Number(); if (myNumber != null) { myPhoneNumbers.add(myNumber); } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 3c890a18e344..3e51ff6e75d2 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -2971,6 +2971,7 @@ public class SubscriptionManager { * permission or had carrier privilege permission on the subscription. * {@link TelephonyManager#hasCarrierPrivileges()} * + * @throws IllegalStateException if Telephony service is in bad state. * @throws SecurityException if the caller doesn't meet the requirements * outlined above. * diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index e99465d58764..2925b1154f14 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1692,8 +1692,8 @@ public class TelephonyManager { * * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier - * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a - * managed profile on the device; for more details see <a + * privileges (see {@link #hasCarrierPrivileges}) on any active subscription. The profile owner + * is an app that owns a managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. * @@ -1733,8 +1733,8 @@ public class TelephonyManager { * * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier - * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a - * managed profile on the device; for more details see <a + * privileges (see {@link #hasCarrierPrivileges}) on any active subscription. The profile owner + * is an app that owns a managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. * @@ -1793,7 +1793,8 @@ public class TelephonyManager { * <li>The caller holds the READ_PRIVILEGED_PHONE_STATE permission.</li> * <li>If the caller is the device or profile owner, the caller holds the * {@link Manifest.permission#READ_PHONE_STATE} permission.</li> - * <li>The caller has carrier privileges (see {@link #hasCarrierPrivileges()}.</li> + * <li>The caller has carrier privileges (see {@link #hasCarrierPrivileges()} on any + * active subscription.</li> * <li>The caller is the default SMS app for the device.</li> * </ul> * <p>The profile owner is an app that owns a managed profile on the device; for more details @@ -1862,8 +1863,8 @@ public class TelephonyManager { * * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier - * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a - * managed profile on the device; for more details see <a + * privileges (see {@link #hasCarrierPrivileges}) on any active subscription. The profile owner + * is an app that owns a managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. * @@ -1889,8 +1890,8 @@ public class TelephonyManager { * * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier - * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a - * managed profile on the device; for more details see <a + * privileges (see {@link #hasCarrierPrivileges}) on any active subscription. The profile owner + * is an app that owns a managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. * @@ -7593,20 +7594,20 @@ public class TelephonyManager { * {@link CarrierConfigManager#KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT}. If * the carrier does not support this mode, this function will always return false. * - * @return true if this device is in emergency SMS mode, false otherwise. + * @return {@code true} if this device is in emergency SMS mode, {@code false} otherwise. * * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isInEmergencySmsMode() { - try { ITelephony telephony = getITelephony(); if (telephony != null) { return telephony.isInEmergencySmsMode(); } } catch (RemoteException ex) { - Rlog.e(TAG, "getNetworkSelectionMode RemoteException", ex); + Rlog.e(TAG, "isInEmergencySmsMode RemoteException", ex); } return false; } diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java index 67103bfddce1..8a852eea5610 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java @@ -237,9 +237,10 @@ public final class TelephonyPermissions { * <ul> * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier - * access check, or the calling package has carrier privileges. - * <li>throw SecurityException: if the caller does not meet any of the requirements and is - * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission. + * access check, or the calling package has carrier privileges on any active subscription. + * <li>throw SecurityException: if the caller does not meet any of the requirements and is + * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission + * or carrier privileges of any active subscription. * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE * permission. In this case the caller would expect to have access to the device * identifiers so false is returned instead of throwing a SecurityException to indicate @@ -259,10 +260,10 @@ public final class TelephonyPermissions { * <ul> * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier - * access check, or the calling package has carrier privileges. + * access check, or the calling package has carrier privileges on any active subscription. * <li>throw SecurityException: if the caller does not meet any of the requirements and is * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission - * or carrier privileges. + * or carrier privileges of any active subscription. * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE * permission or carrier privileges. In this case the caller would expect to have access * to the device identifiers so false is returned instead of throwing a SecurityException @@ -271,8 +272,8 @@ public final class TelephonyPermissions { */ public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId, String callingPackage, String message) { - return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId, - Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); + return checkPrivilegedReadPermissionOrCarrierPrivilegePermission( + context, subId, callingPackage, message, true); } /** @@ -282,7 +283,7 @@ public final class TelephonyPermissions { * <ul> * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier - * access check, or the calling package has carrier privileges. + * access check, or the calling package has carrier privileges on specified subscription. * <li>throw SecurityException: if the caller does not meet any of the requirements and is * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission. * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE @@ -293,21 +294,33 @@ public final class TelephonyPermissions { */ public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId, String callingPackage, String message) { - return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId, - Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); + return checkPrivilegedReadPermissionOrCarrierPrivilegePermission( + context, subId, callingPackage, message, false); } /** * Checks whether the app with the given pid/uid can read device identifiers. * - * @returns true if the caller has the READ_PRIVILEGED_PHONE_STATE permission or the calling - * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier access - * check. + * <p>This method behaves in one of the following ways: + * <ul> + * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling + * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier + * access check; or the calling package has carrier privileges on the specified + * subscription; or allowCarrierPrivilegeOnAnySub is true and has carrier privilege on + * any active subscription. + * <li>throw SecurityException: if the caller does not meet any of the requirements and is + * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission. + * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE + * permission. In this case the caller would expect to have access to the device + * identifiers so false is returned instead of throwing a SecurityException to indicate + * the calling function should return dummy data. + * </ul> */ - @VisibleForTesting - public static boolean checkReadDeviceIdentifiers(Context context, - Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, - String callingPackage, String message) { + private static boolean checkPrivilegedReadPermissionOrCarrierPrivilegePermission( + Context context, int subId, String callingPackage, String message, + boolean allowCarrierPrivilegeOnAnySub) { + int uid = Binder.getCallingUid(); + int pid = Binder.getCallingPid(); // Allow system and root access to the device identifiers. final int appId = UserHandle.getAppId(uid); if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) { @@ -318,10 +331,17 @@ public final class TelephonyPermissions { uid) == PackageManager.PERMISSION_GRANTED) { return true; } - // If the calling package has carrier privileges for any subscription then allow access. - if (checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid)) { + + // If the calling package has carrier privileges for specified sub, then allow access. + if (checkCarrierPrivilegeForSubId(subId)) return true; + + // If the calling package has carrier privileges for any subscription + // and allowCarrierPrivilegeOnAnySub is set true, then allow access. + if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId( + context, TELEPHONY_SUPPLIER, uid)) { return true; } + // if the calling package is not null then perform the DevicePolicyManager device / // profile owner and Appop checks. if (callingPackage != null) { @@ -347,7 +367,7 @@ public final class TelephonyPermissions { } } return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage, - message); + message); } /** diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java index 1de6260f3719..45b236c307c3 100644 --- a/test-mock/src/android/test/mock/MockContext.java +++ b/test-mock/src/android/test/mock/MockContext.java @@ -535,6 +535,14 @@ public class MockContext extends Context { /** @hide */ @Override + @SystemApi + public Intent registerReceiverForAllUsers(BroadcastReceiver receiver, + IntentFilter filter, String broadcastPermission, Handler scheduler) { + throw new UnsupportedOperationException(); + } + + /** @hide */ + @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { throw new UnsupportedOperationException(); |