• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 package com.android.settingslib.media;
17 
18 import android.content.Context;
19 import android.graphics.drawable.Drawable;
20 import android.text.TextUtils;
21 
22 import androidx.annotation.IntDef;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 
27 /**
28  * MediaDevice represents a media device(such like Bluetooth device, cast device and phone device).
29  */
30 public abstract class MediaDevice implements Comparable<MediaDevice> {
31     private static final String TAG = "MediaDevice";
32 
33     @Retention(RetentionPolicy.SOURCE)
34     @IntDef({MediaDeviceType.TYPE_CAST_DEVICE,
35             MediaDeviceType.TYPE_BLUETOOTH_DEVICE,
36             MediaDeviceType.TYPE_PHONE_DEVICE})
37     public @interface MediaDeviceType {
38         int TYPE_PHONE_DEVICE = 1;
39         int TYPE_CAST_DEVICE = 2;
40         int TYPE_BLUETOOTH_DEVICE = 3;
41     }
42 
43     private int mConnectedRecord;
44 
45     protected Context mContext;
46     protected int mType;
47 
MediaDevice(Context context, @MediaDeviceType int type)48     MediaDevice(Context context, @MediaDeviceType int type) {
49         mType = type;
50         mContext = context;
51     }
52 
initDeviceRecord()53     void initDeviceRecord() {
54         ConnectionRecordManager.getInstance().fetchLastSelectedDevice(mContext);
55         mConnectedRecord = ConnectionRecordManager.getInstance().fetchConnectionRecord(mContext,
56                 getId());
57     }
58 
59     /**
60      * Get name from MediaDevice.
61      *
62      * @return name of MediaDevice.
63      */
getName()64     public abstract String getName();
65 
66     /**
67      * Get summary from MediaDevice.
68      *
69      * @return summary of MediaDevice.
70      */
getSummary()71     public abstract String getSummary();
72 
73     /**
74      * Get icon of MediaDevice.
75      *
76      * @return drawable of icon.
77      */
getIcon()78     public abstract Drawable getIcon();
79 
80     /**
81      * Get unique ID that represent MediaDevice
82      * @return unique id of MediaDevice
83      */
getId()84     public abstract String getId();
85 
86     /**
87      * Transfer MediaDevice for media
88      *
89      * @return result of transfer media
90      */
connect()91     public abstract boolean connect();
92 
setConnectedRecord()93     void setConnectedRecord() {
94         mConnectedRecord++;
95         ConnectionRecordManager.getInstance().setConnectionRecord(mContext, getId(),
96                 mConnectedRecord);
97     }
98 
99     /**
100      * Stop transfer MediaDevice
101      */
disconnect()102     public abstract void disconnect();
103 
104     /**
105      * According the MediaDevice type to check whether we are connected to this MediaDevice.
106      *
107      * @return Whether it is connected.
108      */
isConnected()109     public abstract boolean isConnected();
110 
111     /**
112      * Rules:
113      * 1. If there is one of the connected devices identified as a carkit, this carkit will
114      * be always on the top of the device list. Rule 2 and Rule 3 can’t overrule this rule.
115      * 2. For devices without any usage data yet
116      * WiFi device group sorted by alphabetical order + BT device group sorted by alphabetical
117      * order + phone speaker
118      * 3. For devices with usage record.
119      * The most recent used one + device group with usage info sorted by how many times the
120      * device has been used.
121      * 4. Phone device always in the top and the connected Bluetooth devices, cast devices and
122      * phone device will be always above on the disconnect Bluetooth devices.
123      *
124      * So the device list will look like 5 slots ranked as below.
125      * Rule 4 + Rule 1 + the most recently used device + Rule 3 + Rule 2
126      * Any slot could be empty. And available device will belong to one of the slots.
127      *
128      * @return a negative integer, zero, or a positive integer
129      * as this object is less than, equal to, or greater than the specified object.
130      */
131     @Override
compareTo(MediaDevice another)132     public int compareTo(MediaDevice another) {
133         // Check Bluetooth device is have same connection state
134         if (isConnected() ^ another.isConnected()) {
135             if (isConnected()) {
136                 return -1;
137             } else {
138                 return 1;
139             }
140         }
141 
142         // Phone device always in the top.
143         if (mType == MediaDeviceType.TYPE_PHONE_DEVICE) {
144             return -1;
145         } else if (another.mType == MediaDeviceType.TYPE_PHONE_DEVICE) {
146             return 1;
147         }
148         // Check carkit
149         if (isCarKitDevice()) {
150             return -1;
151         } else if (another.isCarKitDevice()) {
152             return 1;
153         }
154         // Set last used device at the first item
155         String lastSelectedDevice = ConnectionRecordManager.getInstance().getLastSelectedDevice();
156         if (TextUtils.equals(lastSelectedDevice, getId())) {
157             return -1;
158         } else if (TextUtils.equals(lastSelectedDevice, another.getId())) {
159             return 1;
160         }
161         // Sort by how many times the device has been used if there is usage record
162         if ((mConnectedRecord != another.mConnectedRecord)
163                 && (another.mConnectedRecord > 0 || mConnectedRecord > 0)) {
164             return (another.mConnectedRecord - mConnectedRecord);
165         }
166         // Both devices have never been used
167         // To devices with the same type, sort by alphabetical order
168         if (mType == another.mType) {
169             final String s1 = getName();
170             final String s2 = another.getName();
171             return s1.compareToIgnoreCase(s2);
172         }
173         // Both devices have never been used, the priority is Phone > Cast > Bluetooth
174         return mType - another.mType;
175     }
176 
177     /**
178      * Check if it is CarKit device
179      * @return true if it is CarKit device
180      */
isCarKitDevice()181     protected boolean isCarKitDevice() {
182         return false;
183     }
184 
185     @Override
equals(Object obj)186     public boolean equals(Object obj) {
187         if (!(obj instanceof MediaDevice)) {
188             return false;
189         }
190         final MediaDevice otherDevice = (MediaDevice) obj;
191         return otherDevice.getId().equals(getId());
192     }
193 }
194