Skip to main content

aios_spec/
event.rs

1//! 事件类型定义 —— "what"
2//!
3//! 从系统采集的原始事件 (`RawEvent`) 到脱敏后的统一事件 (`SanitizedEvent`)。
4//! 这是 DiPECS 数据模型的核心。
5
6use serde::{Deserialize, Serialize};
7
8// ============================================================
9// RawEvent — 原始事件 (含 PII, 仅存在于 collector-core 边界内)
10// ============================================================
11
12/// 从系统采集的原始事件, 未经脱敏。
13///
14/// 此类型仅存在于 aios-collector → aios-core 的传输路径上,
15/// 经由 `PrivacySanitizer` 处理后再也不包含原始敏感数据。
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
17pub enum RawEvent {
18    /// 应用前后台切换 (UsageStatsManager)
19    AppTransition(AppTransitionRawEvent),
20    /// Binder 事务 (eBPF tracepoint)
21    BinderTransaction(BinderTxEvent),
22    /// 进程状态变化 (/proc 轮询)
23    ProcStateChange(ProcStateEvent),
24    /// 文件系统访问 (fanotify)
25    FileSystemAccess(FsAccessEvent),
26    /// 通知到达 (NotificationListenerService)
27    NotificationPosted(NotificationRawEvent),
28    /// 通知交互 (用户点击/清除)
29    NotificationInteraction(NotificationInteractionRawEvent),
30    /// 屏幕状态变化
31    ScreenState(ScreenStateEvent),
32    /// 系统状态快照 (周期性采集)
33    SystemState(SystemStateEvent),
34}
35
36/// apps / collector interface 到 Rust 入口的事件信封。
37///
38/// envelope 只描述来源、版本和传输元信息;真正进入脱敏管线的事件
39/// 仍然是 `raw_event` 中的 `RawEvent`。
40#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
41pub struct CollectorEnvelope {
42    pub schema_version: String,
43    pub source: String,
44    pub source_tier: SourceTier,
45    pub device_trace_id: Option<String>,
46    pub captured_at_ms: i64,
47    pub received_at_ms: Option<i64>,
48    pub raw_event: RawEvent,
49}
50
51/// `RawEvent` packaged with the authoritative `SourceTier` declared by its
52/// ingress (envelope or internal collector). This is the only shape that
53/// flows through the core bus — the tier travels with the event so the
54/// downstream sanitizer can honor it instead of re-inferring per type.
55#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
56pub struct IngestedRawEvent {
57    pub raw_event: RawEvent,
58    pub source_tier: SourceTier,
59}
60
61// ===== RawEvent 子类型 =====
62
63#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
64pub struct AppTransitionRawEvent {
65    pub timestamp_ms: i64,
66    pub package_name: String,
67    pub activity_class: Option<String>,
68    pub transition: AppTransition,
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
72pub enum AppTransition {
73    Foreground,
74    Background,
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
78pub struct BinderTxEvent {
79    pub timestamp_ms: i64,
80    pub source_pid: u32,
81    pub source_uid: u32,
82    /// e.g. "notification", "activity", "window"
83    pub target_service: String,
84    /// e.g. "enqueueNotificationWithTag"
85    pub target_method: String,
86    pub is_oneway: bool,
87    /// Parcel 大小, 不存内容
88    pub payload_size: u32,
89}
90
91#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
92pub struct ProcStateEvent {
93    pub timestamp_ms: i64,
94    pub pid: u32,
95    pub uid: u32,
96    pub package_name: Option<String>,
97    pub vm_rss_kb: u64,
98    pub vm_swap_kb: u64,
99    pub threads: u32,
100    /// oom_score: -1000 ~ 1000, 越低越不容易被 LMK 杀死
101    pub oom_score: i32,
102    pub io_read_mb: u64,
103    pub io_write_mb: u64,
104    pub state: ProcState,
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
108pub enum ProcState {
109    Running,
110    Sleeping,
111    Zombie,
112    Unknown,
113}
114
115#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
116pub struct FsAccessEvent {
117    pub timestamp_ms: i64,
118    pub pid: u32,
119    pub uid: u32,
120    /// 完整文件路径 (脱敏时将只保留扩展名)
121    pub file_path: String,
122    pub access_type: FsAccessType,
123    pub bytes_transferred: Option<u64>,
124}
125
126#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
127pub enum FsAccessType {
128    OpenRead,
129    OpenWrite,
130    Create,
131    Delete,
132}
133
134/// 通知原始事件 — ⚠️ 含 PII (标题和正文)
135#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
136pub struct NotificationRawEvent {
137    pub timestamp_ms: i64,
138    pub package_name: String,
139    pub category: Option<String>,
140    pub channel_id: Option<String>,
141    /// ⚠️ PII
142    pub raw_title: String,
143    /// ⚠️ PII
144    pub raw_text: String,
145    pub is_ongoing: bool,
146    pub group_key: Option<String>,
147    pub has_picture: bool,
148}
149
150#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
151pub struct NotificationInteractionRawEvent {
152    pub timestamp_ms: i64,
153    pub package_name: String,
154    pub notification_key: String,
155    pub action: NotificationAction,
156}
157
158#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
159pub enum NotificationAction {
160    Tapped,
161    Dismissed,
162    Cancelled,
163    Seen,
164}
165
166#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
167pub struct ScreenStateEvent {
168    pub timestamp_ms: i64,
169    pub state: ScreenState,
170}
171
172#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
173pub struct SystemStateEvent {
174    pub timestamp_ms: i64,
175    pub battery_pct: Option<u8>,
176    pub is_charging: bool,
177    pub network: NetworkType,
178    pub ringer_mode: RingerMode,
179    pub location_type: LocationType,
180    pub headphone_connected: bool,
181    pub bluetooth_connected: bool,
182}
183
184// ============================================================
185// 辅助枚举 — 跨类型共用
186// ============================================================
187
188#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
189pub enum SourceTier {
190    PublicApi = 0,
191    Daemon = 1,
192    PrivilegedDaemon = 2,
193    SystemImage = 3,
194}
195
196#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
197pub enum InteractionType {
198    NotifyPost,
199    ActivityLaunch,
200    ShareIntent,
201    ServiceBind,
202}
203
204#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
205pub struct TextHint {
206    pub length_chars: usize,
207    pub script: ScriptHint,
208    pub is_emoji_only: bool,
209}
210
211#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
212pub enum ScriptHint {
213    Latin,
214    Hanzi,
215    Cyrillic,
216    Arabic,
217    Mixed,
218    Unknown,
219}
220
221#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
222pub enum SemanticHint {
223    FileMention,
224    ImageMention,
225    AudioMessage,
226    LinkAttachment,
227    UserMentioned,
228    CalendarInvitation,
229    FinancialContext,
230    VerificationCode,
231}
232
233#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
234pub enum ExtensionCategory {
235    Document,
236    Image,
237    Video,
238    Audio,
239    Archive,
240    Code,
241    Other,
242    Unknown,
243}
244
245#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
246pub enum FsActivityType {
247    Read,
248    Write,
249    Create,
250    Delete,
251}
252
253#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
254pub enum ScreenState {
255    Interactive,
256    NonInteractive,
257    KeyguardShown,
258    KeyguardHidden,
259}
260
261#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
262pub enum NetworkType {
263    Wifi,
264    Cellular,
265    Offline,
266    Unknown,
267}
268
269#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
270pub enum RingerMode {
271    Normal,
272    Vibrate,
273    Silent,
274}
275
276#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
277pub enum LocationType {
278    Home,
279    Work,
280    Commute,
281    Unknown,
282}