1 /*
2  * Copyright 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 package android.uwb;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import java.util.Objects;
26 
27 /**
28  * Represents an angle of arrival measurement between two devices using Ultra Wideband
29  *
30  * @hide
31  */
32 @SystemApi
33 public final class AngleOfArrivalMeasurement implements Parcelable {
34     private final AngleMeasurement mAzimuthAngleMeasurement;
35     private final AngleMeasurement mAltitudeAngleMeasurement;
36 
AngleOfArrivalMeasurement(@onNull AngleMeasurement azimuthAngleMeasurement, @Nullable AngleMeasurement altitudeAngleMeasurement)37     private AngleOfArrivalMeasurement(@NonNull AngleMeasurement azimuthAngleMeasurement,
38             @Nullable AngleMeasurement altitudeAngleMeasurement) {
39         mAzimuthAngleMeasurement = azimuthAngleMeasurement;
40         mAltitudeAngleMeasurement = altitudeAngleMeasurement;
41     }
42 
43     /**
44      * Azimuth angle measurement
45      * <p>Azimuth {@link AngleMeasurement} of remote device in horizontal coordinate system, this is
46      * the angle clockwise from the meridian when viewing above the north pole.
47      *
48      * <p>See: https://en.wikipedia.org/wiki/Horizontal_coordinate_system
49      *
50      * <p>On an Android device, azimuth north is defined as the angle perpendicular away from the
51      * back of the device when holding it in portrait mode upright.
52      *
53      * <p>Azimuth angle must be supported when Angle of Arrival is supported
54      *
55      * @return the azimuth {@link AngleMeasurement}
56      */
57     @NonNull
getAzimuth()58     public AngleMeasurement getAzimuth() {
59         return mAzimuthAngleMeasurement;
60     }
61 
62     /**
63      * Altitude angle measurement
64      * <p>Altitude {@link AngleMeasurement} of remote device in horizontal coordinate system, this
65      * is the angle above the equator when the north pole is up.
66      *
67      * <p>See: https://en.wikipedia.org/wiki/Horizontal_coordinate_system
68      *
69      * <p>On an Android device, altitude is defined as the angle vertical from ground when holding
70      * the device in portrait mode upright.
71      *
72      * @return altitude {@link AngleMeasurement} or null when this is not available
73      */
74     @Nullable
getAltitude()75     public AngleMeasurement getAltitude() {
76         return mAltitudeAngleMeasurement;
77     }
78 
79     /**
80      * @hide
81      */
82     @Override
equals(Object obj)83     public boolean equals(Object obj) {
84         if (this == obj) {
85             return true;
86         }
87 
88         if (obj instanceof AngleOfArrivalMeasurement) {
89             AngleOfArrivalMeasurement other = (AngleOfArrivalMeasurement) obj;
90             return Objects.equals(mAzimuthAngleMeasurement, other.getAzimuth())
91                     && Objects.equals(mAltitudeAngleMeasurement, other.getAltitude());
92         }
93         return false;
94     }
95 
96     /**
97      * @hide
98      */
99     @Override
hashCode()100     public int hashCode() {
101         return Objects.hash(mAzimuthAngleMeasurement, mAltitudeAngleMeasurement);
102     }
103 
104     @Override
describeContents()105     public int describeContents() {
106         return 0;
107     }
108 
109     @Override
writeToParcel(@onNull Parcel dest, int flags)110     public void writeToParcel(@NonNull Parcel dest, int flags) {
111         dest.writeParcelable(mAzimuthAngleMeasurement, flags);
112         dest.writeParcelable(mAltitudeAngleMeasurement, flags);
113     }
114 
115     public static final @android.annotation.NonNull Creator<AngleOfArrivalMeasurement> CREATOR =
116             new Creator<AngleOfArrivalMeasurement>() {
117                 @Override
118                 public AngleOfArrivalMeasurement createFromParcel(Parcel in) {
119                     Builder builder =
120                             new Builder(in.readParcelable(AngleMeasurement.class.getClassLoader()));
121 
122                     builder.setAltitude(in.readParcelable(AngleMeasurement.class.getClassLoader()));
123 
124                     return builder.build();
125                 }
126 
127                 @Override
128                 public AngleOfArrivalMeasurement[] newArray(int size) {
129                     return new AngleOfArrivalMeasurement[size];
130                 }
131             };
132 
133     /** @hide **/
134     @Override
toString()135     public String toString() {
136         return "AngleOfArrivalMeasurement["
137                 + "azimuth: " + mAzimuthAngleMeasurement
138                 + ", altitude: " + mAltitudeAngleMeasurement
139                 + "]";
140     }
141 
142     /**
143      * Builder class for {@link AngleOfArrivalMeasurement}.
144      */
145     public static final class Builder {
146         private final AngleMeasurement mAzimuthAngleMeasurement;
147         private AngleMeasurement mAltitudeAngleMeasurement = null;
148 
149         /**
150          * Constructs an {@link AngleOfArrivalMeasurement} object
151          *
152          * @param azimuthAngle the azimuth angle of the measurement
153          */
Builder(@onNull AngleMeasurement azimuthAngle)154         public Builder(@NonNull AngleMeasurement azimuthAngle) {
155             mAzimuthAngleMeasurement = azimuthAngle;
156         }
157 
158         /**
159          * Set the altitude angle
160          *
161          * @param altitudeAngle altitude angle
162          */
163         @NonNull
setAltitude(@onNull AngleMeasurement altitudeAngle)164         public Builder setAltitude(@NonNull AngleMeasurement altitudeAngle) {
165             mAltitudeAngleMeasurement = altitudeAngle;
166             return this;
167         }
168 
169         /**
170          * Build the {@link AngleOfArrivalMeasurement} object
171          */
172         @NonNull
build()173         public AngleOfArrivalMeasurement build() {
174             return new AngleOfArrivalMeasurement(mAzimuthAngleMeasurement,
175                     mAltitudeAngleMeasurement);
176         }
177     }
178 }
179