1 /*
2  * Copyright (C) 2021 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 com.android.systemui.qs.tiles.dialog;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.graphics.drawable.Drawable;
22 import android.text.Html;
23 import android.text.TextUtils;
24 import android.view.LayoutInflater;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.widget.ImageView;
28 import android.widget.LinearLayout;
29 import android.widget.TextView;
30 
31 import androidx.annotation.NonNull;
32 import androidx.annotation.Nullable;
33 import androidx.recyclerview.widget.RecyclerView;
34 
35 import com.android.internal.annotations.VisibleForTesting;
36 import com.android.settingslib.Utils;
37 import com.android.settingslib.wifi.WifiUtils;
38 import com.android.systemui.R;
39 import com.android.wifitrackerlib.WifiEntry;
40 
41 import java.util.List;
42 import java.util.concurrent.atomic.AtomicReference;
43 
44 /**
45  * Adapter for showing Wi-Fi networks.
46  */
47 public class InternetAdapter extends RecyclerView.Adapter<InternetAdapter.InternetViewHolder> {
48 
49     private static final String TAG = "InternetAdapter";
50     private static final String ACTION_WIFI_DIALOG = "com.android.settings.WIFI_DIALOG";
51     private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key";
52     private static final String EXTRA_CONNECT_FOR_CALLER = "connect_for_caller";
53 
54     private final InternetDialogController mInternetDialogController;
55     private List<WifiEntry> mWifiEntries;
56     @VisibleForTesting
57     protected int mWifiEntriesCount;
58     @VisibleForTesting
59     protected int mMaxEntriesCount = InternetDialogController.MAX_WIFI_ENTRY_COUNT;
60 
61     protected View mHolderView;
62     protected Context mContext;
63 
InternetAdapter(InternetDialogController controller)64     public InternetAdapter(InternetDialogController controller) {
65         mInternetDialogController = controller;
66     }
67 
68     @Override
onCreateViewHolder(@onNull ViewGroup viewGroup, int viewType)69     public InternetViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
70             int viewType) {
71         mContext = viewGroup.getContext();
72         mHolderView = LayoutInflater.from(mContext).inflate(R.layout.internet_list_item,
73                 viewGroup, false);
74         return new InternetViewHolder(mHolderView, mInternetDialogController);
75     }
76 
77     @Override
onBindViewHolder(@onNull InternetViewHolder viewHolder, int position)78     public void onBindViewHolder(@NonNull InternetViewHolder viewHolder, int position) {
79         if (mWifiEntries == null || position >= mWifiEntriesCount) {
80             return;
81         }
82         viewHolder.onBind(mWifiEntries.get(position));
83     }
84 
85     /**
86      * Updates the Wi-Fi networks.
87      *
88      * @param wifiEntries the updated Wi-Fi entries.
89      * @param wifiEntriesCount the total number of Wi-Fi entries.
90      */
setWifiEntries(@ullable List<WifiEntry> wifiEntries, int wifiEntriesCount)91     public void setWifiEntries(@Nullable List<WifiEntry> wifiEntries, int wifiEntriesCount) {
92         mWifiEntries = wifiEntries;
93         mWifiEntriesCount =
94                 (wifiEntriesCount < mMaxEntriesCount) ? wifiEntriesCount : mMaxEntriesCount;
95     }
96 
97     /**
98      * Gets the total number of Wi-Fi networks.
99      *
100      * @return The total number of Wi-Fi entries.
101      */
102     @Override
getItemCount()103     public int getItemCount() {
104         return mWifiEntriesCount;
105     }
106 
107     /**
108      * Sets the maximum number of Wi-Fi networks.
109      */
setMaxEntriesCount(int count)110     public void setMaxEntriesCount(int count) {
111         if (count < 0 || mMaxEntriesCount == count) {
112             return;
113         }
114         mMaxEntriesCount = count;
115         if (mWifiEntriesCount > count) {
116             mWifiEntriesCount = count;
117             notifyDataSetChanged();
118         }
119     }
120 
121     /**
122      * ViewHolder for binding Wi-Fi view.
123      */
124     static class InternetViewHolder extends RecyclerView.ViewHolder {
125 
126         final LinearLayout mContainerLayout;
127         final LinearLayout mWifiListLayout;
128         final LinearLayout mWifiNetworkLayout;
129         final ImageView mWifiIcon;
130         final TextView mWifiTitleText;
131         final TextView mWifiSummaryText;
132         final ImageView mWifiEndIcon;
133         final Context mContext;
134         final InternetDialogController mInternetDialogController;
135 
136         @VisibleForTesting
137         protected WifiUtils.InternetIconInjector mWifiIconInjector;
138 
InternetViewHolder(View view, InternetDialogController internetDialogController)139         InternetViewHolder(View view, InternetDialogController internetDialogController) {
140             super(view);
141             mContext = view.getContext();
142             mInternetDialogController = internetDialogController;
143             mContainerLayout = view.requireViewById(R.id.internet_container);
144             mWifiListLayout = view.requireViewById(R.id.wifi_list);
145             mWifiNetworkLayout = view.requireViewById(R.id.wifi_network_layout);
146             mWifiIcon = view.requireViewById(R.id.wifi_icon);
147             mWifiTitleText = view.requireViewById(R.id.wifi_title);
148             mWifiSummaryText = view.requireViewById(R.id.wifi_summary);
149             mWifiEndIcon = view.requireViewById(R.id.wifi_end_icon);
150             mWifiIconInjector = mInternetDialogController.getWifiIconInjector();
151         }
152 
onBind(@onNull WifiEntry wifiEntry)153         void onBind(@NonNull WifiEntry wifiEntry) {
154             mWifiIcon.setImageDrawable(
155                     getWifiDrawable(wifiEntry.getLevel(), wifiEntry.shouldShowXLevelIcon()));
156             setWifiNetworkLayout(wifiEntry.getTitle(),
157                     Html.fromHtml(wifiEntry.getSummary(false), Html.FROM_HTML_MODE_LEGACY));
158 
159             final int connectedState = wifiEntry.getConnectedState();
160             final int security = wifiEntry.getSecurity();
161             updateEndIcon(connectedState, security);
162 
163             if (connectedState != WifiEntry.CONNECTED_STATE_DISCONNECTED) {
164                 mWifiListLayout.setOnClickListener(
165                         v -> mInternetDialogController.launchWifiNetworkDetailsSetting(
166                                 wifiEntry.getKey()));
167                 return;
168             }
169             mWifiListLayout.setOnClickListener(v -> {
170                 if (wifiEntry.shouldEditBeforeConnect()) {
171                     final Intent intent = new Intent(ACTION_WIFI_DIALOG);
172                     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
173                     intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
174                     intent.putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, wifiEntry.getKey());
175                     intent.putExtra(EXTRA_CONNECT_FOR_CALLER, false);
176                     mContext.startActivity(intent);
177                 }
178                 mInternetDialogController.connect(wifiEntry);
179             });
180         }
181 
setWifiNetworkLayout(CharSequence title, CharSequence summary)182         void setWifiNetworkLayout(CharSequence title, CharSequence summary) {
183             mWifiTitleText.setText(title);
184             if (TextUtils.isEmpty(summary)) {
185                 mWifiSummaryText.setVisibility(View.GONE);
186                 return;
187             }
188             mWifiSummaryText.setVisibility(View.VISIBLE);
189             mWifiSummaryText.setText(summary);
190         }
191 
getWifiDrawable(int level, boolean hasNoInternet)192         Drawable getWifiDrawable(int level, boolean hasNoInternet) {
193             // If the Wi-Fi level is equal to WIFI_LEVEL_UNREACHABLE(-1), then a null drawable
194             // will be returned.
195             if (level == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
196                 return null;
197             }
198             final Drawable drawable = mWifiIconInjector.getIcon(hasNoInternet, level);
199             if (drawable == null) {
200                 return null;
201             }
202             drawable.setTint(
203                     Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorTertiary));
204             final AtomicReference<Drawable> shared = new AtomicReference<>();
205             shared.set(drawable);
206             return shared.get();
207         }
208 
updateEndIcon(int connectedState, int security)209         void updateEndIcon(int connectedState, int security) {
210             Drawable drawable = null;
211             if (connectedState != WifiEntry.CONNECTED_STATE_DISCONNECTED) {
212                 drawable = mContext.getDrawable(R.drawable.ic_settings_24dp);
213             } else if (security != WifiEntry.SECURITY_NONE && security != WifiEntry.SECURITY_OWE) {
214                 drawable = mContext.getDrawable(R.drawable.ic_friction_lock_closed);
215             }
216             if (drawable == null) {
217                 mWifiEndIcon.setVisibility(View.GONE);
218                 return;
219             }
220             mWifiEndIcon.setVisibility(View.VISIBLE);
221             mWifiEndIcon.setImageDrawable(drawable);
222         }
223     }
224 }
225