1 /*
2  * Copyright (C) 2017 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.companion;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.provider.OneTimeUseBuilder;
24 
25 import com.android.internal.util.ArrayUtils;
26 import com.android.internal.util.CollectionUtils;
27 
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Objects;
31 
32 /**
33  * A request for the user to select a companion device to associate with.
34  *
35  * You can optionally set {@link Builder#addDeviceFilter filters} for which devices to show to the
36  * user to select from.
37  * The exact type and fields of the filter you can set depend on the
38  * medium type. See {@link Builder}'s static factory methods for specific protocols that are
39  * supported.
40  *
41  * You can also set {@link Builder#setSingleDevice single device} to request a popup with single
42  * device to be shown instead of a list to choose from
43  */
44 public final class AssociationRequest implements Parcelable {
45 
46     private final boolean mSingleDevice;
47     private final List<DeviceFilter<?>> mDeviceFilters;
48 
AssociationRequest( boolean singleDevice, @Nullable List<DeviceFilter<?>> deviceFilters)49     private AssociationRequest(
50             boolean singleDevice, @Nullable List<DeviceFilter<?>> deviceFilters) {
51         this.mSingleDevice = singleDevice;
52         this.mDeviceFilters = CollectionUtils.emptyIfNull(deviceFilters);
53     }
54 
AssociationRequest(Parcel in)55     private AssociationRequest(Parcel in) {
56         this(
57             in.readByte() != 0,
58             in.readParcelableList(new ArrayList<>(), AssociationRequest.class.getClassLoader()));
59     }
60 
61     /** @hide */
isSingleDevice()62     public boolean isSingleDevice() {
63         return mSingleDevice;
64     }
65 
66     /** @hide */
67     @NonNull
getDeviceFilters()68     public List<DeviceFilter<?>> getDeviceFilters() {
69         return mDeviceFilters;
70     }
71 
72     @Override
equals(Object o)73     public boolean equals(Object o) {
74         if (this == o) return true;
75         if (o == null || getClass() != o.getClass()) return false;
76         AssociationRequest that = (AssociationRequest) o;
77         return mSingleDevice == that.mSingleDevice &&
78                 Objects.equals(mDeviceFilters, that.mDeviceFilters);
79     }
80 
81     @Override
hashCode()82     public int hashCode() {
83         return Objects.hash(mSingleDevice, mDeviceFilters);
84     }
85 
86     @Override
toString()87     public String toString() {
88         return "AssociationRequest{" +
89                 "mSingleDevice=" + mSingleDevice +
90                 ", mDeviceFilters=" + mDeviceFilters +
91                 '}';
92     }
93 
94     @Override
writeToParcel(Parcel dest, int flags)95     public void writeToParcel(Parcel dest, int flags) {
96         dest.writeByte((byte) (mSingleDevice ? 1 : 0));
97         dest.writeParcelableList(mDeviceFilters, flags);
98     }
99 
100     @Override
describeContents()101     public int describeContents() {
102         return 0;
103     }
104 
105     public static final Creator<AssociationRequest> CREATOR = new Creator<AssociationRequest>() {
106         @Override
107         public AssociationRequest createFromParcel(Parcel in) {
108             return new AssociationRequest(in);
109         }
110 
111         @Override
112         public AssociationRequest[] newArray(int size) {
113             return new AssociationRequest[size];
114         }
115     };
116 
117     /**
118      * A builder for {@link AssociationRequest}
119      */
120     public static final class Builder extends OneTimeUseBuilder<AssociationRequest> {
121         private boolean mSingleDevice = false;
122         @Nullable private ArrayList<DeviceFilter<?>> mDeviceFilters = null;
123 
Builder()124         public Builder() {}
125 
126         /**
127          * @param singleDevice if true, scanning for a device will stop as soon as at least one
128          *                     fitting device is found
129          */
130         @NonNull
setSingleDevice(boolean singleDevice)131         public Builder setSingleDevice(boolean singleDevice) {
132             checkNotUsed();
133             this.mSingleDevice = singleDevice;
134             return this;
135         }
136 
137         /**
138          * @param deviceFilter if set, only devices matching the given filter will be shown to the
139          *                     user
140          */
141         @NonNull
addDeviceFilter(@ullable DeviceFilter<?> deviceFilter)142         public Builder addDeviceFilter(@Nullable DeviceFilter<?> deviceFilter) {
143             checkNotUsed();
144             if (deviceFilter != null) {
145                 mDeviceFilters = ArrayUtils.add(mDeviceFilters, deviceFilter);
146             }
147             return this;
148         }
149 
150         /** @inheritDoc */
151         @NonNull
152         @Override
build()153         public AssociationRequest build() {
154             markUsed();
155             return new AssociationRequest(mSingleDevice, mDeviceFilters);
156         }
157     }
158 }
159