Loading core/java/android/permission/PermissionUsageHelper.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -105,7 +105,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis private static final long DEFAULT_RUNNING_TIME_MS = 5000L; private static final long DEFAULT_RUNNING_TIME_MS = 5000L; private static final long ADDITIONAL_RUNNING_TIME_LOCATION_ONLY_MS = private static final long ADDITIONAL_RUNNING_TIME_LOCATION_ONLY_MS = 10_000L - DEFAULT_RUNNING_TIME_MS; 10_000L - DEFAULT_RUNNING_TIME_MS; // LINT.ThenChange(/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt) // LINT.ThenChange(/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt, /packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java) private static final long DEFAULT_RECENT_TIME_MS = 15000L; private static final long DEFAULT_RECENT_TIME_MS = 15000L; private static boolean shouldShowIndicators() { private static boolean shouldShowIndicators() { Loading packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +18 −2 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.location.flags.Flags; import android.media.AudioManager; import android.media.AudioManager; import android.media.AudioRecordingConfiguration; import android.media.AudioRecordingConfiguration; import android.os.Handler; import android.os.Handler; Loading Loading @@ -70,10 +71,14 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon AppOpsManager.OnOpNotedInternalListener, IndividualSensorPrivacyController.Callback, AppOpsManager.OnOpNotedInternalListener, IndividualSensorPrivacyController.Callback, Dumpable { Dumpable { // LINT.IfChange // This is the minimum time that we will keep AppOps that are noted on record. If multiple // This is the minimum time that we will keep AppOps that are noted on record. If multiple // occurrences of the same (op, package, uid) happen in a shorter interval, they will not be // occurrences of the same (op, package, uid) happen in a shorter interval, they will not be // notified to listeners. // notified to listeners. private static final long NOTED_OP_TIME_DELAY_MS = 5000; private static final long NOTED_OP_TIME_DELAY_MS = 5000; // This is the minimum time that we will keep AppOps that are noted on record for location only. private static final long NOTED_OP_TIME_LOCATION_ONLY_DELAY_MS = 10_000; // LINT.ThenChange(/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt, /core/java/android/permission/PermissionUsageHelper.java) private static final String TAG = "AppOpsControllerImpl"; private static final String TAG = "AppOpsControllerImpl"; private static final boolean DEBUG = false; private static final boolean DEBUG = false; Loading Loading @@ -255,7 +260,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon } } /** /** * Adds a callback that will get notifified when an AppOp of the type the controller tracks * Adds a callback that will get notified when an AppOp of the type the controller tracks * changes * changes * * * @param callback Callback to report changes * @param callback Callback to report changes Loading Loading @@ -368,7 +373,11 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon } } // We should keep this so we make sure it cannot time out. // We should keep this so we make sure it cannot time out. mBGHandler.removeCallbacksAndMessages(item); mBGHandler.removeCallbacksAndMessages(item); mBGHandler.scheduleRemoval(item, NOTED_OP_TIME_DELAY_MS); final long delay = (Flags.locationIndicatorsEnabled() && isOpLocation(code)) ? NOTED_OP_TIME_LOCATION_ONLY_DELAY_MS : NOTED_OP_TIME_DELAY_MS; mBGHandler.scheduleRemoval(item, delay); return createdNew; return createdNew; } } Loading Loading @@ -626,6 +635,13 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon return false; return false; } } private boolean isOpLocation(int op) { for (int i = 0; i < OPS_LOC.length; i++) { if (op == OPS_LOC[i]) return true; } return false; } protected class H extends Handler { protected class H extends Handler { H(Looper looper) { H(Looper looper) { super(looper); super(looper); Loading packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt +77 −33 Original line number Original line Diff line number Diff line Loading @@ -139,14 +139,15 @@ constructor( logger.logUpdatedItemFromAppOps(code, uid, packageName, active) logger.logUpdatedItemFromAppOps(code, uid, packageName, active) val procInfo = val procInfo = (activityManager.runningAppProcesses (activityManager.runningAppProcesses ?: emptyList()).find { ?: emptyList()).find { it.uid == uid } it.uid == uid } val importance = procInfo?.importance ?: -1 // Use -1 if process not found val importance = procInfo?.importance ?: -1 // Use -1 if process not found logger.logLocationAppOps( logger.logLocationAppOps( uid, uid, packageName, packageName, importance, importance, !isBackgroundApp(uid) !isBackgroundApp(uid), ) ) dispatchOnPrivacyItemsChanged() dispatchOnPrivacyItemsChanged() Loading Loading @@ -290,35 +291,48 @@ constructor( private fun logLocationAccesses() { private fun logLocationAccesses() { // TODO(b/419834493): Add logbuffer logging here for bugreport debugging. // TODO(b/419834493): Add logbuffer logging here for bugreport debugging. synchronized(lock) { synchronized(lock) { if (!lastHighPowerLocationOp && hasHighPowerLocationAccess) { logLocationIndicatorEvent( uiEventLogger.log { lastState = lastHighPowerLocationOp, LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER.id currentState = hasHighPowerLocationAccess, } onEvent = LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER, } offEvent = LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER_OFF, if (!lastLocationIndicator && hasNonSystemForegroundLocationAccess) { ) uiEventLogger.log { LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP.id } logLocationIndicatorEvent( } lastState = lastLocationIndicator, if (!lastLocationIndicatorWithSystem) { currentState = hasNonSystemForegroundLocationAccess, if (hasNonSystemForegroundLocationAccess || hasSystemLocationAccess) { onEvent = LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP, uiEventLogger.log { LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP.id } offEvent = LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP_OFF, } ) } if (!lastLocationIndicatorWithBackround) { // No background access if (hasNonSystemForegroundLocationAccess || hasBackgroundLocationAccess) { val hasSystemAccess = hasNonSystemForegroundLocationAccess || hasSystemLocationAccess uiEventLogger.log { logLocationIndicatorEvent( LocationIndicatorEvent.LOCATION_INDICATOR_BACKGROUND_APP.id lastState = lastLocationIndicatorWithSystem, } currentState = hasSystemAccess, } onEvent = LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP, } offEvent = LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP_OFF, if (!lastLocationIndicatorWithSystemAndBackround) { ) if ( // No system access val hasBackgroundAccess = hasNonSystemForegroundLocationAccess || hasBackgroundLocationAccess logLocationIndicatorEvent( lastState = lastLocationIndicatorWithBackround, currentState = hasBackgroundAccess, onEvent = LocationIndicatorEvent.LOCATION_INDICATOR_BACKGROUND_APP, offEvent = LocationIndicatorEvent.LOCATION_INDICATOR_BACKGROUND_APP_OFF, ) val hasAllAccess = hasNonSystemForegroundLocationAccess || hasNonSystemForegroundLocationAccess || hasSystemLocationAccess || hasSystemLocationAccess || hasBackgroundLocationAccess hasBackgroundLocationAccess ) { logLocationIndicatorEvent( uiEventLogger.log { LocationIndicatorEvent.LOCATION_INDICATOR_ALL_APP.id } lastLocationIndicatorWithSystemAndBackround, } hasAllAccess, } LocationIndicatorEvent.LOCATION_INDICATOR_ALL_APP, LocationIndicatorEvent.LOCATION_INDICATOR_ALL_APP_OFF, ) hasHighPowerLocationAccess = false hasHighPowerLocationAccess = false hasSystemLocationAccess = false hasSystemLocationAccess = false Loading @@ -327,6 +341,17 @@ constructor( } } } } private fun logLocationIndicatorEvent( lastState: Boolean, currentState: Boolean, onEvent: LocationIndicatorEvent, offEvent: LocationIndicatorEvent, ) { if (lastState != currentState) { uiEventLogger.log(if (currentState) onEvent else offEvent) } } @GuardedBy("lock") @GuardedBy("lock") private fun privacyItemForAppOpEnabledLocked(code: Int): Boolean { private fun privacyItemForAppOpEnabledLocked(code: Int): Boolean { if (code in OPS_LOCATION) { if (code in OPS_LOCATION) { Loading Loading @@ -486,24 +511,43 @@ constructor( // Copied from LocationControllerImpl.java // Copied from LocationControllerImpl.java @UiEvent(doc = "Location indicator shown for high power access") @UiEvent(doc = "Location indicator shown for high power access") LOCATION_INDICATOR_MONITOR_HIGH_POWER(935), LOCATION_INDICATOR_MONITOR_HIGH_POWER(935), @UiEvent(doc = "Location indicator hidden for high power access") LOCATION_INDICATOR_MONITOR_HIGH_POWER_OFF(2417), // Copied from LocationControllerImpl.java // Copied from LocationControllerImpl.java @UiEvent( @UiEvent( doc = doc = "Location indicator shown for system, non-system, foreground app access (i.e., excluding background)" "Location indicator shown for system, non-system, foreground app access (i.e., excluding background)" ) ) LOCATION_INDICATOR_SYSTEM_APP(936), LOCATION_INDICATOR_SYSTEM_APP(936), @UiEvent( doc = "Location indicator hidden for system, non-system, foreground app access (i.e., excluding background)" ) LOCATION_INDICATOR_SYSTEM_APP_OFF(2418), // Copied from LocationControllerImpl.java // Copied from LocationControllerImpl.java @UiEvent( @UiEvent( doc = doc = "Location indicator shown for non-system, foreground app access (i.e., excluding system and background)" "Location indicator shown for non-system, foreground app access (i.e., excluding system and background)" ) ) LOCATION_INDICATOR_NON_SYSTEM_APP(937), LOCATION_INDICATOR_NON_SYSTEM_APP(937), @UiEvent( doc = "Location indicator hidden for non-system, foreground app access (i.e., excluding system and background)" ) LOCATION_INDICATOR_NON_SYSTEM_APP_OFF(2419), @UiEvent( @UiEvent( doc = doc = "Location indicator shown for non-system, foreground, background app access (i.e., excluding system)" "Location indicator shown for non-system, foreground, background app access (i.e., excluding system)" ) ) LOCATION_INDICATOR_BACKGROUND_APP(2325), LOCATION_INDICATOR_BACKGROUND_APP(2325), @UiEvent(doc = "Location indicator shown for all access") LOCATION_INDICATOR_ALL_APP(2354); @UiEvent( doc = "Location indicator hidden for non-system, foreground, background app access (i.e., excluding system)" ) LOCATION_INDICATOR_BACKGROUND_APP_OFF(2420), @UiEvent(doc = "Location indicator shown for all access") LOCATION_INDICATOR_ALL_APP(2354), @UiEvent(doc = "Location indicator hidden for all access") LOCATION_INDICATOR_ALL_APP_OFF(2421); override fun getId(): Int { override fun getId(): Int { return id return id Loading packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +1 −1 Original line number Original line Diff line number Diff line Loading @@ -51,7 +51,7 @@ class PrivacyItemController @Inject constructor( // LINT.IfChange // LINT.IfChange @VisibleForTesting const val TIME_TO_HOLD_INDICATORS = 5_000L @VisibleForTesting const val TIME_TO_HOLD_INDICATORS = 5_000L @VisibleForTesting const val TIME_TO_HOLD_INDICATORS_FOR_LOCATION = 10_000L @VisibleForTesting const val TIME_TO_HOLD_INDICATORS_FOR_LOCATION = 10_000L // LINT.ThenChange(/core/java/android/permission/PermissionUsageHelper.java) // LINT.ThenChange(/core/java/android/permission/PermissionUsageHelper.java, /packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java) } } @VisibleForTesting @VisibleForTesting Loading packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java +32 −0 Original line number Original line Diff line number Diff line Loading @@ -46,10 +46,12 @@ import static org.mockito.Mockito.when; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.content.Context; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.location.flags.Flags; import android.media.AudioManager; import android.media.AudioManager; import android.media.AudioRecordingConfiguration; import android.media.AudioRecordingConfiguration; import android.os.Looper; import android.os.Looper; import android.os.UserHandle; import android.os.UserHandle; import android.platform.test.annotations.EnableFlags; import android.testing.TestableLooper; import android.testing.TestableLooper; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4; Loading @@ -66,6 +68,7 @@ import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Before; import org.junit.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; Loading Loading @@ -539,6 +542,35 @@ public class AppOpsControllerTest extends SysuiTestCase { verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong()); verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong()); } } @Test @EnableFlags(Flags.FLAG_LOCATION_INDICATORS_ENABLED) public void opNotedScheduledForRemoval_delayIsCorrect() { mController.setBGHandler(mMockHandler); ArgumentCaptor<AppOpItem> itemCaptor = ArgumentCaptor.forClass(AppOpItem.class); ArgumentCaptor<Long> delayCaptor = ArgumentCaptor.forClass(Long.class); // Location op is noted mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); // Non-location op is noted mController.onOpNoted(AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); // Check they are both scheduled for removal with the correct delays verify(mMockHandler, times(2)).scheduleRemoval(itemCaptor.capture(), delayCaptor.capture()); List<AppOpItem> items = itemCaptor.getAllValues(); List<Long> delays = delayCaptor.getAllValues(); assertEquals(AppOpsManager.OP_FINE_LOCATION, items.get(0).getCode()); assertEquals(10000L, delays.get(0).longValue()); assertEquals(AppOpsManager.OP_RECORD_AUDIO, items.get(1).getCode()); assertEquals(5000L, delays.get(1).longValue()); } @Test @Test public void noItemsAfterStopListening() { public void noItemsAfterStopListening() { mController.setBGHandler(mMockHandler); mController.setBGHandler(mMockHandler); Loading Loading
core/java/android/permission/PermissionUsageHelper.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -105,7 +105,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis private static final long DEFAULT_RUNNING_TIME_MS = 5000L; private static final long DEFAULT_RUNNING_TIME_MS = 5000L; private static final long ADDITIONAL_RUNNING_TIME_LOCATION_ONLY_MS = private static final long ADDITIONAL_RUNNING_TIME_LOCATION_ONLY_MS = 10_000L - DEFAULT_RUNNING_TIME_MS; 10_000L - DEFAULT_RUNNING_TIME_MS; // LINT.ThenChange(/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt) // LINT.ThenChange(/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt, /packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java) private static final long DEFAULT_RECENT_TIME_MS = 15000L; private static final long DEFAULT_RECENT_TIME_MS = 15000L; private static boolean shouldShowIndicators() { private static boolean shouldShowIndicators() { Loading
packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +18 −2 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.location.flags.Flags; import android.media.AudioManager; import android.media.AudioManager; import android.media.AudioRecordingConfiguration; import android.media.AudioRecordingConfiguration; import android.os.Handler; import android.os.Handler; Loading Loading @@ -70,10 +71,14 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon AppOpsManager.OnOpNotedInternalListener, IndividualSensorPrivacyController.Callback, AppOpsManager.OnOpNotedInternalListener, IndividualSensorPrivacyController.Callback, Dumpable { Dumpable { // LINT.IfChange // This is the minimum time that we will keep AppOps that are noted on record. If multiple // This is the minimum time that we will keep AppOps that are noted on record. If multiple // occurrences of the same (op, package, uid) happen in a shorter interval, they will not be // occurrences of the same (op, package, uid) happen in a shorter interval, they will not be // notified to listeners. // notified to listeners. private static final long NOTED_OP_TIME_DELAY_MS = 5000; private static final long NOTED_OP_TIME_DELAY_MS = 5000; // This is the minimum time that we will keep AppOps that are noted on record for location only. private static final long NOTED_OP_TIME_LOCATION_ONLY_DELAY_MS = 10_000; // LINT.ThenChange(/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt, /core/java/android/permission/PermissionUsageHelper.java) private static final String TAG = "AppOpsControllerImpl"; private static final String TAG = "AppOpsControllerImpl"; private static final boolean DEBUG = false; private static final boolean DEBUG = false; Loading Loading @@ -255,7 +260,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon } } /** /** * Adds a callback that will get notifified when an AppOp of the type the controller tracks * Adds a callback that will get notified when an AppOp of the type the controller tracks * changes * changes * * * @param callback Callback to report changes * @param callback Callback to report changes Loading Loading @@ -368,7 +373,11 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon } } // We should keep this so we make sure it cannot time out. // We should keep this so we make sure it cannot time out. mBGHandler.removeCallbacksAndMessages(item); mBGHandler.removeCallbacksAndMessages(item); mBGHandler.scheduleRemoval(item, NOTED_OP_TIME_DELAY_MS); final long delay = (Flags.locationIndicatorsEnabled() && isOpLocation(code)) ? NOTED_OP_TIME_LOCATION_ONLY_DELAY_MS : NOTED_OP_TIME_DELAY_MS; mBGHandler.scheduleRemoval(item, delay); return createdNew; return createdNew; } } Loading Loading @@ -626,6 +635,13 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon return false; return false; } } private boolean isOpLocation(int op) { for (int i = 0; i < OPS_LOC.length; i++) { if (op == OPS_LOC[i]) return true; } return false; } protected class H extends Handler { protected class H extends Handler { H(Looper looper) { H(Looper looper) { super(looper); super(looper); Loading
packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt +77 −33 Original line number Original line Diff line number Diff line Loading @@ -139,14 +139,15 @@ constructor( logger.logUpdatedItemFromAppOps(code, uid, packageName, active) logger.logUpdatedItemFromAppOps(code, uid, packageName, active) val procInfo = val procInfo = (activityManager.runningAppProcesses (activityManager.runningAppProcesses ?: emptyList()).find { ?: emptyList()).find { it.uid == uid } it.uid == uid } val importance = procInfo?.importance ?: -1 // Use -1 if process not found val importance = procInfo?.importance ?: -1 // Use -1 if process not found logger.logLocationAppOps( logger.logLocationAppOps( uid, uid, packageName, packageName, importance, importance, !isBackgroundApp(uid) !isBackgroundApp(uid), ) ) dispatchOnPrivacyItemsChanged() dispatchOnPrivacyItemsChanged() Loading Loading @@ -290,35 +291,48 @@ constructor( private fun logLocationAccesses() { private fun logLocationAccesses() { // TODO(b/419834493): Add logbuffer logging here for bugreport debugging. // TODO(b/419834493): Add logbuffer logging here for bugreport debugging. synchronized(lock) { synchronized(lock) { if (!lastHighPowerLocationOp && hasHighPowerLocationAccess) { logLocationIndicatorEvent( uiEventLogger.log { lastState = lastHighPowerLocationOp, LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER.id currentState = hasHighPowerLocationAccess, } onEvent = LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER, } offEvent = LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER_OFF, if (!lastLocationIndicator && hasNonSystemForegroundLocationAccess) { ) uiEventLogger.log { LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP.id } logLocationIndicatorEvent( } lastState = lastLocationIndicator, if (!lastLocationIndicatorWithSystem) { currentState = hasNonSystemForegroundLocationAccess, if (hasNonSystemForegroundLocationAccess || hasSystemLocationAccess) { onEvent = LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP, uiEventLogger.log { LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP.id } offEvent = LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP_OFF, } ) } if (!lastLocationIndicatorWithBackround) { // No background access if (hasNonSystemForegroundLocationAccess || hasBackgroundLocationAccess) { val hasSystemAccess = hasNonSystemForegroundLocationAccess || hasSystemLocationAccess uiEventLogger.log { logLocationIndicatorEvent( LocationIndicatorEvent.LOCATION_INDICATOR_BACKGROUND_APP.id lastState = lastLocationIndicatorWithSystem, } currentState = hasSystemAccess, } onEvent = LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP, } offEvent = LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP_OFF, if (!lastLocationIndicatorWithSystemAndBackround) { ) if ( // No system access val hasBackgroundAccess = hasNonSystemForegroundLocationAccess || hasBackgroundLocationAccess logLocationIndicatorEvent( lastState = lastLocationIndicatorWithBackround, currentState = hasBackgroundAccess, onEvent = LocationIndicatorEvent.LOCATION_INDICATOR_BACKGROUND_APP, offEvent = LocationIndicatorEvent.LOCATION_INDICATOR_BACKGROUND_APP_OFF, ) val hasAllAccess = hasNonSystemForegroundLocationAccess || hasNonSystemForegroundLocationAccess || hasSystemLocationAccess || hasSystemLocationAccess || hasBackgroundLocationAccess hasBackgroundLocationAccess ) { logLocationIndicatorEvent( uiEventLogger.log { LocationIndicatorEvent.LOCATION_INDICATOR_ALL_APP.id } lastLocationIndicatorWithSystemAndBackround, } hasAllAccess, } LocationIndicatorEvent.LOCATION_INDICATOR_ALL_APP, LocationIndicatorEvent.LOCATION_INDICATOR_ALL_APP_OFF, ) hasHighPowerLocationAccess = false hasHighPowerLocationAccess = false hasSystemLocationAccess = false hasSystemLocationAccess = false Loading @@ -327,6 +341,17 @@ constructor( } } } } private fun logLocationIndicatorEvent( lastState: Boolean, currentState: Boolean, onEvent: LocationIndicatorEvent, offEvent: LocationIndicatorEvent, ) { if (lastState != currentState) { uiEventLogger.log(if (currentState) onEvent else offEvent) } } @GuardedBy("lock") @GuardedBy("lock") private fun privacyItemForAppOpEnabledLocked(code: Int): Boolean { private fun privacyItemForAppOpEnabledLocked(code: Int): Boolean { if (code in OPS_LOCATION) { if (code in OPS_LOCATION) { Loading Loading @@ -486,24 +511,43 @@ constructor( // Copied from LocationControllerImpl.java // Copied from LocationControllerImpl.java @UiEvent(doc = "Location indicator shown for high power access") @UiEvent(doc = "Location indicator shown for high power access") LOCATION_INDICATOR_MONITOR_HIGH_POWER(935), LOCATION_INDICATOR_MONITOR_HIGH_POWER(935), @UiEvent(doc = "Location indicator hidden for high power access") LOCATION_INDICATOR_MONITOR_HIGH_POWER_OFF(2417), // Copied from LocationControllerImpl.java // Copied from LocationControllerImpl.java @UiEvent( @UiEvent( doc = doc = "Location indicator shown for system, non-system, foreground app access (i.e., excluding background)" "Location indicator shown for system, non-system, foreground app access (i.e., excluding background)" ) ) LOCATION_INDICATOR_SYSTEM_APP(936), LOCATION_INDICATOR_SYSTEM_APP(936), @UiEvent( doc = "Location indicator hidden for system, non-system, foreground app access (i.e., excluding background)" ) LOCATION_INDICATOR_SYSTEM_APP_OFF(2418), // Copied from LocationControllerImpl.java // Copied from LocationControllerImpl.java @UiEvent( @UiEvent( doc = doc = "Location indicator shown for non-system, foreground app access (i.e., excluding system and background)" "Location indicator shown for non-system, foreground app access (i.e., excluding system and background)" ) ) LOCATION_INDICATOR_NON_SYSTEM_APP(937), LOCATION_INDICATOR_NON_SYSTEM_APP(937), @UiEvent( doc = "Location indicator hidden for non-system, foreground app access (i.e., excluding system and background)" ) LOCATION_INDICATOR_NON_SYSTEM_APP_OFF(2419), @UiEvent( @UiEvent( doc = doc = "Location indicator shown for non-system, foreground, background app access (i.e., excluding system)" "Location indicator shown for non-system, foreground, background app access (i.e., excluding system)" ) ) LOCATION_INDICATOR_BACKGROUND_APP(2325), LOCATION_INDICATOR_BACKGROUND_APP(2325), @UiEvent(doc = "Location indicator shown for all access") LOCATION_INDICATOR_ALL_APP(2354); @UiEvent( doc = "Location indicator hidden for non-system, foreground, background app access (i.e., excluding system)" ) LOCATION_INDICATOR_BACKGROUND_APP_OFF(2420), @UiEvent(doc = "Location indicator shown for all access") LOCATION_INDICATOR_ALL_APP(2354), @UiEvent(doc = "Location indicator hidden for all access") LOCATION_INDICATOR_ALL_APP_OFF(2421); override fun getId(): Int { override fun getId(): Int { return id return id Loading
packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +1 −1 Original line number Original line Diff line number Diff line Loading @@ -51,7 +51,7 @@ class PrivacyItemController @Inject constructor( // LINT.IfChange // LINT.IfChange @VisibleForTesting const val TIME_TO_HOLD_INDICATORS = 5_000L @VisibleForTesting const val TIME_TO_HOLD_INDICATORS = 5_000L @VisibleForTesting const val TIME_TO_HOLD_INDICATORS_FOR_LOCATION = 10_000L @VisibleForTesting const val TIME_TO_HOLD_INDICATORS_FOR_LOCATION = 10_000L // LINT.ThenChange(/core/java/android/permission/PermissionUsageHelper.java) // LINT.ThenChange(/core/java/android/permission/PermissionUsageHelper.java, /packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java) } } @VisibleForTesting @VisibleForTesting Loading
packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java +32 −0 Original line number Original line Diff line number Diff line Loading @@ -46,10 +46,12 @@ import static org.mockito.Mockito.when; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.content.Context; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.location.flags.Flags; import android.media.AudioManager; import android.media.AudioManager; import android.media.AudioRecordingConfiguration; import android.media.AudioRecordingConfiguration; import android.os.Looper; import android.os.Looper; import android.os.UserHandle; import android.os.UserHandle; import android.platform.test.annotations.EnableFlags; import android.testing.TestableLooper; import android.testing.TestableLooper; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4; Loading @@ -66,6 +68,7 @@ import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Before; import org.junit.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; Loading Loading @@ -539,6 +542,35 @@ public class AppOpsControllerTest extends SysuiTestCase { verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong()); verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong()); } } @Test @EnableFlags(Flags.FLAG_LOCATION_INDICATORS_ENABLED) public void opNotedScheduledForRemoval_delayIsCorrect() { mController.setBGHandler(mMockHandler); ArgumentCaptor<AppOpItem> itemCaptor = ArgumentCaptor.forClass(AppOpItem.class); ArgumentCaptor<Long> delayCaptor = ArgumentCaptor.forClass(Long.class); // Location op is noted mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); // Non-location op is noted mController.onOpNoted(AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); // Check they are both scheduled for removal with the correct delays verify(mMockHandler, times(2)).scheduleRemoval(itemCaptor.capture(), delayCaptor.capture()); List<AppOpItem> items = itemCaptor.getAllValues(); List<Long> delays = delayCaptor.getAllValues(); assertEquals(AppOpsManager.OP_FINE_LOCATION, items.get(0).getCode()); assertEquals(10000L, delays.get(0).longValue()); assertEquals(AppOpsManager.OP_RECORD_AUDIO, items.get(1).getCode()); assertEquals(5000L, delays.get(1).longValue()); } @Test @Test public void noItemsAfterStopListening() { public void noItemsAfterStopListening() { mController.setBGHandler(mMockHandler); mController.setBGHandler(mMockHandler); Loading