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