1 /*
2  * Copyright (C) 2022 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 package android.telephony.satellite;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import com.android.internal.telephony.flags.Flags;
27 
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Map;
31 import java.util.Objects;
32 import java.util.Set;
33 
34 /**
35  * SatelliteCapabilities is used to represent the capabilities of the satellite service
36  * received from satellite modem.
37  * @hide
38  */
39 @SystemApi
40 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
41 public final class SatelliteCapabilities implements Parcelable {
42     /**
43      * List of technologies supported by the satellite modem.
44      */
45     @NonNull @SatelliteManager.NTRadioTechnology private Set<Integer> mSupportedRadioTechnologies;
46 
47     /**
48      * Whether UE needs to point to a satellite to send and receive data.
49      */
50     private boolean mIsPointingRequired;
51 
52     /**
53      * The maximum number of bytes per datagram that can be sent over satellite.
54      */
55     private int mMaxBytesPerOutgoingDatagram;
56 
57     /**
58      * Antenna Position received from satellite modem which gives information about antenna
59      * direction to be used with satellite communication and suggested device hold positions.
60      * Map key: {@link SatelliteManager.DeviceHoldPosition} value: AntennaPosition
61      */
62     @NonNull
63     private Map<Integer, AntennaPosition> mAntennaPositionMap;
64 
65     /**
66      * @hide
67      */
SatelliteCapabilities(@ullable Set<Integer> supportedRadioTechnologies, boolean isPointingRequired, int maxBytesPerOutgoingDatagram, @NonNull Map<Integer, AntennaPosition> antennaPositionMap)68     public SatelliteCapabilities(@Nullable Set<Integer> supportedRadioTechnologies,
69             boolean isPointingRequired, int maxBytesPerOutgoingDatagram,
70             @NonNull Map<Integer, AntennaPosition> antennaPositionMap) {
71         mSupportedRadioTechnologies = supportedRadioTechnologies == null
72                 ? new HashSet<>() : supportedRadioTechnologies;
73         mIsPointingRequired = isPointingRequired;
74         mMaxBytesPerOutgoingDatagram = maxBytesPerOutgoingDatagram;
75         mAntennaPositionMap = antennaPositionMap;
76     }
77 
SatelliteCapabilities(Parcel in)78     private SatelliteCapabilities(Parcel in) {
79         readFromParcel(in);
80     }
81 
82     @Override
83     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
describeContents()84     public int describeContents() {
85         return 0;
86     }
87 
88     @Override
89     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
writeToParcel(@onNull Parcel out, int flags)90     public void writeToParcel(@NonNull Parcel out, int flags) {
91         if (mSupportedRadioTechnologies != null && !mSupportedRadioTechnologies.isEmpty()) {
92             out.writeInt(mSupportedRadioTechnologies.size());
93             for (int technology : mSupportedRadioTechnologies) {
94                 out.writeInt(technology);
95             }
96         } else {
97             out.writeInt(0);
98         }
99 
100         out.writeBoolean(mIsPointingRequired);
101         out.writeInt(mMaxBytesPerOutgoingDatagram);
102 
103         if (mAntennaPositionMap != null && !mAntennaPositionMap.isEmpty()) {
104             int size = mAntennaPositionMap.size();
105             out.writeInt(size);
106             for (Map.Entry<Integer, AntennaPosition> entry : mAntennaPositionMap.entrySet()) {
107                 out.writeInt(entry.getKey());
108                 out.writeParcelable(entry.getValue(), flags);
109             }
110         } else {
111             out.writeInt(0);
112         }
113     }
114 
115     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
116     @NonNull public static final Creator<SatelliteCapabilities> CREATOR = new Creator<>() {
117         @Override
118         public SatelliteCapabilities createFromParcel(Parcel in) {
119             return new SatelliteCapabilities(in);
120         }
121 
122         @Override
123         public SatelliteCapabilities[] newArray(int size) {
124             return new SatelliteCapabilities[size];
125         }
126     };
127 
128     @Override
toString()129     @NonNull public String toString() {
130         StringBuilder sb = new StringBuilder();
131 
132         sb.append("SupportedRadioTechnology:");
133         if (mSupportedRadioTechnologies != null && !mSupportedRadioTechnologies.isEmpty()) {
134             for (int technology : mSupportedRadioTechnologies) {
135                 sb.append(technology);
136                 sb.append(",");
137             }
138         } else {
139             sb.append("none,");
140         }
141 
142         sb.append("isPointingRequired:");
143         sb.append(mIsPointingRequired);
144         sb.append(",");
145 
146         sb.append("maxBytesPerOutgoingDatagram:");
147         sb.append(mMaxBytesPerOutgoingDatagram);
148         sb.append(",");
149 
150         sb.append("antennaPositionMap:");
151         sb.append(mAntennaPositionMap);
152         return sb.toString();
153     }
154 
155     @Override
equals(Object o)156     public boolean equals(Object o) {
157         if (this == o) return true;
158         if (o == null || getClass() != o.getClass()) return false;
159         SatelliteCapabilities that = (SatelliteCapabilities) o;
160         return Objects.equals(mSupportedRadioTechnologies, that.mSupportedRadioTechnologies)
161                 && mIsPointingRequired == that.mIsPointingRequired
162                 && mMaxBytesPerOutgoingDatagram == that.mMaxBytesPerOutgoingDatagram
163                 && Objects.equals(mAntennaPositionMap, that.mAntennaPositionMap);
164     }
165 
166     @Override
hashCode()167     public int hashCode() {
168         return Objects.hash(mSupportedRadioTechnologies, mIsPointingRequired,
169                 mMaxBytesPerOutgoingDatagram, mAntennaPositionMap);
170     }
171 
172     /**
173      * @return The list of technologies supported by the satellite modem.
174      */
175     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
176     @NonNull @SatelliteManager.NTRadioTechnology public Set<Integer>
getSupportedRadioTechnologies()177             getSupportedRadioTechnologies() {
178         return mSupportedRadioTechnologies;
179     }
180 
181     /**
182      * Get whether UE needs to point to a satellite to send and receive data.
183      *
184      * @return {@code true} if UE needs to point to a satellite to send and receive data and
185      *         {@code false} otherwise.
186      */
187     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
isPointingRequired()188     public boolean isPointingRequired() {
189         return mIsPointingRequired;
190     }
191 
192     /**
193      * The maximum number of bytes per datagram that can be sent over satellite.
194      *
195      * @return The maximum number of bytes per datagram that can be sent over satellite.
196      */
197     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
getMaxBytesPerOutgoingDatagram()198     public int getMaxBytesPerOutgoingDatagram() {
199         return mMaxBytesPerOutgoingDatagram;
200     }
201 
202     /**
203      * Antenna Position received from satellite modem which gives information about antenna
204      * direction to be used with satellite communication and suggested device hold positions.
205      * @return Map key: {@link SatelliteManager.DeviceHoldPosition} value: AntennaPosition
206      */
207     @NonNull
208     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
getAntennaPositionMap()209     public Map<Integer, AntennaPosition> getAntennaPositionMap() {
210         return mAntennaPositionMap;
211     }
212 
readFromParcel(Parcel in)213     private void readFromParcel(Parcel in) {
214         mSupportedRadioTechnologies = new HashSet<>();
215         int numSupportedRadioTechnologies = in.readInt();
216         if (numSupportedRadioTechnologies > 0) {
217             for (int i = 0; i < numSupportedRadioTechnologies; i++) {
218                 mSupportedRadioTechnologies.add(in.readInt());
219             }
220         }
221 
222         mIsPointingRequired = in.readBoolean();
223         mMaxBytesPerOutgoingDatagram = in.readInt();
224 
225         mAntennaPositionMap = new HashMap<>();
226         int antennaPositionMapSize = in.readInt();
227         for (int i = 0; i < antennaPositionMapSize; i++) {
228             int key = in.readInt();
229             AntennaPosition antennaPosition = in.readParcelable(
230                     AntennaPosition.class.getClassLoader(), AntennaPosition.class);
231             mAntennaPositionMap.put(key, antennaPosition);
232         }
233     }
234 }
235