Package com.aurelienpierre.sioul
Class AppNotes
java.lang.Object
android.content.Context
android.content.ContextWrapper
android.app.Service
android.service.notification.NotificationListenerService
com.aurelienpierre.sioul.AppNotes
- All Implemented Interfaces:
ComponentCallbacks,ComponentCallbacks2
Other apps' notifications held until their time (docs/android.md,
"Notifications from other apps"; crates/sioul-app/src/appnotes.rs, which
decides; crates/sioul-core/src/appnotes.rs, how).
Android's notification listener, bound by the system once the person gives
Sioul "Notification access", in a process of its own (":listener"): Qt's
window ends its whole process as it closes (System.exit in
QtActivityBase.onDestroy), which would unbind the listener at each close,
and the background service's process (":steps") runs only when its own
setting is on and does long work a notification must not wait for. Here,
Sioul's library without Qt's window (
DoseAlarms.load(android.content.Context)), as for the doses.
For each notification of another app: what Android says of it, its words
included, handed to Rust in memory on a thread of its own; Rust answers how
long it waits, and Android holds it that long (snoozeNotification): it
comes back whole, with its own tap and actions, alerting as its channel
says. Nothing is ever cancelled, kept or logged; of a conversation, only
where its page is in Android (its app, shortcut and channel, a week), for
the Other apps tab to open it. Nothing is answered or marked as read but
what you ask from a computer, once, through the notification's own Reply
or Mark as read (answer).
Never asked about: Sioul's own, ongoing ones (a call, music, a download),
those that cannot be cleared.
What is held is worked out again (`review`) when something changes that
moves its time: a pause ends, the switch of do-not-disturb, the hours, the
choices. Sioul's files are watched for that.
Replies from your computers (Replies.java; crates/sioul-app/src/replies.rs):
what each relayed notification offers (a Reply, a Mark as read) is said to
Rust with it, and its going when Android takes it away; what the
background step hands over in Sioul's private replies folder is sent here,
the listener alone holding the notifications, each once (answer).-
Nested Class Summary
Nested classes/interfaces inherited from class android.service.notification.NotificationListenerService
NotificationListenerService.Ranking, NotificationListenerService.RankingMapNested classes/interfaces inherited from class android.content.Context
Context.BindServiceFlags -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final longA sound or vibration this recent was the notification's own, as it came.private final RunnableWhat is due sent after the step wrote it: one runnable, so that a burst of changes runs it once.private static final StringThe conversations answered from a computer lately, there (Rust's `replies::ANSWERED`): what is held of them comes now.private static booleanBound by Android, the access given: notifications are decided and held only then.private static final StringAndroid's list of conversations (Settings ▸ Notifications ▸ Conversations), Android 11 and later.private static final StringThe file of what is due there, written whole by the background step.private static final longChanges to what is due settle this long before it is read.Each app's name as the phone shows it, by package, found once a process (`label`).private static final StringAndroid's words in a notification it redacted for an untrusted listener (Android 15).private StringAndroid's words in a redacted notification, in the phone's language; read once (`redacted`).private static final StringSioul's private folder for replies, in its state (Rust's `replies::private_folder`).private final RunnableWhat is held worked out again after Sioul's files changed: one runnable, so that a burst of changes runs it once.private static final longChanges to Sioul's files settle this long before what is held is worked out again.private StringThe phone's default SMS app's package, "" for none (`smsApp`), and when it was last asked.private long(package private) static final StringThe log's tag, the doses' own: `adb logcat -s sioul` shows both.private static final longWritten again at most this often when nothing changed: not at each message.private static final longA conversation unseen for eight days is forgotten (`forgotten`).private static final StringWhat Android says of each conversation seen lately, by Rust's key for it (crates/sioul-core/src/appnotes.rs, `talk_key` of its app and its shortcut): its app, its shortcut and its channel, so that the Other apps tab can open its page in Android, where a conversation set to Always through is marked important (priority), which Sioul's modes let through (PauseMode).private static final intAt most this many conversations kept; past them, the oldest seen go first.private HandlerThreadThe listener's own thread, made in onCreate, ended in onDestroy: nothing is decided on Android's main thread.private static final String[]The files whose change may move what is held: the pause and free time, the switch of do-not-disturb and its people, a focus session, the hours and settings (who may reach you when among them), the lists of senders, the choices, Health's meals and nights, today's slots of time for you (which the window writes as it lays out the day).private final List<FileObserver> The watches of Sioul's folders (`watch`), stopped when the listener is unbound or ends.private HandlerThat thread's queue: each notification, each review and the files' watch go through it, one at a time.Fields inherited from class android.service.notification.NotificationListenerService
ACTION_SETTINGS_HOME, FLAG_FILTER_TYPE_ALERTING, FLAG_FILTER_TYPE_CONVERSATIONS, FLAG_FILTER_TYPE_ONGOING, FLAG_FILTER_TYPE_SILENT, HINT_HOST_DISABLE_CALL_EFFECTS, HINT_HOST_DISABLE_EFFECTS, HINT_HOST_DISABLE_NOTIFICATION_EFFECTS, INTERRUPTION_FILTER_ALARMS, INTERRUPTION_FILTER_ALL, INTERRUPTION_FILTER_NONE, INTERRUPTION_FILTER_PRIORITY, INTERRUPTION_FILTER_UNKNOWN, META_DATA_DEFAULT_AUTOBIND, META_DATA_DEFAULT_FILTER_TYPES, META_DATA_DISABLED_FILTER_TYPES, NOTIFICATION_CHANNEL_OR_GROUP_ADDED, NOTIFICATION_CHANNEL_OR_GROUP_DELETED, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED, REASON_APP_CANCEL, REASON_APP_CANCEL_ALL, REASON_ASSISTANT_CANCEL, REASON_CANCEL, REASON_CANCEL_ALL, REASON_CHANNEL_BANNED, REASON_CHANNEL_REMOVED, REASON_CLEAR_DATA, REASON_CLICK, REASON_ERROR, REASON_GROUP_OPTIMIZATION, REASON_GROUP_SUMMARY_CANCELED, REASON_LISTENER_CANCEL, REASON_LISTENER_CANCEL_ALL, REASON_LOCKDOWN, REASON_PACKAGE_BANNED, REASON_PACKAGE_CHANGED, REASON_PACKAGE_SUSPENDED, REASON_PROFILE_TURNED_OFF, REASON_SNOOZED, REASON_TIMEOUT, REASON_UNAUTOBUNDLED, REASON_USER_STOPPED, SERVICE_INTERFACE, SUPPRESSED_EFFECT_SCREEN_OFF, SUPPRESSED_EFFECT_SCREEN_ONFields inherited from class android.app.Service
START_CONTINUATION_MASK, START_FLAG_REDELIVERY, START_FLAG_RETRY, START_NOT_STICKY, START_REDELIVER_INTENT, START_STICKY, START_STICKY_COMPATIBILITY, STOP_FOREGROUND_DETACH, STOP_FOREGROUND_LEGACY, STOP_FOREGROUND_REMOVEFields inherited from class android.content.Context
ACCESSIBILITY_SERVICE, ACCOUNT_SERVICE, ACTIVITY_SERVICE, ADVANCED_PROTECTION_SERVICE, ALARM_SERVICE, APP_FUNCTION_SERVICE, APP_OPS_SERVICE, APP_SEARCH_SERVICE, APPWIDGET_SERVICE, AUDIO_SERVICE, BATTERY_SERVICE, BIND_ABOVE_CLIENT, BIND_ADJUST_WITH_ACTIVITY, BIND_ALLOW_ACTIVITY_STARTS, BIND_ALLOW_OOM_MANAGEMENT, BIND_AUTO_CREATE, BIND_DEBUG_UNBIND, BIND_EXTERNAL_SERVICE, BIND_EXTERNAL_SERVICE_LONG, BIND_IMPORTANT, BIND_INCLUDE_CAPABILITIES, BIND_NOT_FOREGROUND, BIND_NOT_PERCEPTIBLE, BIND_PACKAGE_ISOLATED_PROCESS, BIND_SHARED_ISOLATED_PROCESS, BIND_WAIVE_PRIORITY, BIOMETRIC_SERVICE, BLOB_STORE_SERVICE, BLUETOOTH_SERVICE, BUGREPORT_SERVICE, CAMERA_SERVICE, CAPTIONING_SERVICE, CARRIER_CONFIG_SERVICE, CLIPBOARD_SERVICE, COMPANION_DEVICE_SERVICE, CONNECTIVITY_DIAGNOSTICS_SERVICE, CONNECTIVITY_SERVICE, CONSUMER_IR_SERVICE, CONTACT_KEYS_SERVICE, CONTEXT_IGNORE_SECURITY, CONTEXT_INCLUDE_CODE, CONTEXT_RESTRICTED, CREDENTIAL_SERVICE, CROSS_PROFILE_APPS_SERVICE, DEVICE_ID_DEFAULT, DEVICE_ID_INVALID, DEVICE_LOCK_SERVICE, DEVICE_POLICY_SERVICE, DISPLAY_HASH_SERVICE, DISPLAY_SERVICE, DOMAIN_VERIFICATION_SERVICE, DOWNLOAD_SERVICE, DROPBOX_SERVICE, EUICC_SERVICE, FILE_INTEGRITY_SERVICE, FINGERPRINT_SERVICE, GAME_SERVICE, GRAMMATICAL_INFLECTION_SERVICE, HARDWARE_PROPERTIES_SERVICE, HEALTHCONNECT_SERVICE, INPUT_METHOD_SERVICE, INPUT_SERVICE, IPSEC_SERVICE, JOB_SCHEDULER_SERVICE, KEYGUARD_SERVICE, KEYSTORE_SERVICE, LAUNCHER_APPS_SERVICE, LAYOUT_INFLATER_SERVICE, LOCALE_SERVICE, LOCATION_SERVICE, MEDIA_COMMUNICATION_SERVICE, MEDIA_METRICS_SERVICE, MEDIA_PROJECTION_SERVICE, MEDIA_QUALITY_SERVICE, MEDIA_ROUTER_SERVICE, MEDIA_SESSION_SERVICE, MIDI_SERVICE, MODE_APPEND, MODE_ENABLE_WRITE_AHEAD_LOGGING, MODE_MULTI_PROCESS, MODE_NO_LOCALIZED_COLLATORS, MODE_PRIVATE, MODE_WORLD_READABLE, MODE_WORLD_WRITEABLE, NETWORK_STATS_SERVICE, NFC_SERVICE, NOTIFICATION_SERVICE, NSD_SERVICE, OVERLAY_SERVICE, PEOPLE_SERVICE, PERFORMANCE_HINT_SERVICE, PERSISTENT_DATA_BLOCK_SERVICE, POWER_SERVICE, PRINT_SERVICE, PROFILING_SERVICE, RECEIVER_EXPORTED, RECEIVER_NOT_EXPORTED, RECEIVER_VISIBLE_TO_INSTANT_APPS, RESTRICTIONS_SERVICE, ROLE_SERVICE, SATELLITE_SERVICE, SEARCH_SERVICE, SECURITY_STATE_SERVICE, SENSOR_SERVICE, SHORTCUT_SERVICE, STATUS_BAR_SERVICE, STORAGE_SERVICE, STORAGE_STATS_SERVICE, SYSTEM_HEALTH_SERVICE, TELECOM_SERVICE, TELEPHONY_IMS_SERVICE, TELEPHONY_SERVICE, TELEPHONY_SUBSCRIPTION_SERVICE, TETHERING_SERVICE, TEXT_CLASSIFICATION_SERVICE, TEXT_SERVICES_MANAGER_SERVICE, TV_AD_SERVICE, TV_INPUT_SERVICE, TV_INTERACTIVE_APP_SERVICE, UI_MODE_SERVICE, USAGE_STATS_SERVICE, USB_SERVICE, USER_SERVICE, VIBRATOR_MANAGER_SERVICE, VIBRATOR_SERVICE, VIRTUAL_DEVICE_SERVICE, VPN_MANAGEMENT_SERVICE, WALLPAPER_SERVICE, WIFI_AWARE_SERVICE, WIFI_P2P_SERVICE, WIFI_RTT_RANGING_SERVICE, WIFI_SERVICE, WINDOW_SERVICEFields inherited from interface android.content.ComponentCallbacks2
TRIM_MEMORY_BACKGROUND, TRIM_MEMORY_COMPLETE, TRIM_MEMORY_MODERATE, TRIM_MEMORY_RUNNING_CRITICAL, TRIM_MEMORY_RUNNING_LOW, TRIM_MEMORY_RUNNING_MODERATE, TRIM_MEMORY_UI_HIDDEN -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate voidanswer()Each reply or Mark as read due now (handed over by the background step, which decided it once): sent through its notification's own action, or said why not (answerOne(org.json.JSONObject)); a step soon, so that what became of it reaches your computers.private booleananswerOne(JSONObject due) One due: its notification found again live by the name the line gave it, among what Android shows, then what Sioul holds, of this phone's own profile; Rust's check that it is still the conversation answered; its Reply (or Mark as read) chosen by what it means and refused when it may not go; "taken" written and flushed; then sent once, as the shade sends one.(package private) static StringRust's question (android/main.cpp), from the window's process: the access, Android's pages for it and for each app's, channel's or conversation's notifications, the contacts' permission, what Android says of the conversations seen lately.private static ComponentNameThis listener, as Android's settings and NotificationManager name it.private longcontactOfLookup(String uri) The contact a lookup address names; -1 when none.private longcontactOfName(String name) The one contact with exactly this name; -1 when none, or when several share it.(package private) static JSONObjectconversations(Context context) What Android says of the conversations seen lately, for the Other apps tab: {api, conversations: {key: {important, page}}}: marked important there; `page`, Android takes it as a conversation, whose page Sioul can open (Android 11 and later).private JSONArrayA contact's numbers or addresses.private voiddecide(StatusBarNotification sbn, NotificationListenerService.Ranking ranking) Rust asked, the answer followed: held so long, or left as it came.private JSONObjectdescribe(StatusBarNotification sbn, NotificationListenerService.Ranking ranking) The notification as Rust reads it (crates/sioul-core/src/appnotes.rs, `Posted`).The keys to forget among those kept (each a JSON text with its time "at"): those unseen for a week, then the oldest past the most kept.(package private) static booleanWhether the person gave Sioul "Notification access".private StringThe app's name as the phone shows it, kept; else the one its notification carries; else its package.private JSONArrayA conversation's messages (MessagingStyle), each with its sender as the app names them; the phone's address book asked about the last one's sender only, the one Rust judges.(package private) static StringnativeDecide(String json) Rust's answer for one notification: {"hold": milliseconds, 0 to let it come, "why", "line"}.(package private) static StringnativeReply(String verb, String json) Replies from your computers (crates/sioul-app/src/replies.rs): "due" (what is due now: {due: [{key, verb, notice}]}), "check" ({key, held, posted}: the live notification found for one, {go, crossed} or {go: false, state}), "taken" ({key}: written and flushed first, {go, words}), "result" ({key, state, crossed, held}), "removed" ({package, key}: a relayed notification gone, {shared}).(package private) static StringnativeReview(String json) What is held, worked out again: {"snooze": [{"key", "ms"}]}, for the keys Android holds now.voidonCreate()The listener's own thread started, before Android binds it.voidEnded: nothing held from here on, the watches stopped, the thread let finish what it was doing.voidonInterruptionFilterChanged(int interruptionFilter) The phone's do-not-disturb changed, whatever changed it: Android tells a bound listener of every change (NotificationManagerService, notifyInterruptionFilterChanged), a word surer than the broadcast to the packages with Do Not Disturb access.voidBound, the access given (at the phone's start, when the access is given, after Android restarted the listener): Sioul's files watched, and what Android holds already worked out again.voidUnbound: the access taken back, or Android stopping the listener.voidAnother app's notification, posted or updated: asked about on the worker thread with the ranking Android gave with it.voidonNotificationRemoved(StatusBarNotification sbn, NotificationListenerService.RankingMap rankings, int reason) A notification gone, as Android says it: for one relayed to your computers, its going said there (Rust's `replies::went`), so that they no longer offer its Reply.private static booleanOne of Android's pages opened, in a task of its own; false when this phone has no such page or refuses it.private static booleanopenAccess(Context context) Android's page for Sioul's notification access: its own switch from Android 11, else the list.private static booleanopenConversation(Context context, JSONObject asked) A conversation's page in Android: {key} (Rust's key for it), or {package, shortcut, channel}.(package private) static String[]pages(int api, boolean conversation, boolean own, boolean channel) Which of Android's pages a conversation is opened at, in order, the next one when a page does not open: "conversation", its own page (where Priority is), once Android gave it one; "conversations", the list of conversations, where one not changed yet shows among the recent ones; "app", the app's notifications.private JSONArrayThe people a notification names (EXTRA_PEOPLE_LIST), and the older addresses (EXTRA_PEOPLE); the phone's address book asked about the first only, the one Rust judges when no message names a sender.private JSONObjectperson(CharSequence name, String key, String uri, boolean bot, boolean contacts) A person, with what the phone's address book says of them when Sioul may read it: a contact's lookup address resolved to its numbers and addresses; a name alone, the numbers of the one contact of that name (`by_name`: counted only for apps that name people as the address book does, Rust decides).The ranking Android gives a notification now; null when it gives none (a held one).private booleanWhether Android gave Sioul a redacted copy (Android 15, for a notification its assistant judged sensitive: a code): its title is the app's name and its text Android's own words for it.private static voidremember(Context context, String pkg, String shortcut, String channel, NotificationChannel given, boolean conversation, long now) A conversation seen (the listener, on its worker thread): its app, its shortcut, the channel it was posted on (its parent's when Android gave it a channel of its own), whether Android takes it as a conversation, whether it is marked important there, and whether it has a page of its own there yet (customized once).private voidA notification's going said to Rust, and a step soon when your computers have it to read.private booleanWhat became of one, said to Rust, which writes it (never the words); always true.private voidWhat is held, worked out again; Android told the new times.private booleanWhether do-not-disturb silences every text now (`textsSilenced`), as Android says it.private StringsmsApp()The phone's default SMS app, asked again each minute at most.private voidA notification held by Android for `ms` (a second at least), then given back whole, as it came.private static JSONObjectOne conversation as kept, by Rust's key; null when not seen lately.(package private) static StringA conversation's key as Rust's `talk_key` makes it: FNV-1a (64 bits) of its app, U+001F and its id, in hexadecimal.private static SharedPreferencesWritten by the listener's process, read by the window's.private static StringA text of the extras, a CharSequence or a String; "" when none.(package private) static booleantextsSilenced(int filter, boolean known, int categories, int conversationSenders) Whether a filter silences every text (review of part 4, S-2).private voidunwatch()The watches of Sioul's folders stopped.private voidwatch()The folders of Sioul's state, configuration and data, watched for the files that move what is held.private voidThe private folder of replies watched for what is due (made first, so that it can be watched before the step writes there): the background step writes it whole beside, then puts it in place.Methods inherited from class android.service.notification.NotificationListenerService
attachBaseContext, cancelAllNotifications, cancelNotification, cancelNotification, cancelNotifications, clearRequestedListenerHints, createConversationNotificationChannelForPackage, getActiveNotifications, getActiveNotifications, getCurrentInterruptionFilter, getCurrentListenerHints, getCurrentRanking, getNotificationChannelGroups, getNotificationChannels, getSnoozedNotifications, migrateNotificationFilter, onBind, onListenerHintsChanged, onNotificationChannelGroupModified, onNotificationChannelModified, onNotificationPosted, onNotificationRankingUpdate, onNotificationRemoved, onNotificationRemoved, onSilentStatusBarIconsVisibilityChanged, requestInterruptionFilter, requestListenerHints, requestRebind, requestUnbind, requestUnbind, setNotificationsShown, snoozeNotification, updateNotificationChannelMethods inherited from class android.app.Service
dump, getApplication, getForegroundServiceType, onConfigurationChanged, onLowMemory, onRebind, onStart, onStartCommand, onTaskRemoved, onTimeout, onTimeout, onTrimMemory, onUnbind, startForeground, startForeground, stopForeground, stopForeground, stopSelf, stopSelf, stopSelfResultMethods inherited from class android.content.ContextWrapper
bindIsolatedService, bindService, bindService, bindService, bindService, bindServiceAsUser, bindServiceAsUser, checkCallingOrSelfPermission, checkCallingOrSelfUriPermission, checkCallingOrSelfUriPermissions, checkCallingPermission, checkCallingUriPermission, checkCallingUriPermissions, checkContentUriPermissionFull, checkPermission, checkSelfPermission, checkUriPermission, checkUriPermission, checkUriPermissions, clearWallpaper, createAttributionContext, createConfigurationContext, createContext, createContextForSplit, createDeviceContext, createDeviceProtectedStorageContext, createDisplayContext, createPackageContext, createWindowContext, createWindowContext, databaseList, deleteDatabase, deleteFile, deleteSharedPreferences, enforceCallingOrSelfPermission, enforceCallingOrSelfUriPermission, enforceCallingPermission, enforceCallingUriPermission, enforcePermission, enforceUriPermission, enforceUriPermission, fileList, getApplicationContext, getApplicationInfo, getAssets, getAttributionSource, getAttributionTag, getBaseContext, getCacheDir, getClassLoader, getCodeCacheDir, getContentResolver, getDatabasePath, getDataDir, getDeviceId, getDir, getDisplay, getExternalCacheDir, getExternalCacheDirs, getExternalFilesDir, getExternalFilesDirs, getExternalMediaDirs, getFilesDir, getFileStreamPath, getMainExecutor, getMainLooper, getNoBackupFilesDir, getObbDir, getObbDirs, getOpPackageName, getPackageCodePath, getPackageManager, getPackageName, getPackageResourcePath, getParams, getResources, getSharedPreferences, getSystemService, getSystemServiceName, getTheme, getWallpaper, getWallpaperDesiredMinimumHeight, getWallpaperDesiredMinimumWidth, grantUriPermission, isDeviceProtectedStorage, isRestricted, isUiContext, moveDatabaseFrom, moveSharedPreferencesFrom, openFileInput, openFileOutput, openOrCreateDatabase, openOrCreateDatabase, peekWallpaper, registerComponentCallbacks, registerDeviceIdChangeListener, registerReceiver, registerReceiver, registerReceiver, registerReceiver, removeStickyBroadcast, removeStickyBroadcastAsUser, revokeSelfPermissionsOnKill, revokeUriPermission, revokeUriPermission, sendBroadcast, sendBroadcast, sendBroadcast, sendBroadcastAsUser, sendBroadcastAsUser, sendOrderedBroadcast, sendOrderedBroadcast, sendOrderedBroadcast, sendOrderedBroadcast, sendOrderedBroadcast, sendOrderedBroadcast, sendOrderedBroadcastAsUser, sendStickyBroadcast, sendStickyBroadcast, sendStickyBroadcastAsUser, sendStickyOrderedBroadcast, sendStickyOrderedBroadcastAsUser, setTheme, setWallpaper, setWallpaper, startActivities, startActivities, startActivity, startActivity, startForegroundService, startInstrumentation, startIntentSender, startIntentSender, startService, stopService, unbindService, unregisterComponentCallbacks, unregisterDeviceIdChangeListener, unregisterReceiver, updateServiceGroupMethods inherited from class android.content.Context
bindIsolatedService, getColor, getColorStateList, getDrawable, getString, getString, getSystemService, getText, obtainStyledAttributes, obtainStyledAttributes, obtainStyledAttributes, obtainStyledAttributes, revokeSelfPermissionOnKill, sendBroadcastWithMultiplePermissions
-
Field Details
-
TAG
The log's tag, the doses' own: `adb logcat -s sioul` shows both.- See Also:
-
REDACTED
Android's words in a notification it redacted for an untrusted listener (Android 15).- See Also:
-
ALERTED_MS
A sound or vibration this recent was the notification's own, as it came.- See Also:
-
SETTLE_MS
Changes to Sioul's files settle this long before what is held is worked out again.- See Also:
-
WATCHED
The files whose change may move what is held: the pause and free time, the switch of do-not-disturb and its people, a focus session, the hours and settings (who may reach you when among them), the lists of senders, the choices, Health's meals and nights, today's slots of time for you (which the window writes as it lays out the day). -
connected
Bound by Android, the access given: notifications are decided and held only then. -
thread
The listener's own thread, made in onCreate, ended in onDestroy: nothing is decided on Android's main thread. -
worker
That thread's queue: each notification, each review and the files' watch go through it, one at a time. -
watches
The watches of Sioul's folders (`watch`), stopped when the listener is unbound or ends. -
labels
Each app's name as the phone shows it, by package, found once a process (`label`). -
redactedWords
Android's words in a redacted notification, in the phone's language; read once (`redacted`). -
smsApp
The phone's default SMS app's package, "" for none (`smsApp`), and when it was last asked. -
smsAppAt
-
review
What is held worked out again after Sioul's files changed: one runnable, so that a burst of changes runs it once. -
answer
What is due sent after the step wrote it: one runnable, so that a burst of changes runs it once. -
REPLIES
Sioul's private folder for replies, in its state (Rust's `replies::private_folder`).- See Also:
-
DUE
The file of what is due there, written whole by the background step.- See Also:
-
ANSWERED
The conversations answered from a computer lately, there (Rust's `replies::ANSWERED`): what is held of them comes now.- See Also:
-
DUE_SETTLE_MS
Changes to what is due settle this long before it is read.- See Also:
-
TALKS
What Android says of each conversation seen lately, by Rust's key for it (crates/sioul-core/src/appnotes.rs, `talk_key` of its app and its shortcut): its app, its shortcut and its channel, so that the Other apps tab can open its page in Android, where a conversation set to Always through is marked important (priority), which Sioul's modes let through (PauseMode). This phone's alone, in Sioul's private storage, never shared; forgotten after a week unseen, as the tab forgets its name.- See Also:
-
TALK_KEPT_MS
A conversation unseen for eight days is forgotten (`forgotten`).- See Also:
-
TALKS_AT_MOST
At most this many conversations kept; past them, the oldest seen go first.- See Also:
-
TALK_AGAIN_MS
Written again at most this often when nothing changed: not at each message.- See Also:
-
CONVERSATIONS_PAGE
Android's list of conversations (Settings ▸ Notifications ▸ Conversations), Android 11 and later.- See Also:
-
-
Constructor Details
-
AppNotes
public AppNotes()
-
-
Method Details
-
nativeDecide
Rust's answer for one notification: {"hold": milliseconds, 0 to let it come, "why", "line"}. -
nativeReview
What is held, worked out again: {"snooze": [{"key", "ms"}]}, for the keys Android holds now. -
nativeReply
Replies from your computers (crates/sioul-app/src/replies.rs): "due" (what is due now: {due: [{key, verb, notice}]}), "check" ({key, held, posted}: the live notification found for one, {go, crossed} or {go: false, state}), "taken" ({key}: written and flushed first, {go, words}), "result" ({key, state, crossed, held}), "removed" ({package, key}: a relayed notification gone, {shared}). -
call
Rust's question (android/main.cpp), from the window's process: the access, Android's pages for it and for each app's, channel's or conversation's notifications, the contacts' permission, what Android says of the conversations seen lately. Any thread. -
component
This listener, as Android's settings and NotificationManager name it. -
granted
Whether the person gave Sioul "Notification access". -
openAccess
Android's page for Sioul's notification access: its own switch from Android 11, else the list. -
open
One of Android's pages opened, in a task of its own; false when this phone has no such page or refuses it. -
talks
Written by the listener's process, read by the window's. -
talkKey
A conversation's key as Rust's `talk_key` makes it: FNV-1a (64 bits) of its app, U+001F and its id, in hexadecimal. Pure, checked on a JVM against Rust's values (android/jvm-checks/ModeCheck.java). -
forgotten
The keys to forget among those kept (each a JSON text with its time "at"): those unseen for a week, then the oldest past the most kept. Pure, checked on a JVM (android/jvm-checks/ModeCheck.java). -
remember
private static void remember(Context context, String pkg, String shortcut, String channel, NotificationChannel given, boolean conversation, long now) A conversation seen (the listener, on its worker thread): its app, its shortcut, the channel it was posted on (its parent's when Android gave it a channel of its own), whether Android takes it as a conversation, whether it is marked important there, and whether it has a page of its own there yet (customized once). Written when something changed, or once a day. -
talk
One conversation as kept, by Rust's key; null when not seen lately. -
conversations
What Android says of the conversations seen lately, for the Other apps tab: {api, conversations: {key: {important, page}}}: marked important there; `page`, Android takes it as a conversation, whose page Sioul can open (Android 11 and later).- Throws:
JSONException
-
pages
Which of Android's pages a conversation is opened at, in order, the next one when a page does not open: "conversation", its own page (where Priority is), once Android gave it one; "conversations", the list of conversations, where one not changed yet shows among the recent ones; "app", the app's notifications. Pure, checked on a JVM (android/jvm-checks/ModeCheck.java). -
openConversation
A conversation's page in Android: {key} (Rust's key for it), or {package, shortcut, channel}. False when no page opened. -
onCreate
The listener's own thread started, before Android binds it. -
onDestroy
Ended: nothing held from here on, the watches stopped, the thread let finish what it was doing.- Overrides:
onDestroyin classNotificationListenerService
-
onListenerConnected
Bound, the access given (at the phone's start, when the access is given, after Android restarted the listener): Sioul's files watched, and what Android holds already worked out again.- Overrides:
onListenerConnectedin classNotificationListenerService
-
onInterruptionFilterChanged
The phone's do-not-disturb changed, whatever changed it: Android tells a bound listener of every change (NotificationManagerService, notifyInterruptionFilterChanged), a word surer than the broadcast to the packages with Do Not Disturb access. Decided in Sioul's own process, where its modes are kept (DndReceiver.HEARD), as the broadcast is.- Overrides:
onInterruptionFilterChangedin classNotificationListenerService
-
onListenerDisconnected
Unbound: the access taken back, or Android stopping the listener.- Overrides:
onListenerDisconnectedin classNotificationListenerService
-
onNotificationPosted
public void onNotificationPosted(StatusBarNotification sbn, NotificationListenerService.RankingMap rankings) Another app's notification, posted or updated: asked about on the worker thread with the ranking Android gave with it. Never Sioul's own, an ongoing one (a call, music, a download), or one that cannot be cleared.- Overrides:
onNotificationPostedin classNotificationListenerService
-
onNotificationRemoved
public void onNotificationRemoved(StatusBarNotification sbn, NotificationListenerService.RankingMap rankings, int reason) A notification gone, as Android says it: for one relayed to your computers, its going said there (Rust's `replies::went`), so that they no longer offer its Reply. Never for Sioul's own holding (REASON_SNOOZED), which is no going.- Overrides:
onNotificationRemovedin classNotificationListenerService
-
removed
A notification's going said to Rust, and a step soon when your computers have it to read. On the worker thread. -
decide
Rust asked, the answer followed: held so long, or left as it came. On the worker thread. -
snooze
A notification held by Android for `ms` (a second at least), then given back whole, as it came. -
review
What is held, worked out again; Android told the new times. On the worker thread. One calm line in the log each time (`adb logcat -s sioul`): how many are held and released, by kind, why, and the next release (Rust's `log_line`: kinds, counts and times, never a name, a number, an app or a message's words); or, when Rust could not answer, that in plain words. -
watch
The folders of Sioul's state, configuration and data, watched for the files that move what is held. -
watchReplies
The private folder of replies watched for what is due (made first, so that it can be watched before the step writes there): the background step writes it whole beside, then puts it in place. And for the conversations answered lately: what Sioul holds of one is worked out again, to come now. -
unwatch
The watches of Sioul's folders stopped. -
answer
Each reply or Mark as read due now (handed over by the background step, which decided it once): sent through its notification's own action, or said why not (answerOne(org.json.JSONObject)); a step soon, so that what became of it reaches your computers. On the worker thread. -
answerOne
One due: its notification found again live by the name the line gave it, among what Android shows, then what Sioul holds, of this phone's own profile; Rust's check that it is still the conversation answered; its Reply (or Mark as read) chosen by what it means and refused when it may not go; "taken" written and flushed; then sent once, as the shade sends one. Whether anything was said to Rust.- Throws:
JSONException
-
result
private boolean result(String key, String state, boolean crossed, boolean held) throws JSONException What became of one, said to Rust, which writes it (never the words); always true.- Throws:
JSONException
-
silencesTexts
Whether do-not-disturb silences every text now (`textsSilenced`), as Android says it. -
textsSilenced
Whether a filter silences every text (review of part 4, S-2). Android ranks no held notification, so a held text cannot be asked whether it would ring: "nothing" and "alarms only" silence every text; "priority" only when its policy, as Android 15 and later give it in force (`getConsolidatedNotificationPolicy`, Sioul's mode or yours), lets neither messages nor conversations ring; an older Android's "priority" may let starred contacts' texts ring, so it reads as not silenced, and a text held then waits (docs/android.md). At posting, each text's own ranking says it (`intercepted`). -
ranking
The ranking Android gives a notification now; null when it gives none (a held one). -
describe
private JSONObject describe(StatusBarNotification sbn, NotificationListenerService.Ranking ranking) throws JSONException The notification as Rust reads it (crates/sioul-core/src/appnotes.rs, `Posted`).- Throws:
JSONException
-
text
A text of the extras, a CharSequence or a String; "" when none. -
messages
A conversation's messages (MessagingStyle), each with its sender as the app names them; the phone's address book asked about the last one's sender only, the one Rust judges.- Throws:
JSONException
-
people
The people a notification names (EXTRA_PEOPLE_LIST), and the older addresses (EXTRA_PEOPLE); the phone's address book asked about the first only, the one Rust judges when no message names a sender.- Throws:
JSONException
-
person
private JSONObject person(CharSequence name, String key, String uri, boolean bot, boolean contacts) throws JSONException A person, with what the phone's address book says of them when Sioul may read it: a contact's lookup address resolved to its numbers and addresses; a name alone, the numbers of the one contact of that name (`by_name`: counted only for apps that name people as the address book does, Rust decides).- Throws:
JSONException
-
contactOfLookup
The contact a lookup address names; -1 when none. -
contactOfName
The one contact with exactly this name; -1 when none, or when several share it. -
data
A contact's numbers or addresses. -
label
The app's name as the phone shows it, kept; else the one its notification carries; else its package. -
redacted
Whether Android gave Sioul a redacted copy (Android 15, for a notification its assistant judged sensitive: a code): its title is the app's name and its text Android's own words for it. -
smsApp
The phone's default SMS app, asked again each minute at most.
-