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

Commit 726d387e authored by Jacky Kao's avatar Jacky Kao
Browse files

Adds APIs to let live caption can access the data in the DB (2/n)

1. Proposes the public APIs to get and the system APIs to set the
status of the captions and UI show/hide, and notify the status change.

2. Creates a new class, CaptioningManagerImpl, to get/set the value
of the secure setting keys through the A11yManagerService.

3. Adds a new permission, to protect the setter methods which can't
be used by 3rd party apps.

Bug: 136282740
Test: a11y CTS & unit tests
Change-Id: I591b98578dbb94ca8b5be8a553b81d23a143ee16
Ignore-AOSP-First: new permissions (not yet in AOSP)
parent 7ade3e1c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -52371,6 +52371,8 @@ package android.view.accessibility {
    method @NonNull public android.view.accessibility.CaptioningManager.CaptionStyle getUserStyle();
    method public boolean isCallCaptioningEnabled();
    method public final boolean isEnabled();
    method public final boolean isSystemAudioCaptioningRequested();
    method public final boolean isSystemAudioCaptioningUiRequested();
    method public void removeCaptioningChangeListener(@NonNull android.view.accessibility.CaptioningManager.CaptioningChangeListener);
  }
@@ -52399,6 +52401,8 @@ package android.view.accessibility {
    method public void onEnabledChanged(boolean);
    method public void onFontScaleChanged(float);
    method public void onLocaleChanged(@Nullable java.util.Locale);
    method public void onSystemAudioCaptioningChanged(boolean);
    method public void onSystemAudioCaptioningUiChanged(boolean);
    method public void onUserStyleChanged(@NonNull android.view.accessibility.CaptioningManager.CaptionStyle);
  }
+6 −0
Original line number Diff line number Diff line
@@ -293,6 +293,7 @@ package android {
    field public static final String SET_ORIENTATION = "android.permission.SET_ORIENTATION";
    field public static final String SET_POINTER_SPEED = "android.permission.SET_POINTER_SPEED";
    field public static final String SET_SCREEN_COMPATIBILITY = "android.permission.SET_SCREEN_COMPATIBILITY";
    field public static final String SET_SYSTEM_AUDIO_CAPTION = "android.permission.SET_SYSTEM_AUDIO_CAPTION";
    field public static final String SET_VOLUME_KEY_LONG_PRESS_LISTENER = "android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER";
    field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
    field public static final String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
@@ -15172,6 +15173,11 @@ package android.view.accessibility {
    method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void unregisterSystemAction(int);
  }
  public class CaptioningManager {
    method @RequiresPermission(android.Manifest.permission.SET_SYSTEM_AUDIO_CAPTION) public final void setSystemAudioCaptioningRequested(boolean);
    method @RequiresPermission(android.Manifest.permission.SET_SYSTEM_AUDIO_CAPTION) public final void setSystemAudioCaptioningUiRequested(boolean);
  }
}
package android.view.autofill {
+68 −0
Original line number Diff line number Diff line
@@ -1766,6 +1766,74 @@ public final class AccessibilityManager {
        }
    }

    /**
     * Sets the system audio caption enabled state.
     *
     * @param isEnabled The system audio captioning enabled state.
     * @param userId The user Id.
     * @hide
     */
    @RequiresPermission(Manifest.permission.SET_SYSTEM_AUDIO_CAPTION)
    public void setSystemAudioCaptioningRequested(boolean isEnabled, int userId) {
        final IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return;
            }
        }
        try {
            service.setSystemAudioCaptioningRequested(isEnabled, userId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the system audio caption UI enabled state.
     *
     * @param userId The user Id.
     * @return the system audio caption UI enabled state.
     * @hide
     */
    public boolean isSystemAudioCaptioningUiRequested(int userId) {
        final IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return false;
            }
        }
        try {
            return service.isSystemAudioCaptioningUiRequested(userId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Sets the system audio caption UI enabled state.
     *
     * @param isEnabled The system audio captioning UI enabled state.
     * @param userId The user Id.
     * @hide
     */
    @RequiresPermission(Manifest.permission.SET_SYSTEM_AUDIO_CAPTION)
    public void setSystemAudioCaptioningUiRequested(boolean isEnabled, int userId) {
        final IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return;
            }
        }
        try {
            service.setSystemAudioCaptioningUiRequested(isEnabled, userId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    private IAccessibilityManager getServiceLocked() {
        if (mService == null) {
            tryConnectToServiceLocked(null);
+132 −0
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package android.view.accessibility;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
@@ -44,6 +47,7 @@ import java.util.Locale;
public class CaptioningManager {
    /** Default captioning enabled value. */
    private static final int DEFAULT_ENABLED = 0;
    private static final boolean SYSTEM_AUDIO_CAPTIONING_DEFAULT_ENABLED = false;

    /** Default style preset as an index into {@link CaptionStyle#PRESETS}. */
    private static final int DEFAULT_PRESET = 0;
@@ -55,6 +59,8 @@ public class CaptioningManager {
    private final ContentResolver mContentResolver;
    private final ContentObserver mContentObserver;
    private final Resources mResources;
    private final Context mContext;
    private final AccessibilityManager mAccessibilityManager;

    /**
     * Creates a new captioning manager for the specified context.
@@ -62,7 +68,9 @@ public class CaptioningManager {
     * @hide
     */
    public CaptioningManager(Context context) {
        mContext = context;
        mContentResolver = context.getContentResolver();
        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);

        final Handler handler = new Handler(context.getMainLooper());
        mContentObserver = new MyContentObserver(handler);
@@ -141,6 +149,60 @@ public class CaptioningManager {
        return CaptionStyle.PRESETS[preset];
    }

    /**
     * @return the system audio caption enabled state.
     */
    public final boolean isSystemAudioCaptioningRequested() {
        return Secure.getIntForUser(mContentResolver, Secure.ODI_CAPTIONS_ENABLED,
                SYSTEM_AUDIO_CAPTIONING_DEFAULT_ENABLED ? 1 : 0, mContext.getUserId()) == 1;
    }

    /**
     * Sets the system audio caption enabled state.
     *
     * @param isEnabled The system audio captioning enabled state.
     *
     * @throws SecurityException if the caller does not have permission
     * {@link Manifest.permission#SET_SYSTEM_AUDIO_CAPTION}
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.SET_SYSTEM_AUDIO_CAPTION)
    public final void setSystemAudioCaptioningRequested(boolean isEnabled) {
        if (mAccessibilityManager != null) {
            mAccessibilityManager.setSystemAudioCaptioningRequested(isEnabled,
                    mContext.getUserId());
        }
    }

    /**
     * @return the system audio caption UI enabled state.
     */
    public final boolean isSystemAudioCaptioningUiRequested() {
        return mAccessibilityManager != null
                && mAccessibilityManager.isSystemAudioCaptioningUiRequested(mContext.getUserId());
    }

    /**
     * Sets the system audio caption UI enabled state.
     *
     * @param isEnabled The system audio captioning UI enabled state.
     *
     * @throws SecurityException if the caller does not have permission
     * {@link Manifest.permission#SET_SYSTEM_AUDIO_CAPTION}
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.SET_SYSTEM_AUDIO_CAPTION)
    public final void setSystemAudioCaptioningUiRequested(boolean isEnabled) {
        if (mAccessibilityManager != null) {
            mAccessibilityManager.setSystemAudioCaptioningUiRequested(isEnabled,
                    mContext.getUserId());
        }
    }

    /**
     * Adds a listener for changes in the user's preferred captioning enabled
     * state and visual properties.
@@ -160,6 +222,8 @@ public class CaptioningManager {
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE);
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_PRESET);
                registerObserver(Secure.ODI_CAPTIONS_ENABLED);
                registerObserver(Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED);
            }

            mListeners.add(listener);
@@ -229,6 +293,24 @@ public class CaptioningManager {
        }
    }

    private void notifySystemAudioCaptionChanged() {
        final boolean enabled = isSystemAudioCaptioningRequested();
        synchronized (mListeners) {
            for (CaptioningChangeListener listener : mListeners) {
                listener.onSystemAudioCaptioningChanged(enabled);
            }
        }
    }

    private void notifySystemAudioCaptionUiChanged() {
        final boolean enabled = isSystemAudioCaptioningUiRequested();
        synchronized (mListeners) {
            for (CaptioningChangeListener listener : mListeners) {
                listener.onSystemAudioCaptioningUiChanged(enabled);
            }
        }
    }

    private class MyContentObserver extends ContentObserver {
        private final Handler mHandler;

@@ -248,6 +330,10 @@ public class CaptioningManager {
                notifyLocaleChanged();
            } else if (Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE.equals(name)) {
                notifyFontScaleChanged();
            } else if (Secure.ODI_CAPTIONS_ENABLED.equals(name)) {
                notifySystemAudioCaptionChanged();
            } else if (Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED.equals(name)) {
                notifySystemAudioCaptionUiChanged();
            } else {
                // We only need a single callback when multiple style properties
                // change in rapid succession.
@@ -565,5 +651,51 @@ public class CaptioningManager {
         * @see CaptioningManager#getFontScale()
         */
        public void onFontScaleChanged(float fontScale) {}


        /**
         * Called when the system audio caption enabled state changes.
         *
         * @param enabled the system audio caption enabled state
         */
        public void onSystemAudioCaptioningChanged(boolean enabled) {}

        /**
         * Called when the system audio caption UI enabled state changes.
         *
         * @param enabled the system audio caption UI enabled state
         */
        public void onSystemAudioCaptioningUiChanged(boolean enabled) {}
    }

    /**
     * Interface for accessing the system audio captioning related secure setting keys.
     *
     * @hide
     */
    public interface SystemAudioCaptioningAccessing {
        /**
         * Sets the system audio caption enabled state.
         *
         * @param isEnabled The system audio captioning enabled state.
         * @param userId The user Id.
         */
        void setSystemAudioCaptioningRequested(boolean isEnabled, int userId);

        /**
         * Gets the system audio caption UI enabled state.
         *
         * @param userId The user Id.
         * @return the system audio caption UI enabled state.
         */
        boolean isSystemAudioCaptioningUiRequested(int userId);

        /**
         * Sets the system audio caption UI enabled state.
         *
         * @param isEnabled The system audio captioning UI enabled state.
         * @param userId The user Id.
         */
        void setSystemAudioCaptioningUiRequested(boolean isEnabled, int userId);
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -100,4 +100,14 @@ interface IAccessibilityManager {
    int getFocusColor();

    boolean isAudioDescriptionByDefaultEnabled();

    // Requires Manifest.permission.SET_SYSTEM_AUDIO_CAPTION
    // System process only
    void setSystemAudioCaptioningRequested(boolean isEnabled, int userId);

    boolean isSystemAudioCaptioningUiRequested(int userId);

    // Requires Manifest.permission.SET_SYSTEM_AUDIO_CAPTION
    // System process only
    void setSystemAudioCaptioningUiRequested(boolean isEnabled, int userId);
}
Loading