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