summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoshan Pius <rpius@google.com>2022-06-15 10:38:17 -0700
committerRoshan Pius <rpius@google.com>2022-07-06 16:33:29 +0000
commit1870d114c5e084372e7f99b1c20fb4090cffc160 (patch)
treeaf87981d43e7541180b5c63d22170faea0092adc
parent32989487c3669fb428ed3d0fb8efd98132cbf479 (diff)
downloadUwb-1870d114c5e084372e7f99b1c20fb4090cffc160.tar.gz
uwb(service): Reconfigure all ongoing 3p app sessions on moving to bg
When app moves to bg, the apps will not get range notifications (even though the session is not terminated). We restore the notifications when they move back to fg. Bug: 235488235 Test: atest ServiceUwbTests Test: Manually tested the notification setting change when 3p app is moved to bg/fg using HelloUwb Change-Id: Ia9b9f9452cb2ac9a3fd3c32f05cf4d4aaaa684c9
-rw-r--r--service/java/com/android/server/uwb/UwbInjector.java12
-rw-r--r--service/java/com/android/server/uwb/UwbSessionManager.java140
-rw-r--r--service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java78
3 files changed, 199 insertions, 31 deletions
diff --git a/service/java/com/android/server/uwb/UwbInjector.java b/service/java/com/android/server/uwb/UwbInjector.java
index 11453a78..cf2f5e17 100644
--- a/service/java/com/android/server/uwb/UwbInjector.java
+++ b/service/java/com/android/server/uwb/UwbInjector.java
@@ -114,7 +114,9 @@ public class UwbInjector {
UwbSessionManager uwbSessionManager =
new UwbSessionManager(uwbConfigurationManager, mNativeUwbManager, mUwbMetrics,
uwbSessionNotificationManager, this,
- mContext.getSystemService(AlarmManager.class), mLooper);
+ mContext.getSystemService(AlarmManager.class),
+ mContext.getSystemService(ActivityManager.class),
+ mLooper);
mUwbService = new UwbServiceCore(mContext, mNativeUwbManager, mUwbMetrics,
mUwbCountryCode, uwbSessionManager, uwbConfigurationManager, this, mLooper);
mSystemBuildProperties = new SystemBuildProperties();
@@ -350,10 +352,14 @@ public class UwbInjector {
}
/** Helper method to check if the app is from foreground app/service. */
+ public static boolean isForegroundAppOrServiceImportance(int importance) {
+ return importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
+ }
+
+ /** Helper method to check if the app is from foreground app/service. */
public boolean isForegroundAppOrService(int uid, @NonNull String packageName) {
try {
- return getPackageImportance(uid, packageName)
- <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
+ return isForegroundAppOrServiceImportance(getPackageImportance(uid, packageName));
} catch (SecurityException e) {
Log.e(TAG, "Failed to retrieve the app importance", e);
return false;
diff --git a/service/java/com/android/server/uwb/UwbSessionManager.java b/service/java/com/android/server/uwb/UwbSessionManager.java
index e200d0bd..0a1cafaa 100644
--- a/service/java/com/android/server/uwb/UwbSessionManager.java
+++ b/service/java/com/android/server/uwb/UwbSessionManager.java
@@ -15,6 +15,8 @@
*/
package com.android.server.uwb;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
+
import static com.android.server.uwb.data.UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS;
import static com.google.uwb.support.fira.FiraParams.MULTICAST_LIST_UPDATE_ACTION_ADD;
@@ -22,8 +24,10 @@ import static com.google.uwb.support.fira.FiraParams.MULTICAST_LIST_UPDATE_ACTIO
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.AlarmManager;
import android.content.AttributionSource;
+import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -91,6 +95,9 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
// TODO: don't expose the internal field for testing.
@VisibleForTesting
final ConcurrentHashMap<Integer, UwbSession> mSessionTable = new ConcurrentHashMap();
+ final ConcurrentHashMap<Integer, List<UwbSession>> mNonPrivilegedUidToFiraSessionsTable =
+ new ConcurrentHashMap();
+ private final ActivityManager mActivityManager;
private final NativeUwbManager mNativeUwbManager;
private final UwbMetrics mUwbMetrics;
private final UwbConfigurationManager mConfigurationManager;
@@ -98,12 +105,15 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
private final UwbInjector mUwbInjector;
private final AlarmManager mAlarmManager;
private final int mMaxSessionNumber;
+ private final Looper mLooper;
private final EventTask mEventTask;
- public UwbSessionManager(UwbConfigurationManager uwbConfigurationManager,
+ public UwbSessionManager(
+ UwbConfigurationManager uwbConfigurationManager,
NativeUwbManager nativeUwbManager, UwbMetrics uwbMetrics,
UwbSessionNotificationManager uwbSessionNotificationManager,
- UwbInjector uwbInjector, AlarmManager alarmManager, Looper serviceLooper) {
+ UwbInjector uwbInjector, AlarmManager alarmManager, ActivityManager activityManager,
+ Looper serviceLooper) {
mNativeUwbManager = nativeUwbManager;
mNativeUwbManager.setSessionListener(this);
mUwbMetrics = uwbMetrics;
@@ -111,8 +121,42 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
mSessionNotificationManager = uwbSessionNotificationManager;
mUwbInjector = uwbInjector;
mAlarmManager = alarmManager;
+ mActivityManager = activityManager;
mMaxSessionNumber = mNativeUwbManager.getMaxSessionNumber();
+ mLooper = serviceLooper;
mEventTask = new EventTask(serviceLooper);
+ registerUidImportanceTransitions();
+ }
+
+
+ // Detect UIDs going foreground/background
+ private void registerUidImportanceTransitions() {
+ Handler handler = new Handler(mLooper);
+ mActivityManager.addOnUidImportanceListener(new ActivityManager.OnUidImportanceListener() {
+ @Override
+ public void onUidImportance(final int uid, final int importance) {
+ handler.post(() -> {
+ List<UwbSession> uwbSessions = mNonPrivilegedUidToFiraSessionsTable.get(uid);
+ if (uwbSessions == null) {
+ // Not a uid in the watch list
+ return;
+ }
+ boolean newModeHasNonPrivilegedFgApp =
+ UwbInjector.isForegroundAppOrServiceImportance(importance);
+ for (UwbSession uwbSession : uwbSessions) {
+ // already at correct state.
+ if (newModeHasNonPrivilegedFgApp == uwbSession.hasNonPrivilegedFgApp()) {
+ continue;
+ }
+ uwbSession.setHasNonPrivilegedFgApp(newModeHasNonPrivilegedFgApp);
+ // Reconfigure the session based on the new fg/bg state.
+ Log.i(TAG, "App state change. IsFg: " + newModeHasNonPrivilegedFgApp
+ + ". Reconfiguring session ntf control");
+ uwbSession.reconfigureFiraSessionOnFgStateChange();
+ }
+ });
+ }
+ }, IMPORTANCE_FOREGROUND_SERVICE);
}
private static boolean hasAllRangingResultError(@NonNull UwbRangingData rangingData) {
@@ -222,15 +266,23 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
// Check the attribution source chain to ensure that there are no 3p apps which are not in
// fg which can receive the ranging results.
AttributionSource nonPrivilegedAppAttrSource =
- uwbSession.hasAnyNonPrivilegedAppInAttributionSource();
- if (nonPrivilegedAppAttrSource != null && !mUwbInjector.isForegroundAppOrService(
- nonPrivilegedAppAttrSource.getUid(), nonPrivilegedAppAttrSource.getPackageName())) {
- Log.e(TAG, "Found a non fg 3p app/service in the attribution source of request: "
+ uwbSession.getAnyNonPrivilegedAppInAttributionSource();
+ if (nonPrivilegedAppAttrSource != null) {
+ Log.d(TAG, "Found a non fg 3p app/service in the attribution source of request: "
+ nonPrivilegedAppAttrSource);
- Log.e(TAG, "openRanging - System policy disallows for non fg 3p apps");
- rangingCallbacks.onRangingOpenFailed(sessionHandle,
- RangingChangeReason.SYSTEM_POLICY, new PersistableBundle());
- return;
+ // TODO(b/211445008): Move this operation to uwb thread.
+ long identity = Binder.clearCallingIdentity();
+ boolean hasNonPrivilegedFgApp = mUwbInjector.isForegroundAppOrService(
+ nonPrivilegedAppAttrSource.getUid(),
+ nonPrivilegedAppAttrSource.getPackageName());
+ Binder.restoreCallingIdentity(identity);
+ uwbSession.setHasNonPrivilegedFgApp(hasNonPrivilegedFgApp);
+ if (!hasNonPrivilegedFgApp) {
+ Log.e(TAG, "openRanging - System policy disallows for non fg 3p apps");
+ rangingCallbacks.onRangingOpenFailed(sessionHandle,
+ RangingChangeReason.SYSTEM_POLICY, new PersistableBundle());
+ return;
+ }
}
if (isExistedSession(sessionId)) {
Log.i(TAG, "Duplicated sessionId");
@@ -270,6 +322,7 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
}
mSessionTable.put(sessionId, uwbSession);
+ addToNonPrivilegedUidToFiraSessionTableIfNecessary(uwbSession);
mEventTask.execute(SESSION_OPEN_RANGING, uwbSession);
return;
}
@@ -477,10 +530,47 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
void removeSession(UwbSession uwbSession) {
if (uwbSession != null) {
uwbSession.getBinder().unlinkToDeath(uwbSession, 0);
+ removeFromNonPrivilegedUidToFiraSessionTableIfNecessary(uwbSession);
mSessionTable.remove(uwbSession.getSessionId());
}
}
+ void addToNonPrivilegedUidToFiraSessionTableIfNecessary(@NonNull UwbSession uwbSession) {
+ if (getSessionType(uwbSession.getProtocolName()) == UwbUciConstants.SESSION_TYPE_RANGING) {
+ AttributionSource nonPrivilegedAppAttrSource =
+ uwbSession.getAnyNonPrivilegedAppInAttributionSource();
+ if (nonPrivilegedAppAttrSource != null) {
+ Log.d(TAG, "Detected start of non privileged FIRA session from "
+ + nonPrivilegedAppAttrSource);
+ List<UwbSession> sessions = mNonPrivilegedUidToFiraSessionsTable.computeIfAbsent(
+ nonPrivilegedAppAttrSource.getUid(), v -> new ArrayList<>());
+ sessions.add(uwbSession);
+ }
+ }
+ }
+
+ void removeFromNonPrivilegedUidToFiraSessionTableIfNecessary(@NonNull UwbSession uwbSession) {
+ if (getSessionType(uwbSession.getProtocolName()) == UwbUciConstants.SESSION_TYPE_RANGING) {
+ AttributionSource nonPrivilegedAppAttrSource =
+ uwbSession.getAnyNonPrivilegedAppInAttributionSource();
+ if (nonPrivilegedAppAttrSource != null) {
+ Log.d(TAG, "Detected end of non privileged FIRA session from "
+ + nonPrivilegedAppAttrSource);
+ List<UwbSession> sessions = mNonPrivilegedUidToFiraSessionsTable.get(
+ nonPrivilegedAppAttrSource.getUid());
+ if (sessions == null) {
+ Log.wtf(TAG, "No sessions found for uid: "
+ + nonPrivilegedAppAttrSource.getUid());
+ return;
+ }
+ sessions.remove(uwbSession);
+ if (sessions.isEmpty()) {
+ mNonPrivilegedUidToFiraSessionsTable.remove(
+ nonPrivilegedAppAttrSource.getUid());
+ }
+ }
+ }
+ }
private class EventTask extends Handler {
EventTask(Looper looper) {
@@ -909,13 +999,14 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
private final String mProtocolName;
private final IBinder mIBinder;
private final WaitObj mWaitObj;
- public boolean isWait;
private Params mParams;
private int mSessionState;
private UwbMulticastListUpdateStatus mMulticastListUpdateStatus;
private final int mProfileType;
private AlarmManager.OnAlarmListener mRangingResultErrorStreakTimerListener;
private final String mChipId;
+ private boolean mHasNonPrivilegedFgApp = false;
+ private @FiraParams.RangeDataNtfConfig Integer mOrigRangeDataNtfConfig;
UwbSession(AttributionSource attributionSource, SessionHandle sessionHandle, int sessionId,
String protocolName, Params params, IUwbRangingCallbacks iUwbRangingCallbacks,
@@ -929,7 +1020,6 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
this.mSessionState = UwbUciConstants.UWB_SESSION_STATE_DEINIT;
this.mParams = params;
this.mWaitObj = new WaitObj();
- this.isWait = false;
this.mProfileType = convertProtolNameToProfileType(protocolName);
this.mChipId = chipId;
}
@@ -944,7 +1034,7 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
* @return true if there is some non-system app, false otherwise.
*/
@Nullable
- public AttributionSource hasAnyNonPrivilegedAppInAttributionSource() {
+ public AttributionSource getAnyNonPrivilegedAppInAttributionSource() {
// Iterate attribution source chain to ensure that there is no non-fg 3p app in the
// request.
AttributionSource attributionSource = mAttributionSource;
@@ -1057,6 +1147,14 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
return mWaitObj;
}
+ public boolean hasNonPrivilegedFgApp() {
+ return mHasNonPrivilegedFgApp;
+ }
+
+ public void setHasNonPrivilegedFgApp(boolean hasNonPrivilegedFgApp) {
+ mHasNonPrivilegedFgApp = hasNonPrivilegedFgApp;
+ }
+
/**
* Starts a timer to detect if the error streak is longer than
* {@link #RANGING_RESULT_ERROR_STREAK_TIMER_TIMEOUT_MS}.
@@ -1085,6 +1183,22 @@ public class UwbSessionManager implements INativeUwbManager.SessionNotification
}
}
+ public void reconfigureFiraSessionOnFgStateChange() {
+ if (mOrigRangeDataNtfConfig == null) {
+ mOrigRangeDataNtfConfig = ((FiraOpenSessionParams) mParams).getRangeDataNtfConfig();
+ }
+ // Reconfigure the session to change notification control when the app transitions
+ // from fg to bg and vice versa.
+ FiraRangingReconfigureParams reconfigureParams =
+ new FiraRangingReconfigureParams.Builder()
+ // If app is in fg, use the configured ntf control, else disable.
+ .setRangeDataNtfConfig(mHasNonPrivilegedFgApp
+ // use to retrieve the latest configured ntf control.
+ ? mOrigRangeDataNtfConfig : FiraParams.RANGE_DATA_NTF_CONFIG_DISABLE)
+ .build();
+ reconfigure(mSessionHandle, reconfigureParams);
+ }
+
@Override
public void binderDied() {
Log.i(TAG, "binderDied : getSessionId is getSessionId() " + getSessionId());
diff --git a/service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java b/service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java
index 925f6ac0..e54c52ef 100644
--- a/service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java
+++ b/service/tests/src/com/android/server/uwb/UwbSessionManagerTest.java
@@ -16,6 +16,9 @@
package com.android.server.uwb;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+
import static com.android.server.uwb.UwbSessionManager.SESSION_OPEN_RANGING;
import static com.google.common.truth.Truth.assertThat;
@@ -37,6 +40,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
+import android.app.ActivityManager.OnUidImportanceListener;
import android.app.AlarmManager;
import android.content.AttributionSource;
import android.os.IBinder;
@@ -70,6 +75,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -89,6 +95,8 @@ public class UwbSessionManagerTest {
private static final int MAX_SESSION_NUM = 8;
private static final int UID = 343453;
private static final String PACKAGE_NAME = "com.uwb.test";
+ private static final int UID_2 = 67;
+ private static final String PACKAGE_NAME_2 = "com.android.uwb.2";
private static final AttributionSource ATTRIBUTION_SOURCE =
new AttributionSource.Builder(UID).setPackageName(PACKAGE_NAME).build();
@@ -106,9 +114,13 @@ public class UwbSessionManagerTest {
private ExecutorService mExecutorService;
@Mock
private AlarmManager mAlarmManager;
+ @Mock
+ private ActivityManager mActivityManager;
private TestLooper mTestLooper = new TestLooper();
private UwbSessionManager mUwbSessionManager;
private MockitoSession mMockitoSession;
+ @Captor
+ private ArgumentCaptor<OnUidImportanceListener> mOnUidImportanceListenerArgumentCaptor;
@Before
public void setup() {
@@ -125,8 +137,12 @@ public class UwbSessionManagerTest {
mUwbSessionNotificationManager,
mUwbInjector,
mAlarmManager,
+ mActivityManager,
mTestLooper.getLooper()));
+ verify(mActivityManager).addOnUidImportanceListener(
+ mOnUidImportanceListenerArgumentCaptor.capture(), anyInt());
+
// static mocking for executor service.
mMockitoSession = ExtendedMockito.mockitoSession()
.mockStatic(Executors.class, Mockito.withSettings().lenient())
@@ -554,10 +570,12 @@ public class UwbSessionManagerTest {
mUwbSessionManager.mSessionTable.put(TEST_SESSION_ID, mockUwbSession1);
when(mockUwbSession1.getBinder()).thenReturn(mock(IBinder.class));
when(mockUwbSession1.getSessionId()).thenReturn(TEST_SESSION_ID);
+ when(mockUwbSession1.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
UwbSession mockUwbSession2 = mock(UwbSession.class);
mUwbSessionManager.mSessionTable.put(TEST_SESSION_ID + 100, mockUwbSession2);
when(mockUwbSession2.getBinder()).thenReturn(mock(IBinder.class));
when(mockUwbSession2.getSessionId()).thenReturn(TEST_SESSION_ID + 100);
+ when(mockUwbSession2.getProtocolName()).thenReturn(FiraParams.PROTOCOL_NAME);
mUwbSessionManager.deinitAllSession();
@@ -864,27 +882,29 @@ public class UwbSessionManagerTest {
assertThat(mTestLooper.isIdle()).isFalse();
}
- @Test
- public void testOpenRangingWithNonSystemAppInFgInChain() throws Exception {
- int test_uid_2 = 67;
- String test_package_name_2 = "com.android.uwb.2";
- when(mUwbInjector.isSystemApp(test_uid_2, test_package_name_2)).thenReturn(false);
- when(mUwbInjector.isForegroundAppOrService(test_uid_2, test_package_name_2))
+ private UwbSession initUwbSessionForNonSystemAppInFgInChain() throws Exception {
+ when(mUwbInjector.isSystemApp(UID_2, PACKAGE_NAME_2)).thenReturn(false);
+ when(mUwbInjector.isForegroundAppOrService(UID_2, PACKAGE_NAME_2))
.thenReturn(true);
// simulate system app triggered the request on behalf of a fg app in fg.
AttributionSource attributionSource = new AttributionSource.Builder(UID)
.setPackageName(PACKAGE_NAME)
- .setNext(new AttributionSource.Builder(test_uid_2)
- .setPackageName(test_package_name_2)
+ .setNext(new AttributionSource.Builder(UID_2)
+ .setPackageName(PACKAGE_NAME_2)
.build())
.build();
UwbSession uwbSession = setUpUwbSessionForExecution(attributionSource);
-
mUwbSessionManager.initSession(attributionSource, uwbSession.getSessionHandle(),
TEST_SESSION_ID, FiraParams.PROTOCOL_NAME,
uwbSession.getParams(), uwbSession.getIUwbRangingCallbacks(), TEST_CHIP_ID);
+ return uwbSession;
+ }
+
+ @Test
+ public void testOpenRangingWithNonSystemAppInFgInChain() throws Exception {
+ initUwbSessionForNonSystemAppInFgInChain();
// OPEN_RANGING message scheduled.
assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
@@ -892,18 +912,46 @@ public class UwbSessionManagerTest {
}
@Test
+ public void testOpenRangingWithNonSystemAppInFgInChain_MoveToBgAndFg() throws Exception {
+ UwbSession uwbSession = initUwbSessionForNonSystemAppInFgInChain();
+ // OPEN_RANGING message scheduled.
+ assertThat(mTestLooper.nextMessage().what).isEqualTo(SESSION_OPEN_RANGING);
+ mTestLooper.dispatchAll();
+
+ // Move to background.
+ mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
+ UID_2, IMPORTANCE_BACKGROUND);
+ mTestLooper.dispatchNext();
+ assertThat(mTestLooper.nextMessage().what)
+ .isEqualTo(UwbSessionManager.SESSION_RECONFIG_RANGING);
+ FiraOpenSessionParams firaParams = (FiraOpenSessionParams) uwbSession.getParams();
+ assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
+ FiraParams.RANGE_DATA_NTF_CONFIG_DISABLE);
+ mTestLooper.dispatchAll();
+
+ // Move to foreground.
+ mOnUidImportanceListenerArgumentCaptor.getValue().onUidImportance(
+ UID_2, IMPORTANCE_FOREGROUND);
+ mTestLooper.dispatchNext();
+ assertThat(mTestLooper.nextMessage().what)
+ .isEqualTo(UwbSessionManager.SESSION_RECONFIG_RANGING);
+ firaParams = (FiraOpenSessionParams) uwbSession.getParams();
+ assertThat(firaParams.getRangeDataNtfConfig()).isEqualTo(
+ FiraParams.RANGE_DATA_NTF_CONFIG_ENABLE);
+ mTestLooper.dispatchAll();
+ }
+
+ @Test
public void testOpenRangingWithNonSystemAppNotInFgInChain() throws Exception {
- int test_uid_2 = 67;
- String test_package_name_2 = "com.android.uwb.2";
- when(mUwbInjector.isSystemApp(test_uid_2, test_package_name_2)).thenReturn(false);
- when(mUwbInjector.isForegroundAppOrService(test_uid_2, test_package_name_2))
+ when(mUwbInjector.isSystemApp(UID_2, PACKAGE_NAME_2)).thenReturn(false);
+ when(mUwbInjector.isForegroundAppOrService(UID_2, PACKAGE_NAME_2))
.thenReturn(false);
// simulate system app triggered the request on behalf of a fg app not in fg.
AttributionSource attributionSource = new AttributionSource.Builder(UID)
.setPackageName(PACKAGE_NAME)
- .setNext(new AttributionSource.Builder(test_uid_2)
- .setPackageName(test_package_name_2)
+ .setNext(new AttributionSource.Builder(UID_2)
+ .setPackageName(PACKAGE_NAME_2)
.build())
.build();
UwbSession uwbSession = setUpUwbSessionForExecution(attributionSource);