diff options
5 files changed, 117 insertions, 76 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java index fb3f382af192..e91d697d4b86 100644 --- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java +++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java @@ -324,6 +324,7 @@ class LicenseHtmlGeneratorFromXml { if (!TextUtils.isEmpty(noticeHeader)) { writer.println(noticeHeader); + writer.println("<br/>"); } int count = 0; diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 77a54a568859..1afda6572a21 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -1578,57 +1578,62 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return; } - synchronized (mRecords) { - String str = "notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId - + " state=" + state; - if (VDBG) { - log(str); - } - mLocalLog.log(str); - // for service state updates, don't notify clients when subId is invalid. This prevents - // us from sending incorrect notifications like b/133140128 - // In the future, we can remove this logic for every notification here and add a - // callback so listeners know when their PhoneStateListener's subId becomes invalid, but - // for now we use the simplest fix. - if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) { - mServiceState[phoneId] = state; + final long callingIdentity = Binder.clearCallingIdentity(); + try { + synchronized (mRecords) { + String str = "notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + + phoneId + " state=" + state; + if (VDBG) { + log(str); + } + mLocalLog.log(str); + // for service state updates, don't notify clients when subId is invalid. This + // prevents us from sending incorrect notifications like b/133140128 + // In the future, we can remove this logic for every notification here and add a + // callback so listeners know when their PhoneStateListener's subId becomes invalid, + // but for now we use the simplest fix. + if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) { + mServiceState[phoneId] = state; - for (Record r : mRecords) { - if (VDBG) { - log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId - + " phoneId=" + phoneId + " state=" + state); - } - if (r.matchTelephonyCallbackEvent( - TelephonyCallback.EVENT_SERVICE_STATE_CHANGED) - && idMatch(r, subId, phoneId)) { + for (Record r : mRecords) { + if (VDBG) { + log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId + + " phoneId=" + phoneId + " state=" + state); + } + if (r.matchTelephonyCallbackEvent( + TelephonyCallback.EVENT_SERVICE_STATE_CHANGED) + && idMatch(r, subId, phoneId)) { - try { - ServiceState stateToSend; - if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { - stateToSend = new ServiceState(state); - } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) { - stateToSend = state.createLocationInfoSanitizedCopy(false); - } else { - stateToSend = state.createLocationInfoSanitizedCopy(true); - } - if (DBG) { - log("notifyServiceStateForSubscriber: callback.onSSC r=" + r - + " subId=" + subId + " phoneId=" + phoneId - + " state=" + state); + try { + ServiceState stateToSend; + if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { + stateToSend = new ServiceState(state); + } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) { + stateToSend = state.createLocationInfoSanitizedCopy(false); + } else { + stateToSend = state.createLocationInfoSanitizedCopy(true); + } + if (DBG) { + log("notifyServiceStateForSubscriber: callback.onSSC r=" + r + + " subId=" + subId + " phoneId=" + phoneId + + " state=" + stateToSend); + } + r.callback.onServiceStateChanged(stateToSend); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); } - r.callback.onServiceStateChanged(stateToSend); - } catch (RemoteException ex) { - mRemoveList.add(r.binder); } } + } else { + log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId + + " or subId=" + subId); } - } else { - log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId - + " or subId=" + subId); + handleRemoveListLocked(); } - handleRemoveListLocked(); + broadcastServiceStateChanged(state, phoneId, subId); + } finally { + Binder.restoreCallingIdentity(callingIdentity); } - broadcastServiceStateChanged(state, phoneId, subId); } public void notifySimActivationStateChangedForPhoneId(int phoneId, int subId, @@ -3161,13 +3166,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { public static final String ACTION_SIGNAL_STRENGTH_CHANGED = "android.intent.action.SIG_STR"; private void broadcastServiceStateChanged(ServiceState state, int phoneId, int subId) { - final long ident = Binder.clearCallingIdentity(); try { mBatteryStats.notePhoneState(state.getState()); } catch (RemoteException re) { // Can't do much - } finally { - Binder.restoreCallingIdentity(ident); } // Send the broadcast exactly once to all possible disjoint sets of apps. @@ -3184,8 +3186,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { // - Sanitized ServiceState sent to all other apps with READ_PHONE_STATE // - Sanitized ServiceState sent to all other apps with READ_PRIVILEGED_PHONE_STATE but not // READ_PHONE_STATE - if (Binder.withCleanCallingIdentity(() -> - LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId()))) { + if (LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId())) { Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false); mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( fullIntent, diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java index f586126196dd..7d148f6225be 100644 --- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java +++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java @@ -17,6 +17,7 @@ package com.android.server.security.rkp; import android.os.CancellationSignal; +import android.os.IBinder; import android.os.OperationCanceledException; import android.os.OutcomeReceiver; import android.security.rkp.IGetKeyCallback; @@ -39,23 +40,23 @@ import java.util.concurrent.Executor; */ final class RemoteProvisioningRegistration extends IRegistration.Stub { static final String TAG = RemoteProvisioningService.TAG; - private final ConcurrentHashMap<IGetKeyCallback, CancellationSignal> mGetKeyOperations = + private final ConcurrentHashMap<IBinder, CancellationSignal> mGetKeyOperations = new ConcurrentHashMap<>(); - private final Set<IStoreUpgradedKeyCallback> mStoreUpgradedKeyOperations = - ConcurrentHashMap.newKeySet(); + private final Set<IBinder> mStoreUpgradedKeyOperations = ConcurrentHashMap.newKeySet(); private final RegistrationProxy mRegistration; private final Executor mExecutor; private class GetKeyReceiver implements OutcomeReceiver<RemotelyProvisionedKey, Exception> { IGetKeyCallback mCallback; + GetKeyReceiver(IGetKeyCallback callback) { mCallback = callback; } @Override public void onResult(RemotelyProvisionedKey result) { - mGetKeyOperations.remove(mCallback); - Log.i(TAG, "Successfully fetched key for client " + mCallback.hashCode()); + mGetKeyOperations.remove(mCallback.asBinder()); + Log.i(TAG, "Successfully fetched key for client " + mCallback.asBinder().hashCode()); android.security.rkp.RemotelyProvisionedKey parcelable = new android.security.rkp.RemotelyProvisionedKey(); parcelable.keyBlob = result.getKeyBlob(); @@ -65,19 +66,21 @@ final class RemoteProvisioningRegistration extends IRegistration.Stub { @Override public void onError(Exception e) { - mGetKeyOperations.remove(mCallback); + mGetKeyOperations.remove(mCallback.asBinder()); if (e instanceof OperationCanceledException) { - Log.i(TAG, "Operation cancelled for client " + mCallback.hashCode()); + Log.i(TAG, "Operation cancelled for client " + mCallback.asBinder().hashCode()); wrapCallback(mCallback::onCancel); } else if (e instanceof RkpProxyException) { - Log.e(TAG, "RKP error fetching key for client " + mCallback.hashCode() + ": " + Log.e(TAG, "RKP error fetching key for client " + mCallback.asBinder().hashCode() + + ": " + e.getMessage()); RkpProxyException rkpException = (RkpProxyException) e; wrapCallback(() -> mCallback.onError(toGetKeyError(rkpException), e.getMessage())); } else { - Log.e(TAG, "Unknown error fetching key for client " + mCallback.hashCode() + ": " - + e.getMessage()); + Log.e(TAG, + "Unknown error fetching key for client " + mCallback.asBinder().hashCode() + + ": " + e.getMessage()); wrapCallback(() -> mCallback.onError(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN, e.getMessage())); } @@ -108,20 +111,23 @@ final class RemoteProvisioningRegistration extends IRegistration.Stub { @Override public void getKey(int keyId, IGetKeyCallback callback) { CancellationSignal cancellationSignal = new CancellationSignal(); - if (mGetKeyOperations.putIfAbsent(callback, cancellationSignal) != null) { - Log.e(TAG, "Client can only request one call at a time " + callback.hashCode()); + if (mGetKeyOperations.putIfAbsent(callback.asBinder(), cancellationSignal) != null) { + Log.e(TAG, + "Client can only request one call at a time " + callback.asBinder().hashCode()); throw new IllegalArgumentException( "Callback is already associated with an existing operation: " - + callback.hashCode()); + + callback.asBinder().hashCode()); } try { - Log.i(TAG, "Fetching key " + keyId + " for client " + callback.hashCode()); + Log.i(TAG, "Fetching key " + keyId + " for client " + callback.asBinder().hashCode()); mRegistration.getKeyAsync(keyId, cancellationSignal, mExecutor, new GetKeyReceiver(callback)); } catch (Exception e) { - Log.e(TAG, "getKeyAsync threw an exception for client " + callback.hashCode(), e); - mGetKeyOperations.remove(callback); + Log.e(TAG, + "getKeyAsync threw an exception for client " + callback.asBinder().hashCode(), + e); + mGetKeyOperations.remove(callback.asBinder()); wrapCallback(() -> callback.onError(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN, e.getMessage())); } @@ -129,23 +135,23 @@ final class RemoteProvisioningRegistration extends IRegistration.Stub { @Override public void cancelGetKey(IGetKeyCallback callback) { - CancellationSignal cancellationSignal = mGetKeyOperations.remove(callback); + CancellationSignal cancellationSignal = mGetKeyOperations.remove(callback.asBinder()); if (cancellationSignal == null) { throw new IllegalArgumentException( - "Invalid client in cancelGetKey: " + callback.hashCode()); + "Invalid client in cancelGetKey: " + callback.asBinder().hashCode()); } - Log.i(TAG, "Requesting cancellation for client " + callback.hashCode()); + Log.i(TAG, "Requesting cancellation for client " + callback.asBinder().hashCode()); cancellationSignal.cancel(); } @Override public void storeUpgradedKeyAsync(byte[] oldKeyBlob, byte[] newKeyBlob, IStoreUpgradedKeyCallback callback) { - if (!mStoreUpgradedKeyOperations.add(callback)) { + if (!mStoreUpgradedKeyOperations.add(callback.asBinder())) { throw new IllegalArgumentException( "Callback is already associated with an existing operation: " - + callback.hashCode()); + + callback.asBinder().hashCode()); } try { @@ -153,20 +159,20 @@ final class RemoteProvisioningRegistration extends IRegistration.Stub { new OutcomeReceiver<>() { @Override public void onResult(Void result) { - mStoreUpgradedKeyOperations.remove(callback); + mStoreUpgradedKeyOperations.remove(callback.asBinder()); wrapCallback(callback::onSuccess); } @Override public void onError(Exception e) { - mStoreUpgradedKeyOperations.remove(callback); + mStoreUpgradedKeyOperations.remove(callback.asBinder()); wrapCallback(() -> callback.onError(e.getMessage())); } }); } catch (Exception e) { Log.e(TAG, "storeUpgradedKeyAsync threw an exception for client " - + callback.hashCode(), e); - mStoreUpgradedKeyOperations.remove(callback); + + callback.asBinder().hashCode(), e); + mStoreUpgradedKeyOperations.remove(callback.asBinder()); wrapCallback(() -> callback.onError(e.getMessage())); } } diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java index 97e463646fdc..2bd7383ddde0 100644 --- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java +++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java @@ -61,7 +61,7 @@ public class RemoteProvisioningService extends SystemService { try { mCallback.onSuccess(new RemoteProvisioningRegistration(registration, mExecutor)); } catch (RemoteException e) { - Log.e(TAG, "Error calling success callback " + mCallback.hashCode(), e); + Log.e(TAG, "Error calling success callback " + mCallback.asBinder().hashCode(), e); } } @@ -70,7 +70,7 @@ public class RemoteProvisioningService extends SystemService { try { mCallback.onError(error.toString()); } catch (RemoteException e) { - Log.e(TAG, "Error calling error callback " + mCallback.hashCode(), e); + Log.e(TAG, "Error calling error callback " + mCallback.asBinder().hashCode(), e); } } } diff --git a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java index 1dcd0b936c86..df7be515774a 100644 --- a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java +++ b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java @@ -23,8 +23,10 @@ import static org.mockito.AdditionalAnswers.answerVoid; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.argThat; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.contains; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; @@ -32,6 +34,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import android.os.Binder; import android.os.CancellationSignal; import android.os.OperationCanceledException; import android.os.OutcomeReceiver; @@ -101,8 +104,10 @@ public class RemoteProvisioningRegistrationTest { .when(mRegistrationProxy).getKeyAsync(eq(42), any(), any(), any()); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.getKey(42, callback); verify(callback).onSuccess(matches(expectedKey)); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -114,8 +119,10 @@ public class RemoteProvisioningRegistrationTest { executor.execute(() -> receiver.onError(expectedException)))) .when(mRegistrationProxy).getKeyAsync(eq(0), any(), any(), any()); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.getKey(0, callback); verify(callback).onError(eq(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN), eq("oops!")); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -140,18 +147,28 @@ public class RemoteProvisioningRegistrationTest { executor.execute(() -> receiver.onError(expectedException)))) .when(mRegistrationProxy).getKeyAsync(eq(0), any(), any(), any()); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.getKey(0, callback); verify(callback).onError(eq(error), contains(errorField.getName())); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } } @Test public void getKeyCancelDuringProxyOperation() throws Exception { + final Binder theBinder = new Binder(); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(theBinder).when(callback).asBinder(); doAnswer( answerGetKeyAsync((keyId, cancelSignal, executor, receiver) -> { - mRegistration.cancelGetKey(callback); + // Use a different callback object to ensure that the callback equivalence + // relies on the actual IBinder object. + IGetKeyCallback differentCallback = mock(IGetKeyCallback.class); + doReturn(theBinder).when(differentCallback).asBinder(); + mRegistration.cancelGetKey(differentCallback); + verify(differentCallback, atLeastOnce()).asBinder(); + verifyNoMoreInteractions(differentCallback); assertThat(cancelSignal.isCanceled()).isTrue(); executor.execute(() -> receiver.onError(new OperationCanceledException())); })) @@ -159,18 +176,21 @@ public class RemoteProvisioningRegistrationTest { mRegistration.getKey(Integer.MAX_VALUE, callback); verify(callback).onCancel(); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @Test public void cancelGetKeyWithInvalidCallback() throws Exception { IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback)); } @Test public void getKeyRejectsDuplicateCallback() throws Exception { IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); doAnswer( answerGetKeyAsync((keyId, cancelSignal, executor, receiver) -> { assertThrows(IllegalArgumentException.class, () -> @@ -181,12 +201,14 @@ public class RemoteProvisioningRegistrationTest { mRegistration.getKey(0, callback); verify(callback, times(1)).onSuccess(any()); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @Test public void getKeyCancelAfterCompleteFails() throws Exception { IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); doAnswer( answerGetKeyAsync((keyId, cancelSignal, executor, receiver) -> executor.execute(() -> @@ -197,6 +219,7 @@ public class RemoteProvisioningRegistrationTest { mRegistration.getKey(Integer.MIN_VALUE, callback); verify(callback).onSuccess(any()); assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback)); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -208,10 +231,12 @@ public class RemoteProvisioningRegistrationTest { .getKeyAsync(anyInt(), any(), any(), any()); IGetKeyCallback callback = mock(IGetKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.getKey(0, callback); verify(callback).onError(eq(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN), eq(expectedException.getMessage())); assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback)); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -224,8 +249,10 @@ public class RemoteProvisioningRegistrationTest { .storeUpgradedKeyAsync(any(), any(), any(), any()); IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback); verify(callback).onSuccess(); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -239,8 +266,10 @@ public class RemoteProvisioningRegistrationTest { .storeUpgradedKeyAsync(any(), any(), any(), any()); IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback); verify(callback).onError(errorString); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @@ -252,14 +281,17 @@ public class RemoteProvisioningRegistrationTest { .storeUpgradedKeyAsync(any(), any(), any(), any()); IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback); verify(callback).onError(errorString); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } @Test public void storeUpgradedKeyDuplicateCallback() throws Exception { IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class); + doReturn(new Binder()).when(callback).asBinder(); doAnswer( answerStoreUpgradedKeyAsync((oldBlob, newBlob, executor, receiver) -> { @@ -273,6 +305,7 @@ public class RemoteProvisioningRegistrationTest { mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback); verify(callback).onSuccess(); + verify(callback, atLeastOnce()).asBinder(); verifyNoMoreInteractions(callback); } |