• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 use super::{
18     Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize, SerializeArray,
19     SerializeOption,
20 };
21 use crate::binder::AsNative;
22 use crate::error::{status_result, Result, StatusCode};
23 use crate::sys;
24 
25 use std::fs::File;
26 use std::os::unix::io::{AsRawFd, FromRawFd};
27 
28 /// Rust version of the Java class android.os.ParcelFileDescriptor
29 #[derive(Debug)]
30 pub struct ParcelFileDescriptor(File);
31 
32 impl ParcelFileDescriptor {
33     /// Create a new `ParcelFileDescriptor`
new(file: File) -> Self34     pub fn new(file: File) -> Self {
35         Self(file)
36     }
37 }
38 
39 impl AsRef<File> for ParcelFileDescriptor {
as_ref(&self) -> &File40     fn as_ref(&self) -> &File {
41         &self.0
42     }
43 }
44 
45 impl From<ParcelFileDescriptor> for File {
from(file: ParcelFileDescriptor) -> File46     fn from(file: ParcelFileDescriptor) -> File {
47         file.0
48     }
49 }
50 
51 impl Serialize for ParcelFileDescriptor {
serialize(&self, parcel: &mut Parcel) -> Result<()>52     fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
53         let fd = self.0.as_raw_fd();
54         let status = unsafe {
55             // Safety: `Parcel` always contains a valid pointer to an
56             // `AParcel`. Likewise, `ParcelFileDescriptor` always contains a
57             // valid file, so we can borrow a valid file
58             // descriptor. `AParcel_writeParcelFileDescriptor` does NOT take
59             // ownership of the fd, so we need not duplicate it first.
60             sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), fd)
61         };
62         status_result(status)
63     }
64 }
65 
66 impl SerializeArray for ParcelFileDescriptor {}
67 
68 impl SerializeOption for ParcelFileDescriptor {
serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()>69     fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
70         if let Some(f) = this {
71             f.serialize(parcel)
72         } else {
73             let status = unsafe {
74                 // Safety: `Parcel` always contains a valid pointer to an
75                 // `AParcel`. `AParcel_writeParcelFileDescriptor` accepts the
76                 // value `-1` as the file descriptor to signify serializing a
77                 // null file descriptor.
78                 sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), -1i32)
79             };
80             status_result(status)
81         }
82     }
83 }
84 
85 impl SerializeArray for Option<ParcelFileDescriptor> {}
86 
87 impl DeserializeOption for ParcelFileDescriptor {
deserialize_option(parcel: &Parcel) -> Result<Option<Self>>88     fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
89         let mut fd = -1i32;
90         unsafe {
91             // Safety: `Parcel` always contains a valid pointer to an
92             // `AParcel`. We pass a valid mutable pointer to an i32, which
93             // `AParcel_readParcelFileDescriptor` assigns the valid file
94             // descriptor into, or `-1` if deserializing a null file
95             // descriptor. The read function passes ownership of the file
96             // descriptor to its caller if it was non-null, so we must take
97             // ownership of the file and ensure that it is eventually closed.
98             status_result(sys::AParcel_readParcelFileDescriptor(
99                 parcel.as_native(),
100                 &mut fd,
101             ))?;
102         }
103         if fd < 0 {
104             Ok(None)
105         } else {
106             let file = unsafe {
107                 // Safety: At this point, we know that the file descriptor was
108                 // not -1, so must be a valid, owned file descriptor which we
109                 // can safely turn into a `File`.
110                 File::from_raw_fd(fd)
111             };
112             Ok(Some(ParcelFileDescriptor::new(file)))
113         }
114     }
115 }
116 
117 impl DeserializeArray for Option<ParcelFileDescriptor> {}
118 
119 impl Deserialize for ParcelFileDescriptor {
deserialize(parcel: &Parcel) -> Result<Self>120     fn deserialize(parcel: &Parcel) -> Result<Self> {
121         Deserialize::deserialize(parcel)
122             .transpose()
123             .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
124     }
125 }
126 
127 impl DeserializeArray for ParcelFileDescriptor {}
128