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

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

Merge "[audio] AudioService IPC invalidation listener changes" into main

parents c5d886b6 7274c3a4
Loading
Loading
Loading
Loading
+28 −76
Original line number Original line Diff line number Diff line
@@ -837,6 +837,7 @@ public class AudioService extends IAudioService.Stub
    private final Executor mAudioServerLifecycleExecutor;
    private final Executor mAudioServerLifecycleExecutor;
    private long mSysPropListenerNativeHandle;
    private long mSysPropListenerNativeHandle;
    private CacheWatcher mCacheWatcher;
    private final List<Future> mScheduledPermissionTasks = new ArrayList();
    private final List<Future> mScheduledPermissionTasks = new ArrayList();
    private IMediaProjectionManager mProjectionService; // to validate projection token
    private IMediaProjectionManager mProjectionService; // to validate projection token
@@ -11093,31 +11094,26 @@ public class AudioService extends IAudioService.Stub
                    }, getAudioPermissionsDelay(), TimeUnit.MILLISECONDS));
                    }, getAudioPermissionsDelay(), TimeUnit.MILLISECONDS));
                }
                }
            };
            };
            if (PropertyInvalidatedCache.separatePermissionNotificationsEnabled()) {
                mCacheWatcher = new CacheWatcher(task);
                mCacheWatcher.start();
            } else {
                mSysPropListenerNativeHandle = mAudioSystem.listenForSystemPropertyChange(
                mSysPropListenerNativeHandle = mAudioSystem.listenForSystemPropertyChange(
                        PermissionManager.CACHE_KEY_PACKAGE_INFO_NOTIFY,
                        PermissionManager.CACHE_KEY_PACKAGE_INFO_NOTIFY,
                        task);
                        task);
            }
        } else {
        } else {
            mAudioSystem.listenForSystemPropertyChange(
            mAudioSystem.listenForSystemPropertyChange(
                    PermissionManager.CACHE_KEY_PACKAGE_INFO_NOTIFY,
                    PermissionManager.CACHE_KEY_PACKAGE_INFO_NOTIFY,
                    () -> mAudioServerLifecycleExecutor.execute(
                    () -> mAudioServerLifecycleExecutor.execute(
                                mPermissionProvider::onPermissionStateChanged));
                                mPermissionProvider::onPermissionStateChanged));
        }
        }
        if (PropertyInvalidatedCache.separatePermissionNotificationsEnabled()) {
            new PackageInfoTransducer().start();
        }
    }
    }
    /**
    /**
     * A transducer that converts high-speed changes in the CACHE_KEY_PACKAGE_INFO_CACHE
     * Listens for CACHE_KEY_PACKAGE_INFO_CACHE invalidations to trigger permission syncing
     * PropertyInvalidatedCache into low-speed changes in the CACHE_KEY_PACKAGE_INFO_NOTIFY system
     * property.  This operates on the popcorn principle: changes in the source are done when the
     * source has been quiet for the soak interval.
     *
     * TODO(b/381097912) This is a temporary measure to support migration away from sysprop
     * sniffing.  It should be cleaned up.
     */
     */
    private static class PackageInfoTransducer extends Thread {
    private static class CacheWatcher extends Thread {
        // The run/stop signal.
        // The run/stop signal.
        private final AtomicBoolean mRunning = new AtomicBoolean(false);
        private final AtomicBoolean mRunning = new AtomicBoolean(false);
@@ -11125,81 +11121,33 @@ public class AudioService extends IAudioService.Stub
        // The source of change information.
        // The source of change information.
        private final PropertyInvalidatedCache.NonceWatcher mWatcher;
        private final PropertyInvalidatedCache.NonceWatcher mWatcher;
        // The handler for scheduling delayed reactions to changes.
        // Task to trigger when cache changes
        private final Handler mHandler;
        private final Runnable mTask;
        // How long to soak changes: 50ms is the legacy choice.
        public CacheWatcher(Runnable r) {
        private final static long SOAK_TIME_MS = 50;
            mWatcher = PropertyInvalidatedCache.getNonceWatcher(
                    PermissionManager.CACHE_KEY_PACKAGE_INFO_CACHE);
        // The ubiquitous lock.
            mTask = r;
        private final Object mLock = new Object();
        // If positive, this is the soak expiration time.
        @GuardedBy("mLock")
        private long mSoakDeadlineMs = -1;
        // A source of unique long values.
        @GuardedBy("mLock")
        private long mToken = 0;
        PackageInfoTransducer() {
            mWatcher = PropertyInvalidatedCache
                       .getNonceWatcher(PermissionManager.CACHE_KEY_PACKAGE_INFO_CACHE);
            mHandler = new Handler(BackgroundThread.getHandler().getLooper()) {
                    @Override
                    public void handleMessage(Message msg) {
                        PackageInfoTransducer.this.handleMessage(msg);
                    }};
        }
        }
        public void run() {
        public void run() {
            mRunning.set(true);
            mRunning.set(true);
            while (mRunning.get()) {
            while (mRunning.get()) {
                doCheck();
                try {
                try {
                    final int changes = mWatcher.waitForChange();
                    mWatcher.waitForChange();
                    if (changes == 0 || !mRunning.get()) {
                        continue;
                    }
                } catch (InterruptedException e) {
                } catch (InterruptedException e) {
                    Log.wtf(TAG, "Unexpected Interrupt", e);
                    // We don't know why the exception occurred but keep running until told to
                    // We don't know why the exception occurred but keep running until told to
                    // stop.
                    // stop.
                    continue;
                    continue;
                }
                }
                trigger();
            }
            }
            }
        @GuardedBy("mLock")
        private void updateLocked() {
            String n = Long.toString(mToken++);
            SystemPropertySetter.setWithRetry(PermissionManager.CACHE_KEY_PACKAGE_INFO_NOTIFY, n);
        }
        }
        private void trigger() {
        public synchronized void doCheck() {
            synchronized (mLock) {
            if (mWatcher.isChanged()) {
                boolean alreadyQueued = mSoakDeadlineMs >= 0;
                mTask.run();
                final long nowMs = SystemClock.uptimeMillis();
                mSoakDeadlineMs = nowMs + SOAK_TIME_MS;
                if (!alreadyQueued) {
                    mHandler.sendEmptyMessageAtTime(0, mSoakDeadlineMs);
                    updateLocked();
                }
            }
        }
        private void handleMessage(Message msg) {
            synchronized (mLock) {
                if (mSoakDeadlineMs < 0) {
                    return;  // ???
                }
                final long nowMs = SystemClock.uptimeMillis();
                if (mSoakDeadlineMs > nowMs) {
                    mSoakDeadlineMs = nowMs + SOAK_TIME_MS;
                    mHandler.sendEmptyMessageAtTime(0, mSoakDeadlineMs);
                    return;
                }
                mSoakDeadlineMs = -1;
                updateLocked();
            }
            }
        }
        }
@@ -15376,7 +15324,11 @@ public class AudioService extends IAudioService.Stub
    /** @see AudioManager#permissionUpdateBarrier() */
    /** @see AudioManager#permissionUpdateBarrier() */
    public void permissionUpdateBarrier() {
    public void permissionUpdateBarrier() {
        if (!audioserverPermissions()) return;
        if (!audioserverPermissions()) return;
        if (PropertyInvalidatedCache.separatePermissionNotificationsEnabled()) {
            mCacheWatcher.doCheck();
        } else {
            mAudioSystem.triggerSystemPropertyUpdate(mSysPropListenerNativeHandle);
            mAudioSystem.triggerSystemPropertyUpdate(mSysPropListenerNativeHandle);
        }
        List<Future> snapshot;
        List<Future> snapshot;
        synchronized (mScheduledPermissionTasks) {
        synchronized (mScheduledPermissionTasks) {
            snapshot = List.copyOf(mScheduledPermissionTasks);
            snapshot = List.copyOf(mScheduledPermissionTasks);