1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use core::fmt;
use std::sync::{Arc, RwLock};

use ndk::configuration::{
    Configuration, Keyboard, KeysHidden, LayoutDir, NavHidden, Navigation, Orientation, ScreenLong,
    ScreenSize, Touchscreen, UiModeNight, UiModeType,
};

/// A (cheaply clonable) reference to this application's [`ndk::configuration::Configuration`]
///
/// This provides a thread-safe way to access the latest configuration state for
/// an application without deeply copying the large [`ndk::configuration::Configuration`] struct.
///
/// If the application is notified of configuration changes then those changes
/// will become visible via pre-existing configuration references.
#[derive(Clone)]
pub struct ConfigurationRef {
    config: Arc<RwLock<Configuration>>,
}
impl PartialEq for ConfigurationRef {
    fn eq(&self, other: &Self) -> bool {
        if Arc::ptr_eq(&self.config, &other.config) {
            true
        } else {
            let other_guard = other.config.read().unwrap();
            self.config.read().unwrap().eq(&*other_guard)
        }
    }
}
impl Eq for ConfigurationRef {}
unsafe impl Send for ConfigurationRef {}
unsafe impl Sync for ConfigurationRef {}

impl fmt::Debug for ConfigurationRef {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.config.read().unwrap().fmt(f)
    }
}

impl ConfigurationRef {
    pub(crate) fn new(config: Configuration) -> Self {
        Self {
            config: Arc::new(RwLock::new(config)),
        }
    }

    pub(crate) fn replace(&self, src: Configuration) {
        self.config.write().unwrap().copy(&src);
    }

    // Returns a deep copy of the full application configuration
    pub fn copy(&self) -> Configuration {
        let mut dest = Configuration::new();
        dest.copy(&self.config.read().unwrap());
        dest
    }
    /// Returns the country code, as a [`String`] of two characters, if set
    pub fn country(&self) -> Option<String> {
        self.config.read().unwrap().country()
    }

    /// Returns the screen density in dpi.
    ///
    /// On some devices it can return values outside of the density enum.
    pub fn density(&self) -> Option<u32> {
        self.config.read().unwrap().density()
    }

    /// Returns the keyboard type.
    pub fn keyboard(&self) -> Keyboard {
        self.config.read().unwrap().keyboard()
    }

    /// Returns keyboard visibility/availability.
    pub fn keys_hidden(&self) -> KeysHidden {
        self.config.read().unwrap().keys_hidden()
    }

    /// Returns the language, as a `String` of two characters, if a language is set
    pub fn language(&self) -> Option<String> {
        self.config.read().unwrap().language()
    }

    /// Returns the layout direction
    pub fn layout_direction(&self) -> LayoutDir {
        self.config.read().unwrap().layout_direction()
    }

    /// Returns the mobile country code.
    pub fn mcc(&self) -> i32 {
        self.config.read().unwrap().mcc()
    }

    /// Returns the mobile network code, if one is defined
    pub fn mnc(&self) -> Option<i32> {
        self.config.read().unwrap().mnc()
    }

    pub fn nav_hidden(&self) -> NavHidden {
        self.config.read().unwrap().nav_hidden()
    }

    pub fn navigation(&self) -> Navigation {
        self.config.read().unwrap().navigation()
    }

    pub fn orientation(&self) -> Orientation {
        self.config.read().unwrap().orientation()
    }

    pub fn screen_height_dp(&self) -> Option<i32> {
        self.config.read().unwrap().screen_height_dp()
    }

    pub fn screen_width_dp(&self) -> Option<i32> {
        self.config.read().unwrap().screen_width_dp()
    }

    pub fn screen_long(&self) -> ScreenLong {
        self.config.read().unwrap().screen_long()
    }

    #[cfg(feature = "api-level-30")]
    pub fn screen_round(&self) -> ScreenRound {
        self.config.read().unwrap().screen_round()
    }

    pub fn screen_size(&self) -> ScreenSize {
        self.config.read().unwrap().screen_size()
    }

    pub fn sdk_version(&self) -> i32 {
        self.config.read().unwrap().sdk_version()
    }

    pub fn smallest_screen_width_dp(&self) -> Option<i32> {
        self.config.read().unwrap().smallest_screen_width_dp()
    }

    pub fn touchscreen(&self) -> Touchscreen {
        self.config.read().unwrap().touchscreen()
    }

    pub fn ui_mode_night(&self) -> UiModeNight {
        self.config.read().unwrap().ui_mode_night()
    }

    pub fn ui_mode_type(&self) -> UiModeType {
        self.config.read().unwrap().ui_mode_type()
    }
}