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

Commit 05ee8965 authored by Atneya Nair's avatar Atneya Nair Committed by Android (Google) Code Review
Browse files

Revert^2 "Migrate audio permission provider prop listener"

This reverts commit 236f2a16.

Reason for revert: Reapply

Change-Id: Ia3cec6493e1d0d54b44175bf8f183c4c937b6449
parent 236f2a16
Loading
Loading
Loading
Loading
+71 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <android_media_audiopolicy.h>
#include <android_os_Parcel.h>
#include <audiomanager/AudioManager.h>
#include <android-base/properties.h>
#include <binder/IBinder.h>
#include <jni.h>
#include <media/AidlConversion.h>
@@ -41,8 +42,10 @@
#include <system/audio_policy.h>
#include <utils/Log.h>

#include <thread>
#include <optional>
#include <sstream>
#include <memory>
#include <vector>

#include "android_media_AudioAttributes.h"
@@ -261,6 +264,13 @@ static struct {
    jfieldID mMixerBehavior;
} gAudioMixerAttributesField;

static struct {
    jclass clazz;
    jmethodID run;
} gRunnableClassInfo;

static JavaVM* gVm;

static Mutex gLock;

enum AudioError {
@@ -3363,6 +3373,55 @@ static jboolean android_media_AudioSystem_isBluetoothVariableLatencyEnabled(JNIE
    return enabled;
}

class JavaSystemPropertyListener {
  public:
    JavaSystemPropertyListener(JNIEnv* env, jobject javaCallback, std::string sysPropName) :
            mCallback(env->NewGlobalRef(javaCallback)),
            mCachedProperty(android::base::CachedProperty{std::move(sysPropName)}) {
        mListenerThread = std::thread([this]() mutable {
            JNIEnv* threadEnv = GetOrAttachJNIEnvironment(gVm);
            while (!mCleanupSignal.load()) {
                using namespace std::chrono_literals;
                // 1s timeout so this thread can read the cleanup signal to (slowly) be able to
                // be destroyed.
                std::string newVal = mCachedProperty.WaitForChange(1000ms) ?: "";
                if (newVal != "" && mLastVal != newVal) {
                    threadEnv->CallVoidMethod(mCallback, gRunnableClassInfo.run);
                    mLastVal = std::move(newVal);
                }
            }
            });
    }

    ~JavaSystemPropertyListener() {
        mCleanupSignal.store(true);
        mListenerThread.join();
        JNIEnv* env = GetOrAttachJNIEnvironment(gVm);
        env->DeleteGlobalRef(mCallback);
    }

  private:
    jobject mCallback;
    android::base::CachedProperty mCachedProperty;
    std::thread mListenerThread;
    std::atomic<bool> mCleanupSignal{false};
    std::string mLastVal = "";
};

std::vector<std::unique_ptr<JavaSystemPropertyListener>> gSystemPropertyListeners;
std::mutex gSysPropLock{};

static void android_media_AudioSystem_listenForSystemPropertyChange(JNIEnv *env,  jobject thiz,
        jstring sysProp,
        jobject javaCallback) {
    ScopedUtfChars sysPropChars{env, sysProp};
    auto listener = std::make_unique<JavaSystemPropertyListener>(env, javaCallback,
            std::string{sysPropChars.c_str()});
    std::unique_lock _l{gSysPropLock};
    gSystemPropertyListeners.push_back(std::move(listener));
}


// ----------------------------------------------------------------------------

#define MAKE_AUDIO_SYSTEM_METHOD(x) \
@@ -3535,7 +3594,12 @@ static const JNINativeMethod gMethods[] =
                                android_media_AudioSystem_clearPreferredMixerAttributes),
         MAKE_AUDIO_SYSTEM_METHOD(supportsBluetoothVariableLatency),
         MAKE_AUDIO_SYSTEM_METHOD(setBluetoothVariableLatencyEnabled),
         MAKE_AUDIO_SYSTEM_METHOD(isBluetoothVariableLatencyEnabled)};
         MAKE_AUDIO_SYSTEM_METHOD(isBluetoothVariableLatencyEnabled),
         MAKE_JNI_NATIVE_METHOD("listenForSystemPropertyChange",
                                "(Ljava/lang/String;Ljava/lang/Runnable;)V",
                                android_media_AudioSystem_listenForSystemPropertyChange),

        };

static const JNINativeMethod gEventHandlerMethods[] =
        {MAKE_JNI_NATIVE_METHOD("native_setup", "(Ljava/lang/Object;)V",
@@ -3817,6 +3881,12 @@ int register_android_media_AudioSystem(JNIEnv *env)
    gAudioMixerAttributesField.mMixerBehavior =
            GetFieldIDOrDie(env, audioMixerAttributesClass, "mMixerBehavior", "I");

    jclass runnableClazz = FindClassOrDie(env, "java/lang/Runnable");
    gRunnableClassInfo.clazz = MakeGlobalRefOrDie(env, runnableClazz);
    gRunnableClassInfo.run = GetMethodIDOrDie(env, runnableClazz, "run", "()V");

    LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&gVm) != 0);

    AudioSystem::addErrorCallback(android_media_AudioSystem_error_callback);

    RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
+7 −0
Original line number Diff line number Diff line
@@ -2649,4 +2649,11 @@ public class AudioSystem
     * @hide
     */
    public static native boolean isBluetoothVariableLatencyEnabled();

    /**
     * Register a native listener for system property sysprop
     * @param callback the listener which fires when the property changes
     * @hide
     */
    public static native void listenForSystemPropertyChange(String sysprop, Runnable callback);
}
+37 −25
Original line number Diff line number Diff line
@@ -734,6 +734,8 @@ public class AudioService extends IAudioService.Stub
    // Broadcast receiver for device connections intent broadcasts
    private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
    private final Executor mAudioServerLifecycleExecutor;
    private IMediaProjectionManager mProjectionService; // to validate projection token
    /** Interface for UserManagerService. */
@@ -1052,7 +1054,8 @@ public class AudioService extends IAudioService.Stub
                              audioserverPermissions() ?
                                initializeAudioServerPermissionProvider(
                                    context, audioPolicyFacade, audioserverLifecycleExecutor) :
                                    null
                                    null,
                              audioserverLifecycleExecutor
                              );
        }
@@ -1138,13 +1141,16 @@ public class AudioService extends IAudioService.Stub
     *               {@link AudioSystemThread} is created as the messaging thread instead.
     * @param appOps {@link AppOpsManager} system service
     * @param enforcer Used for permission enforcing
     * @param permissionProvider Used to push permissions to audioserver
     * @param audioserverLifecycleExecutor Used for tasks managing audioserver lifecycle
     */
    @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
    public AudioService(Context context, AudioSystemAdapter audioSystem,
            SystemServerAdapter systemServer, SettingsAdapter settings,
            AudioVolumeGroupHelperBase audioVolumeGroupHelper, AudioPolicyFacade audioPolicy,
            @Nullable Looper looper, AppOpsManager appOps, @NonNull PermissionEnforcer enforcer,
            /* @NonNull */ AudioServerPermissionProvider permissionProvider) {
            /* @NonNull */ AudioServerPermissionProvider permissionProvider,
            Executor audioserverLifecycleExecutor) {
        super(enforcer);
        sLifecycleLogger.enqueue(new EventLogger.StringEvent("AudioService()"));
        mContext = context;
@@ -1152,6 +1158,7 @@ public class AudioService extends IAudioService.Stub
        mAppOps = appOps;
        mPermissionProvider = permissionProvider;
        mAudioServerLifecycleExecutor = audioserverLifecycleExecutor;
        mAudioSystem = audioSystem;
        mSystemServer = systemServer;
@@ -1163,6 +1170,34 @@ public class AudioService extends IAudioService.Stub
        mBroadcastHandlerThread = new HandlerThread("AudioService Broadcast");
        mBroadcastHandlerThread.start();
        // Listen to permission invalidations for the PermissionProvider
        if (audioserverPermissions()) {
            final Handler broadcastHandler = mBroadcastHandlerThread.getThreadHandler();
            mAudioSystem.listenForSystemPropertyChange(PermissionManager.CACHE_KEY_PACKAGE_INFO,
                    new Runnable() {
                        // Roughly chosen to be long enough to suppress the autocork behavior
                        // of the permission cache (50ms), and longer than the task could reasonably
                        // take, even with many packages and users, while not introducing visible
                        // permission leaks - since the app needs to restart, and trigger an action
                        // which requires permissions from audioserver before this delay.
                        // For RECORD_AUDIO, we are additionally protected by appops.
                        final long UPDATE_DELAY_MS = 110;
                        final AtomicLong scheduledUpdateTimestamp = new AtomicLong(0);
                        @Override
                        public void run() {
                            var currentTime = SystemClock.uptimeMillis();
                            if (currentTime > scheduledUpdateTimestamp.get()) {
                                scheduledUpdateTimestamp.set(currentTime + UPDATE_DELAY_MS);
                                broadcastHandler.postAtTime( () ->
                                        mAudioServerLifecycleExecutor.execute(mPermissionProvider
                                            ::onPermissionStateChanged),
                                        currentTime + UPDATE_DELAY_MS
                                    );
                            }
                        }
            });
        }
        mDeviceBroker = new AudioDeviceBroker(mContext, this, mAudioSystem);
        mIsSingleVolume = AudioSystem.isSingleVolume(context);
@@ -11972,29 +12007,6 @@ public class AudioService extends IAudioService.Stub
            provider.onServiceStart(audioPolicy.getPermissionController());
        });
        // Set up event listeners
        // Must be kept in sync with PermissionManager
        Runnable cacheSysPropHandler = new Runnable() {
            private AtomicReference<SystemProperties.Handle> mHandle = new AtomicReference();
            private AtomicLong mNonce = new AtomicLong();
            @Override
            public void run() {
                if (mHandle.get() == null) {
                    // Cache the handle
                    mHandle.compareAndSet(null, SystemProperties.find(
                            PermissionManager.CACHE_KEY_PACKAGE_INFO));
                }
                long nonce;
                SystemProperties.Handle ref;
                if ((ref = mHandle.get()) != null && (nonce = ref.getLong(0)) != 0 &&
                        mNonce.getAndSet(nonce) != nonce) {
                    audioserverExecutor.execute(() -> provider.onPermissionStateChanged());
                }
            }
        };
        SystemProperties.addChangeCallback(cacheSysPropHandler);
        IntentFilter packageUpdateFilter = new IntentFilter();
        packageUpdateFilter.addAction(ACTION_PACKAGE_ADDED);
        packageUpdateFilter.addAction(ACTION_PACKAGE_REMOVED);
+4 −0
Original line number Diff line number Diff line
@@ -748,6 +748,10 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback,
        return AudioSystem.setMasterMute(mute);
    }

    public void listenForSystemPropertyChange(String systemPropertyName, Runnable callback) {
        AudioSystem.listenForSystemPropertyChange(systemPropertyName, callback);
    }

    /**
     * Part of AudioService dump
     * @param pw
+1 −1
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ public class AbsoluteVolumeBehaviorTest {
        mAudioService = new AudioService(mContext, mSpyAudioSystem, mSystemServer,
                mSettingsAdapter, mAudioVolumeGroupHelper, mMockAudioPolicy,
                mTestLooper.getLooper(), mock(AppOpsManager.class), mock(PermissionEnforcer.class),
                mock(AudioServerPermissionProvider.class)) {
                mock(AudioServerPermissionProvider.class), r -> r.run()) {
            @Override
            public int getDeviceForStream(int stream) {
                return AudioSystem.DEVICE_OUT_SPEAKER;
Loading