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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
use super::action::Action;
use super::attribute_list::{AttributeList, Semicolon};
use super::data::Data;
use serde::{Deserialize, Serialize};

/// Specifies the set of other apps that an app intends to interact with.
///
/// These other apps can be specified by package name, by intent signature, or by
/// provider authority, as described in later sections on this page.
///
/// ## Node
/// Some packages are [`visible automatically`]. Your app can always see these packages in
/// its queries for other installed apps. To view other packages, declare your app's need
/// for increased package visibility using the <queries> element.
///
/// Learn more about how to use the <queries> element in the guide on [`package visibility
/// filtering`].
///
/// ## XML Syntax
/// ```xml
/// <queries>
///      <package android:name="string" />
///      <intent>
///         ...
///      </intent>
///      <provider android:authorities="list" />
///  </queries>
/// ```
///
/// ## Contained in
/// * [`<manifest>`]
///
/// ## Introduced in
/// API Level 30
///
/// [`<manifest>`]: crate::AndroidManifest
/// [`package visibility filtering`]: https://developer.android.com/training/package-visibility
/// [`visible automatically`]: https://developer.android.com/training/package-visibility/automatic
#[derive(Debug, Deserialize, Serialize, YaSerialize, YaDeserialize, PartialEq, Eq, Clone)]
pub struct Queries {
    /// Specifies a single app that your app intends to access. This other app might
    /// integrate with your app, or your app might use services that the other app
    /// provides.
    pub package: Option<Package>,
    /// Specifies an [`intent filter signature`]. Your app can discover other apps that
    /// have matching [`<intent-filter>`] elements.
    pub intent: Option<Intent>,
    /// Specifies one or more [`content provider authorities`]. Your app can discover
    /// other apps whose content providers use the specified authorities.
    ///
    /// ## Note
    /// There are some restrictions on the options that you can include in this
    /// `<provider>` element, compared to a typical [`<provider>`] manifest element.
    /// Usually, you only specify the `android:authorities` attribute.
    ///
    /// [`<provider>`]: crate::Provider
    /// [`content provider authorities`]: https://developer.android.com/guide/topics/providers/content-provider-basics#ContentURIs
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub provider: Vec<QueriesProvider>,
}

/// Specifies a single app that your app intends to access. This other app might integrate
/// with your app, or your app might use services that the other app provides.
#[derive(Debug, Deserialize, Serialize, YaSerialize, YaDeserialize, PartialEq, Eq, Clone)]
pub struct Package {
    /// `Required`. Specifies the package name of the other app.
    #[yaserde(attribute, prefix = "android")]
    pub name: String,
}

/// Specifies an [`intent filter signature`]. Your app can discover other apps that have
/// matching [`<intent-filter>`] elements.
///
/// ## Node
/// There are some restrictions on the options that you can include in this <intent>
/// element, compared to a typical intent filter signature. Learn more about these
/// restrictions in the "intent filter signature" section of the guide to [`declaring
/// package visibility needs`].
///
/// [`<intent-filter>`]: crate::IntentFilter
/// [`intent filter signature`]: https://developer.android.com/training/basics/intents/filters
/// [`declaring package visibility needs`]: https://developer.android.com/training/package-visibility/declaring#intent-filter-signature
#[derive(
    Debug, Deserialize, Serialize, YaSerialize, YaDeserialize, PartialEq, Eq, Default, Clone,
)]
pub struct Intent {
    pub action: Action,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub data: Vec<Data>,
}

/// Declares a content provider component used in [`<queries>`].
///
/// A content provider is a subclass of [`ContentProvider`] that supplies structured
/// access to data managed by the application. All content providers in your application
/// must be defined in a `<provider>` element in the manifest file; otherwise, the system
/// is unaware of them and doesn't run them.
///
/// You only declare content providers that are part of your application. Content
/// providers in other applications that you use in your application should not be
/// declared.
///
/// The Android system stores references to content providers according to an authority
/// string, part of the provider's content URI. For example, suppose you want to access a
/// content provider that stores information about health care professionals.
/// To do this, you call the method [`ContentResolver.query()`],
/// which among other arguments takes a URI that identifies the provider:
///
/// ## XML Example
/// ```xml
/// content://com.example.project.healthcareprovider/nurses/rn
/// ```
///
/// The `content:` `scheme` identifies the URI as a content URI pointing to an Android
/// content provider. The authority `com.example.project.healthcareprovider` identifies
/// the provider itself; the Android system looks up the authority in its list of known
/// providers and their authorities. The substring `nurses/rn` is a `path`, which the
/// content provider can use to identify subsets of the provider data.
///
/// In cases where you need to query a content provider but don't know the specific
/// package names, you can declare that provider authority in a <provider> element,
/// as shown in the following snippet:
///
/// ## XML Example
/// ```xml
/// <manifest package="com.example.suite.enterprise">
///     <queries>
///         <provider android:authorities="com.example.settings.files" />
///     </queries>
///    ...
/// </manifest>
/// ```
///
/// ## Node
/// If your <queries> element includes a <provider> element, you might see an editor
/// warning in Android Studio related to the <provider> element. As long as you're using
/// the latest "dot" release of the Android Gradle plugin, your build is unaffected, so
/// you can disregard the warning. Learn more in the blog post about [`Preparing your
/// Gradle build for package visibility in Android 11`].
///
/// ## Contained in
/// * [`<queries>`]
///
/// ## Introduced in
/// API Level 30
///
/// [`ContentProvider`]: https://developer.android.com/reference/android/content/ContentProvider
/// [`ContentResolver.query()`]: https://developer.android.com/reference/android/content/ContentResolver#query(android.net.Uri,%20java.lang.String[],%20android.os.Bundle,%20android.os.CancellationSignal)
/// [`Content Providers`]: https://developer.android.com/guide/topics/providers/content-providers
/// [`<queries>`]: crate::Queries
/// [`Preparing your Gradle build for package visibility in Android 11`]: https://android-developers.googleblog.com/2020/07/preparing-your-build-for-package-visibility-in-android-11.html
#[derive(
    Debug, Deserialize, Serialize, YaSerialize, YaDeserialize, PartialEq, Eq, Default, Clone,
)]
#[serde(rename = "provider")]
pub struct QueriesProvider {
    /// A list of one or more URI authorities that identify data offered by the content
    /// provider. Multiple authorities are listed by separating their names with a
    /// semicolon. To avoid conflicts, authority names should use a Java-style naming
    /// convention (such as com.example.provider.cartoonprovider). Typically, it's the
    /// name of the [`ContentProvider`] subclass that implements the provider
    ///
    /// There is no default. At least one authority must be specified.
    ///
    /// [`ContentProvider`]: https://developer.android.com/reference/android/content/ContentProvider
    #[yaserde(
        attribute,
        prefix = "android",
        skip_serializing_if = "check_authorities"
    )]
    #[serde(skip_serializing_if = "AttributeList::is_empty")]
    pub authorities: AttributeList<Semicolon, String>,
    /// The name of the class that implements the content provider, a subclass of
    /// [`ContentProvider`]. This should be a fully qualified class name (such
    /// as, `"com.example.project.TransportationProvider"`). However, as a
    /// shorthand, if the first character of the name is a period, it is
    /// appended to the package name specified in the [`<manifest>`] element.
    ///
    /// There is no default. The name must be specified.
    ///
    /// [`ContentProvider`]: https://developer.android.com/reference/android/content/ContentProvider
    /// [`<manifest>`]: crate::AndroidManifest
    #[yaserde(attribute, prefix = "android")]
    pub name: String,
}

impl QueriesProvider {
    pub fn check_authorities(&self, value: &AttributeList<Semicolon, String>) -> bool {
        value.is_empty()
    }
}