Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60864b94 authored by Fabian Kozynski's avatar Fabian Kozynski
Browse files

Do not hold indicators for apps that become paused

If an app op becomes "paused" (microphone muted or disabled by toggle),
remove the indicator immediately as opposed to holding for 5s.

Also, pass the value that we are using for mic muted to
PermissionManager, so they are in sync.

Test: atest SystemUITests
Test: manual
Fixes: 184891081
Change-Id: I4d46fc6e1cefa45c0d718cc01f40c8f060dafee7
parent 0190323c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2009,6 +2009,7 @@ package android.permission {

  public final class PermissionManager {
    method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData();
    method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(boolean);
    method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource);
  }

+18 −0
Original line number Diff line number Diff line
@@ -885,6 +885,24 @@ public final class PermissionManager {
        return mUsageHelper.getOpUsageData(new AudioManager().isMicrophoneMute());
    }

    /**
     * @param micMuted whether to consider the microphone muted when retrieving audio ops
     * @return A list of permission groups currently or recently used by all apps by all users in
     * the current profile group.
     *
     * @hide
     */
    @TestApi
    @NonNull
    @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS)
    public List<PermGroupUsage> getIndicatorAppOpUsageData(boolean micMuted) {
        // Lazily initialize the usage helper
        if (mUsageHelper == null) {
            mUsageHelper = new PermissionUsageHelper(mContext);
        }
        return mUsageHelper.getOpUsageData(micMuted);
    }

    /**
     * Determine if a package should be shown in indicators. Only a select few roles, and the
     * system app itself, are hidden. These values are updated at most every 15 seconds.
+16 −2
Original line number Diff line number Diff line
@@ -60,17 +60,31 @@ public interface AppOpsController {
    /**
     * Returns a copy of the list containing all the active AppOps that the controller tracks.
     *
     * @return List of active AppOps information
     * @return List of active AppOps information, without paused elements.
     */
    List<AppOpItem> getActiveAppOps();

    /**
     * Returns a copy of the list containing all the active AppOps that the controller tracks.
     *
     * @param showPaused {@code true} to also obtain paused items. {@code false} otherwise.
     * @return List of active AppOps information
     */
    List<AppOpItem> getActiveAppOps(boolean showPaused);

    /**
     * Returns a copy of the list containing all the active AppOps that the controller tracks, for
     * a given user id.
     *
     * @param userId User id to track
     * @param showPaused {@code true} to also obtain paused items. {@code false} otherwise.
     *
     * @return List of active AppOps information for that user id
     */
    List<AppOpItem> getActiveAppOpsForUser(int userId);
    List<AppOpItem> getActiveAppOpsForUser(int userId, boolean showPaused);

    /**
     * @return whether this controller is considering the microphone as muted.
     */
    boolean isMicMuted();
}
+27 −8
Original line number Diff line number Diff line
@@ -241,9 +241,9 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
            AppOpItem item = getAppOpItemLocked(mActiveItems, code, uid, packageName);
            if (item == null && active) {
                item = new AppOpItem(code, uid, packageName, mClock.elapsedRealtime());
                if (code == AppOpsManager.OP_RECORD_AUDIO) {
                if (isOpMicrophone(code)) {
                    item.setDisabled(isAnyRecordingPausedLocked(uid));
                } else if (code == AppOpsManager.OP_CAMERA) {
                } else if (isOpCamera(code)) {
                    item.setDisabled(mCameraDisabled);
                }
                mActiveItems.add(item);
@@ -298,6 +298,11 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
        return PermissionManager.shouldShowPackageForIndicatorCached(mContext, packageName);
    }

    @WorkerThread
    public List<AppOpItem> getActiveAppOps() {
        return getActiveAppOps(false);
    }

    /**
     * Returns a copy of the list containing all the active AppOps that the controller tracks.
     *
@@ -306,8 +311,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
     * @return List of active AppOps information
     */
    @WorkerThread
    public List<AppOpItem> getActiveAppOps() {
        return getActiveAppOpsForUser(UserHandle.USER_ALL);
    public List<AppOpItem> getActiveAppOps(boolean showPaused) {
        return getActiveAppOpsForUser(UserHandle.USER_ALL, showPaused);
    }

    /**
@@ -321,7 +326,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
     * @return List of active AppOps information for that user id
     */
    @WorkerThread
    public List<AppOpItem> getActiveAppOpsForUser(int userId) {
    public List<AppOpItem> getActiveAppOpsForUser(int userId, boolean showPaused) {
        Assert.isNotMainThread();
        List<AppOpItem> list = new ArrayList<>();
        synchronized (mActiveItems) {
@@ -330,7 +335,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
                AppOpItem item = mActiveItems.get(i);
                if ((userId == UserHandle.USER_ALL
                        || UserHandle.getUserId(item.getUid()) == userId)
                        && isUserVisible(item.getPackageName()) && !item.isDisabled()) {
                        && isUserVisible(item.getPackageName())
                        && (showPaused || !item.isDisabled())) {
                    list.add(item);
                }
            }
@@ -441,9 +447,9 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
                AppOpItem item = mActiveItems.get(i);

                boolean paused = false;
                if (item.getCode() == AppOpsManager.OP_RECORD_AUDIO) {
                if (isOpMicrophone(item.getCode())) {
                    paused = isAnyRecordingPausedLocked(item.getUid());
                } else if (item.getCode() == AppOpsManager.OP_CAMERA) {
                } else if (isOpCamera(item.getCode())) {
                    paused = mCameraDisabled;
                }

@@ -502,6 +508,19 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
        });
    }

    @Override
    public boolean isMicMuted() {
        return mMicMuted;
    }

    private boolean isOpCamera(int op) {
        return op == AppOpsManager.OP_CAMERA || op == AppOpsManager.OP_PHONE_CALL_CAMERA;
    }

    private boolean isOpMicrophone(int op) {
        return op == AppOpsManager.OP_RECORD_AUDIO || op == AppOpsManager.OP_PHONE_CALL_MICROPHONE;
    }

    protected class H extends Handler {
        H(Looper looper) {
            super(looper);
+9 −4
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.util.Log
import androidx.annotation.MainThread
import androidx.annotation.VisibleForTesting
import androidx.annotation.WorkerThread
import com.android.systemui.appops.AppOpsController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -48,7 +49,6 @@ private val defaultDialogProvider = object : PrivacyDialogController.DialogProvi
        return PrivacyDialog(context, list, starter)
    }
}

/**
 * Controller for [PrivacyDialog].
 *
@@ -66,6 +66,7 @@ class PrivacyDialogController(
    private val uiExecutor: Executor,
    private val privacyLogger: PrivacyLogger,
    private val keyguardStateController: KeyguardStateController,
    private val appOpsController: AppOpsController,
    @VisibleForTesting private val dialogProvider: DialogProvider
) {

@@ -79,7 +80,8 @@ class PrivacyDialogController(
        @Background backgroundExecutor: Executor,
        @Main uiExecutor: Executor,
        privacyLogger: PrivacyLogger,
        keyguardStateController: KeyguardStateController
        keyguardStateController: KeyguardStateController,
        appOpsController: AppOpsController
    ) : this(
            permissionManager,
            packageManager,
@@ -90,6 +92,7 @@ class PrivacyDialogController(
            uiExecutor,
            privacyLogger,
            keyguardStateController,
            appOpsController,
            defaultDialogProvider
    )

@@ -127,7 +130,9 @@ class PrivacyDialogController(
    }

    @WorkerThread
    private fun permGroupUsage(): List<PermGroupUsage> = permissionManager.indicatorAppOpUsageData
    private fun permGroupUsage(): List<PermGroupUsage> {
        return permissionManager.getIndicatorAppOpUsageData(appOpsController.isMicMuted)
    }

    /**
     * Show the [PrivacyDialog]
Loading