001// SPDX-License-Identifier: GPL-3.0-or-later
002// Copyright © 2026 Aurélien Pierre
003
004package com.aurelienpierre.sioul;
005
006import android.content.ContentProvider;
007import android.content.ContentValues;
008import android.content.Context;
009import android.database.Cursor;
010import android.net.Uri;
011import android.system.ErrnoException;
012import android.system.Os;
013import android.util.Log;
014import android.view.accessibility.AccessibilityManager;
015
016/**
017 * What is chosen as Sioul's process starts, before anything of Qt's (Android
018 * makes an app's providers first): Qt's accessibility is kept for screen
019 * readers. Android counts as accessibility any service that reads windows,
020 * such as a password manager filling forms (Bitwarden's), and Qt then walks
021 * every item of a page at each change of the screen to describe it: seconds
022 * of work while a long page scrolls, for nobody. With TalkBack or another
023 * screen reader on (touch exploration), Qt's accessibility is as Qt makes
024 * it; a screen reader turned on while Sioul runs reads it from its next start.
025 */
026public final class StartChoices extends ContentProvider
027{
028    /** Read by Qt's Java side (QtAccessibilityDelegate) at each change of accessibility. */
029    private static final String NO_ACCESSIBILITY = "QT_ANDROID_DISABLE_ACCESSIBILITY";
030
031    @Override
032    public boolean onCreate()
033    {
034        final Context context = getContext();
035        final AccessibilityManager manager = context == null ? null : (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
036        final boolean reader = manager != null && manager.isTouchExplorationEnabled();
037        try {
038            if (reader)
039                Os.unsetenv(NO_ACCESSIBILITY);
040            else
041                Os.setenv(NO_ACCESSIBILITY, "1", true);
042        } catch (ErrnoException e) {
043            Log.w(DoseAlarms.TAG, "Accessibility: the choice could not be made: " + e);
044        }
045        return true;
046    }
047
048    @Override
049    public Cursor query(Uri uri, String[] projection, String selection, String[] args, String order)
050    {
051        return null;
052    }
053
054    @Override
055    public String getType(Uri uri)
056    {
057        return null;
058    }
059
060    @Override
061    public Uri insert(Uri uri, ContentValues values)
062    {
063        return null;
064    }
065
066    @Override
067    public int delete(Uri uri, String selection, String[] args)
068    {
069        return 0;
070    }
071
072    @Override
073    public int update(Uri uri, ContentValues values, String selection, String[] args)
074    {
075        return 0;
076    }
077}