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}