ndk/
configuration.rs

1//! Bindings for [`AConfiguration`]
2//!
3//! See also the [NDK docs](https://developer.android.com/ndk/reference/group/configuration) for
4//! [`AConfiguration`], as well as the [docs for providing
5//! resources](https://developer.android.com/guide/topics/resources/providing-resources.html),
6//! which explain many of the configuration values.  The [`android.content.res.Configuration`
7//! javadoc](https://developer.android.com/reference/android/content/res/Configuration.html) may
8//! also have useful information.
9//!
10//! [`AConfiguration`]: https://developer.android.com/ndk/reference/group/configuration#aconfiguration
11
12use crate::asset::AssetManager;
13use num_enum::{FromPrimitive, IntoPrimitive};
14use std::fmt;
15use std::ptr::NonNull;
16
17/// A native [`AConfiguration *`]
18///
19/// [`Configuration`] is an opaque type used to get and set various subsystem configurations.
20///
21/// [`AConfiguration *`]: https://developer.android.com/ndk/reference/group/configuration#aconfiguration
22pub struct Configuration {
23    ptr: NonNull<ffi::AConfiguration>,
24}
25
26unsafe impl Send for Configuration {}
27unsafe impl Sync for Configuration {}
28
29impl Drop for Configuration {
30    fn drop(&mut self) {
31        unsafe { ffi::AConfiguration_delete(self.ptr.as_ptr()) }
32    }
33}
34
35impl Clone for Configuration {
36    fn clone(&self) -> Self {
37        let mut new = Self::new();
38        new.copy(self);
39        new
40    }
41}
42
43impl PartialEq for Configuration {
44    fn eq(&self, other: &Self) -> bool {
45        self.diff(other).0 == 0
46    }
47}
48impl Eq for Configuration {}
49
50impl fmt::Debug for Configuration {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        f.debug_struct("Configuration")
53            .field("mcc", &self.mcc())
54            .field("mnc", &self.mnc())
55            .field("lang", &self.language())
56            .field("country", &self.country())
57            .field("orientation", &self.orientation())
58            .field("touchscreen", &self.touchscreen())
59            .field("density", &self.density())
60            .field("keyboard", &self.keyboard())
61            .field("navigation", &self.navigation())
62            .field("keys_hidden", &self.keys_hidden())
63            .field("nav_hidden", &self.nav_hidden())
64            .field("sdk_version", &self.sdk_version())
65            .field("screen_size", &self.screen_size())
66            .field("screen_long", &self.screen_long())
67            .field("ui_mode_type", &self.ui_mode_type())
68            .field("ui_mode_night", &self.ui_mode_night())
69            .finish()
70    }
71}
72
73impl Configuration {
74    /// Construct a `Configuration` from a pointer.
75    ///
76    /// # Safety
77    /// By calling this function, you assert that it is a valid pointer to a native
78    /// `AConfiguration`, and give ownership of it to the `Configuration` instance.
79    pub unsafe fn from_ptr(ptr: NonNull<ffi::AConfiguration>) -> Self {
80        Self { ptr }
81    }
82
83    /// Create a new `Configuration`, with the same contents as the `AConfiguration` referenced by
84    /// the pointer.
85    ///
86    /// This is useful if you have a pointer, but not ownership of it.
87    ///
88    /// # Safety
89    /// By calling this function, you assert that it is a valid pointer to a native
90    /// `AConfiguration`.
91    pub unsafe fn clone_from_ptr(ptr: NonNull<ffi::AConfiguration>) -> Self {
92        let conf = Self::new();
93        ffi::AConfiguration_copy(conf.ptr.as_ptr(), ptr.as_ptr());
94        conf
95    }
96
97    /// The pointer to the native `AConfiguration`.  Keep in mind that the `Configuration` object
98    /// still has ownership, and will free it when dropped.
99    pub fn ptr(&self) -> NonNull<ffi::AConfiguration> {
100        self.ptr
101    }
102
103    pub fn from_asset_manager(am: &AssetManager) -> Self {
104        let config = Self::new();
105        unsafe {
106            ffi::AConfiguration_fromAssetManager(config.ptr().as_mut(), am.ptr().as_mut());
107        }
108        config
109    }
110
111    /// Create a new `Configuration`, with none of the values set.
112    pub fn new() -> Self {
113        unsafe {
114            Self {
115                ptr: NonNull::new(ffi::AConfiguration_new()).unwrap(),
116            }
117        }
118    }
119
120    /// `dest.copy(&src)` copies the contents of `src` to `dest`
121    pub fn copy(&mut self, other: &Self) {
122        unsafe { ffi::AConfiguration_copy(self.ptr.as_ptr(), other.ptr.as_ptr()) }
123    }
124
125    /// Information about what fields differ between the two configurations
126    pub fn diff(&self, other: &Self) -> DiffResult {
127        unsafe {
128            DiffResult(ffi::AConfiguration_diff(self.ptr.as_ptr(), other.ptr.as_ptr()) as u32)
129        }
130    }
131
132    /// Returns false if anything in `self` conflicts with `requested`
133    pub fn matches(&self, requested: &Self) -> bool {
134        unsafe { ffi::AConfiguration_match(self.ptr.as_ptr(), requested.ptr.as_ptr()) != 0 }
135    }
136
137    /// Returns the country code, as a [`String`] of two characters, if set
138    pub fn country(&self) -> Option<String> {
139        let mut chars = [0u8; 2];
140        unsafe {
141            ffi::AConfiguration_getCountry(self.ptr.as_ptr(), chars.as_mut_ptr().cast());
142        }
143        if chars[0] == 0 {
144            None
145        } else {
146            Some(std::str::from_utf8(chars.as_slice()).unwrap().to_owned())
147        }
148    }
149
150    /// Returns the screen density in dpi.
151    ///
152    /// On some devices it can return values outside of the density enum.
153    pub fn density(&self) -> Option<u32> {
154        let density = unsafe { ffi::AConfiguration_getDensity(self.ptr.as_ptr()) as u32 };
155        match density {
156            ffi::ACONFIGURATION_DENSITY_DEFAULT => Some(160),
157            ffi::ACONFIGURATION_DENSITY_ANY => None,
158            ffi::ACONFIGURATION_DENSITY_NONE => None,
159            density => Some(density),
160        }
161    }
162
163    /// Returns the keyboard type.
164    pub fn keyboard(&self) -> Keyboard {
165        unsafe { ffi::AConfiguration_getKeyboard(self.ptr.as_ptr()).into() }
166    }
167
168    /// Returns keyboard visibility/availability.
169    pub fn keys_hidden(&self) -> KeysHidden {
170        unsafe { ffi::AConfiguration_getKeysHidden(self.ptr.as_ptr()).into() }
171    }
172
173    /// Returns the language, as a [`String`] of two characters, if set
174    pub fn language(&self) -> Option<String> {
175        let mut chars = [0u8; 2];
176        unsafe {
177            ffi::AConfiguration_getLanguage(self.ptr.as_ptr(), chars.as_mut_ptr().cast());
178        }
179        if chars[0] == 0 {
180            None
181        } else {
182            Some(std::str::from_utf8(chars.as_slice()).unwrap().to_owned())
183        }
184    }
185
186    /// Returns the layout direction
187    pub fn layout_direction(&self) -> LayoutDir {
188        unsafe { ffi::AConfiguration_getLayoutDirection(self.ptr.as_ptr()).into() }
189    }
190
191    /// Returns the mobile country code.
192    pub fn mcc(&self) -> i32 {
193        unsafe { ffi::AConfiguration_getMcc(self.ptr.as_ptr()) }
194    }
195
196    /// Returns the mobile network code, if one is defined
197    pub fn mnc(&self) -> Option<i32> {
198        unsafe {
199            match ffi::AConfiguration_getMnc(self.ptr.as_ptr()) {
200                0 => None,
201                x if x == ffi::ACONFIGURATION_MNC_ZERO as i32 => Some(0),
202                x => Some(x),
203            }
204        }
205    }
206
207    pub fn nav_hidden(&self) -> NavHidden {
208        unsafe { ffi::AConfiguration_getNavHidden(self.ptr.as_ptr()).into() }
209    }
210
211    pub fn navigation(&self) -> Navigation {
212        unsafe { ffi::AConfiguration_getNavigation(self.ptr.as_ptr()).into() }
213    }
214
215    pub fn orientation(&self) -> Orientation {
216        unsafe { ffi::AConfiguration_getOrientation(self.ptr.as_ptr()).into() }
217    }
218
219    pub fn screen_height_dp(&self) -> Option<i32> {
220        unsafe {
221            let height = ffi::AConfiguration_getScreenHeightDp(self.ptr.as_ptr());
222            if height == ffi::ACONFIGURATION_SCREEN_HEIGHT_DP_ANY as i32 {
223                None
224            } else {
225                Some(height)
226            }
227        }
228    }
229
230    pub fn screen_width_dp(&self) -> Option<i32> {
231        unsafe {
232            let width = ffi::AConfiguration_getScreenWidthDp(self.ptr.as_ptr());
233            if width == ffi::ACONFIGURATION_SCREEN_WIDTH_DP_ANY as i32 {
234                None
235            } else {
236                Some(width)
237            }
238        }
239    }
240
241    pub fn screen_long(&self) -> ScreenLong {
242        unsafe { ffi::AConfiguration_getScreenLong(self.ptr.as_ptr()).into() }
243    }
244
245    #[cfg(feature = "api-level-30")]
246    pub fn screen_round(&self) -> ScreenRound {
247        unsafe { ffi::AConfiguration_getScreenRound(self.ptr.as_ptr()).into() }
248    }
249
250    pub fn screen_size(&self) -> ScreenSize {
251        unsafe { ffi::AConfiguration_getScreenSize(self.ptr.as_ptr()).into() }
252    }
253
254    pub fn sdk_version(&self) -> i32 {
255        unsafe { ffi::AConfiguration_getSdkVersion(self.ptr.as_ptr()) }
256    }
257
258    pub fn smallest_screen_width_dp(&self) -> Option<i32> {
259        unsafe {
260            let width = ffi::AConfiguration_getSmallestScreenWidthDp(self.ptr.as_ptr());
261            if width == ffi::ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY as i32 {
262                None
263            } else {
264                Some(width)
265            }
266        }
267    }
268
269    pub fn touchscreen(&self) -> Touchscreen {
270        unsafe { ffi::AConfiguration_getTouchscreen(self.ptr.as_ptr()).into() }
271    }
272
273    pub fn ui_mode_night(&self) -> UiModeNight {
274        unsafe { ffi::AConfiguration_getUiModeNight(self.ptr.as_ptr()).into() }
275    }
276
277    pub fn ui_mode_type(&self) -> UiModeType {
278        unsafe { ffi::AConfiguration_getUiModeType(self.ptr.as_ptr()).into() }
279    }
280}
281
282/// A bitfield representing the differences between two [`Configuration`]s
283#[derive(Copy, Clone, Debug, PartialEq, Eq)]
284pub struct DiffResult(pub u32);
285
286impl DiffResult {
287    pub fn mcc(self) -> bool {
288        self.0 & ffi::ACONFIGURATION_MCC != 0
289    }
290    pub fn mnc(self) -> bool {
291        self.0 & ffi::ACONFIGURATION_MNC != 0
292    }
293    pub fn locale(self) -> bool {
294        self.0 & ffi::ACONFIGURATION_LOCALE != 0
295    }
296    pub fn touchscreen(self) -> bool {
297        self.0 & ffi::ACONFIGURATION_TOUCHSCREEN != 0
298    }
299    pub fn keyboard(self) -> bool {
300        self.0 & ffi::ACONFIGURATION_KEYBOARD != 0
301    }
302    pub fn keyboard_hidden(self) -> bool {
303        self.0 & ffi::ACONFIGURATION_KEYBOARD_HIDDEN != 0
304    }
305    pub fn navigation(self) -> bool {
306        self.0 & ffi::ACONFIGURATION_NAVIGATION != 0
307    }
308    pub fn orientation(self) -> bool {
309        self.0 & ffi::ACONFIGURATION_ORIENTATION != 0
310    }
311    pub fn density(self) -> bool {
312        self.0 & ffi::ACONFIGURATION_DENSITY != 0
313    }
314    pub fn screen_size(self) -> bool {
315        self.0 & ffi::ACONFIGURATION_SCREEN_SIZE != 0
316    }
317    pub fn version(self) -> bool {
318        self.0 & ffi::ACONFIGURATION_VERSION != 0
319    }
320    pub fn screen_layout(self) -> bool {
321        self.0 & ffi::ACONFIGURATION_SCREEN_LAYOUT != 0
322    }
323    pub fn ui_mode(self) -> bool {
324        self.0 & ffi::ACONFIGURATION_UI_MODE != 0
325    }
326    pub fn smallest_screen_size(self) -> bool {
327        self.0 & ffi::ACONFIGURATION_SMALLEST_SCREEN_SIZE != 0
328    }
329    pub fn layout_dir(self) -> bool {
330        self.0 & ffi::ACONFIGURATION_LAYOUTDIR != 0
331    }
332    pub fn screen_round(self) -> bool {
333        self.0 & ffi::ACONFIGURATION_SCREEN_ROUND != 0
334    }
335    pub fn color_mode(self) -> bool {
336        self.0 & ffi::ACONFIGURATION_COLOR_MODE != 0
337    }
338}
339
340#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
341#[repr(i32)]
342#[non_exhaustive]
343pub enum Orientation {
344    Any = ffi::ACONFIGURATION_ORIENTATION_ANY as i32,
345    Port = ffi::ACONFIGURATION_ORIENTATION_PORT as i32,
346    Land = ffi::ACONFIGURATION_ORIENTATION_LAND as i32,
347    Square = ffi::ACONFIGURATION_ORIENTATION_SQUARE as i32,
348
349    #[doc(hidden)]
350    #[num_enum(catch_all)]
351    __Unknown(i32),
352}
353
354#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
355#[repr(i32)]
356#[non_exhaustive]
357pub enum Touchscreen {
358    Any = ffi::ACONFIGURATION_TOUCHSCREEN_ANY as i32,
359    NoTouch = ffi::ACONFIGURATION_TOUCHSCREEN_NOTOUCH as i32,
360    Stylus = ffi::ACONFIGURATION_TOUCHSCREEN_STYLUS as i32,
361    Finger = ffi::ACONFIGURATION_TOUCHSCREEN_FINGER as i32,
362
363    #[doc(hidden)]
364    #[num_enum(catch_all)]
365    __Unknown(i32),
366}
367
368#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
369#[repr(i32)]
370#[non_exhaustive]
371pub enum Density {
372    Default = ffi::ACONFIGURATION_DENSITY_DEFAULT as i32,
373    Low = ffi::ACONFIGURATION_DENSITY_LOW as i32,
374    Medium = ffi::ACONFIGURATION_DENSITY_MEDIUM as i32,
375    TV = ffi::ACONFIGURATION_DENSITY_TV as i32,
376    High = ffi::ACONFIGURATION_DENSITY_HIGH as i32,
377    XHigh = ffi::ACONFIGURATION_DENSITY_XHIGH as i32,
378    XXHigh = ffi::ACONFIGURATION_DENSITY_XXHIGH as i32,
379    XXXHigh = ffi::ACONFIGURATION_DENSITY_XXXHIGH as i32,
380    Any = ffi::ACONFIGURATION_DENSITY_ANY as i32,
381    None = ffi::ACONFIGURATION_DENSITY_NONE as i32,
382
383    #[doc(hidden)]
384    #[num_enum(catch_all)]
385    __Unknown(i32),
386}
387
388impl Density {
389    /// The DPI associated with the density class.
390    /// See [the Android screen density
391    /// docs](https://developer.android.com/training/multiscreen/screendensities#TaskProvideAltBmp)
392    ///
393    /// There are some [`Density`] values that have no associated DPI; these values return [`None`].
394    pub fn dpi(self) -> Option<u32> {
395        match self {
396            Self::Default => Some(160), // Or should it be None?
397            Self::Low => Some(120),
398            Self::Medium => Some(160),
399            Self::High => Some(240),
400            Self::XHigh => Some(320),
401            Self::XXHigh => Some(480),
402            Self::XXXHigh => Some(640),
403            Self::TV => Some(213),
404            Self::Any => None,
405            Self::None => None,
406            // TODO
407            Self::__Unknown(v) => Some(v as u32),
408        }
409    }
410
411    /// The Hi-DPI factor associated with the density class.  This is the factor by which an
412    /// image/resource should be scaled to match its size across devices.  The baseline is a 160dpi
413    /// screen (i.e., Hi-DPI factor = DPI / 160).
414    /// See [the Android screen density
415    /// docs](https://developer.android.com/training/multiscreen/screendensities#TaskProvideAltBmp)
416    ///
417    /// There are some [`Density`] values that have no associated DPI; these values return [`None`].
418    pub fn approx_hidpi_factor(self) -> Option<f64> {
419        match self {
420            Self::Default => Some(1.), // Or should it be None?
421            Self::Low => Some(0.75),
422            Self::Medium => Some(1.),
423            Self::High => Some(1.5),
424            Self::XHigh => Some(2.),
425            Self::XXHigh => Some(3.),
426            Self::XXXHigh => Some(4.),
427            Self::TV => Some(4. / 3.),
428            Self::Any => None,
429            Self::None => None,
430            Self::__Unknown(_) => None,
431        }
432    }
433}
434
435#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
436#[repr(i32)]
437#[non_exhaustive]
438pub enum Keyboard {
439    Any = ffi::ACONFIGURATION_KEYBOARD_ANY as i32,
440    NoKeys = ffi::ACONFIGURATION_KEYBOARD_NOKEYS as i32,
441    Qwerty = ffi::ACONFIGURATION_KEYBOARD_QWERTY as i32,
442    TwelveKey = ffi::ACONFIGURATION_KEYBOARD_12KEY as i32,
443
444    #[doc(hidden)]
445    #[num_enum(catch_all)]
446    __Unknown(i32),
447}
448
449#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
450#[repr(i32)]
451#[non_exhaustive]
452pub enum Navigation {
453    Any = ffi::ACONFIGURATION_NAVIGATION_ANY as i32,
454    NoNav = ffi::ACONFIGURATION_NAVIGATION_NONAV as i32,
455    DPad = ffi::ACONFIGURATION_NAVIGATION_DPAD as i32,
456    Trackball = ffi::ACONFIGURATION_NAVIGATION_TRACKBALL as i32,
457    Wheel = ffi::ACONFIGURATION_NAVIGATION_WHEEL as i32,
458
459    #[doc(hidden)]
460    #[num_enum(catch_all)]
461    __Unknown(i32),
462}
463
464#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
465#[repr(i32)]
466#[non_exhaustive]
467pub enum KeysHidden {
468    Any = ffi::ACONFIGURATION_KEYSHIDDEN_ANY as i32,
469    No = ffi::ACONFIGURATION_KEYSHIDDEN_NO as i32,
470    Yes = ffi::ACONFIGURATION_KEYSHIDDEN_YES as i32,
471    Soft = ffi::ACONFIGURATION_KEYSHIDDEN_SOFT as i32,
472
473    #[doc(hidden)]
474    #[num_enum(catch_all)]
475    __Unknown(i32),
476}
477
478#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
479#[repr(i32)]
480#[non_exhaustive]
481pub enum NavHidden {
482    Any = ffi::ACONFIGURATION_NAVHIDDEN_ANY as i32,
483    No = ffi::ACONFIGURATION_NAVHIDDEN_NO as i32,
484    Yes = ffi::ACONFIGURATION_NAVHIDDEN_YES as i32,
485
486    #[doc(hidden)]
487    #[num_enum(catch_all)]
488    __Unknown(i32),
489}
490
491#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
492#[repr(i32)]
493#[non_exhaustive]
494pub enum ScreenSize {
495    Any = ffi::ACONFIGURATION_SCREENSIZE_ANY as i32,
496    Small = ffi::ACONFIGURATION_SCREENSIZE_SMALL as i32,
497    Normal = ffi::ACONFIGURATION_SCREENSIZE_NORMAL as i32,
498    Large = ffi::ACONFIGURATION_SCREENSIZE_LARGE as i32,
499    XLarge = ffi::ACONFIGURATION_SCREENSIZE_XLARGE as i32,
500
501    #[doc(hidden)]
502    #[num_enum(catch_all)]
503    __Unknown(i32),
504}
505
506#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
507#[repr(i32)]
508#[non_exhaustive]
509pub enum ScreenLong {
510    Any = ffi::ACONFIGURATION_SCREENLONG_ANY as i32,
511    No = ffi::ACONFIGURATION_SCREENLONG_NO as i32,
512    Yes = ffi::ACONFIGURATION_SCREENLONG_YES as i32,
513
514    #[doc(hidden)]
515    #[num_enum(catch_all)]
516    __Unknown(i32),
517}
518
519#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
520#[repr(i32)]
521#[non_exhaustive]
522pub enum ScreenRound {
523    Any = ffi::ACONFIGURATION_SCREENROUND_ANY as i32,
524    No = ffi::ACONFIGURATION_SCREENROUND_NO as i32,
525    Yes = ffi::ACONFIGURATION_SCREENROUND_YES as i32,
526
527    #[doc(hidden)]
528    #[num_enum(catch_all)]
529    __Unknown(i32),
530}
531
532#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
533#[repr(i32)]
534#[non_exhaustive]
535pub enum WideColorGamut {
536    Any = ffi::ACONFIGURATION_WIDE_COLOR_GAMUT_ANY as i32,
537    No = ffi::ACONFIGURATION_WIDE_COLOR_GAMUT_NO as i32,
538    Yes = ffi::ACONFIGURATION_WIDE_COLOR_GAMUT_YES as i32,
539
540    #[doc(hidden)]
541    #[num_enum(catch_all)]
542    __Unknown(i32),
543}
544
545#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
546#[repr(i32)]
547#[non_exhaustive]
548pub enum HDR {
549    Any = ffi::ACONFIGURATION_HDR_ANY as i32,
550    No = ffi::ACONFIGURATION_HDR_NO as i32,
551    Yes = ffi::ACONFIGURATION_HDR_YES as i32,
552
553    #[doc(hidden)]
554    #[num_enum(catch_all)]
555    __Unknown(i32),
556}
557
558#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
559#[repr(i32)]
560#[non_exhaustive]
561pub enum LayoutDir {
562    Any = ffi::ACONFIGURATION_LAYOUTDIR_ANY as i32,
563    Ltr = ffi::ACONFIGURATION_LAYOUTDIR_LTR as i32,
564    Rtl = ffi::ACONFIGURATION_LAYOUTDIR_RTL as i32,
565
566    #[doc(hidden)]
567    #[num_enum(catch_all)]
568    __Unknown(i32),
569}
570
571#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
572#[repr(i32)]
573#[non_exhaustive]
574pub enum UiModeType {
575    Any = ffi::ACONFIGURATION_UI_MODE_TYPE_ANY as i32,
576    Normal = ffi::ACONFIGURATION_UI_MODE_TYPE_NORMAL as i32,
577    Desk = ffi::ACONFIGURATION_UI_MODE_TYPE_DESK as i32,
578    Car = ffi::ACONFIGURATION_UI_MODE_TYPE_CAR as i32,
579    Television = ffi::ACONFIGURATION_UI_MODE_TYPE_TELEVISION as i32,
580    Applicance = ffi::ACONFIGURATION_UI_MODE_TYPE_APPLIANCE as i32,
581    Watch = ffi::ACONFIGURATION_UI_MODE_TYPE_WATCH as i32,
582    VrHeadset = ffi::ACONFIGURATION_UI_MODE_TYPE_VR_HEADSET as i32,
583
584    #[doc(hidden)]
585    #[num_enum(catch_all)]
586    __Unknown(i32),
587}
588
589#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
590#[repr(i32)]
591#[non_exhaustive]
592pub enum UiModeNight {
593    Any = ffi::ACONFIGURATION_UI_MODE_NIGHT_ANY as i32,
594    No = ffi::ACONFIGURATION_UI_MODE_NIGHT_NO as i32,
595    Yes = ffi::ACONFIGURATION_UI_MODE_NIGHT_YES as i32,
596
597    #[doc(hidden)]
598    #[num_enum(catch_all)]
599    __Unknown(i32),
600}