1 /*
2  * Copyright (C) 2016 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.support.car.lenspicker;
17 
18 import android.content.ComponentName;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.pm.ActivityInfo;
22 import android.content.pm.ApplicationInfo;
23 import android.content.pm.PackageManager;
24 import android.content.pm.ResolveInfo;
25 import android.graphics.drawable.Drawable;
26 import android.os.AsyncTask;
27 import android.util.Log;
28 import android.view.LayoutInflater;
29 import android.view.ViewGroup;
30 
31 import androidx.car.widget.PagedListView;
32 import androidx.recyclerview.widget.RecyclerView;
33 
34 import java.util.ArrayList;
35 import java.util.List;
36 
37 /**
38  * An adapter that binds each of the rows within the {@link LensResolverActivity}.
39  */
40 public class ResolverAdapter extends RecyclerView.Adapter<ResolverListRow>
41         implements PagedListView.ItemCap {
42     private static final String TAG = "ResolverAdapter";
43 
44     private final Context mContext;
45     private final List<ResolveInfo> mResolveInfos;
46     private final List<LensPickerItem> mItems = new ArrayList<>();
47     private ResolverListRow.ResolverSelectionHandler mHandler;
48 
ResolverAdapter(Context context, List<ResolveInfo> resolveInfos)49     public ResolverAdapter(Context context, List<ResolveInfo> resolveInfos) {
50         mContext = context;
51         mResolveInfos = resolveInfos;
52 
53         new LoadTask().execute(null, null, null);
54     }
55 
setSelectionHandler(ResolverListRow.ResolverSelectionHandler handler)56     public void setSelectionHandler(ResolverListRow.ResolverSelectionHandler handler) {
57         mHandler = handler;
58     }
59 
60     @Override
onCreateViewHolder(ViewGroup parent, int viewType)61     public ResolverListRow onCreateViewHolder(ViewGroup parent, int viewType) {
62         LayoutInflater inflater = LayoutInflater.from(parent.getContext());
63         return new ResolverListRow(
64                 inflater.inflate(R.layout.car_list_item_1_card, parent, false));
65     }
66 
67     @Override
onBindViewHolder(ResolverListRow holder, int position)68     public void onBindViewHolder(ResolverListRow holder, int position) {
69         holder.bind(mContext, mResolveInfos.get(position), mItems.get(position), mHandler);
70     }
71 
72     @Override
getItemCount()73     public int getItemCount() {
74         return mItems == null ? 0 : mItems.size();
75     }
76 
77     @Override
setMaxItems(int maxItems)78     public void setMaxItems(int maxItems) {
79         // No-op, but method override is needed for PagedListView.
80     }
81 
82     /**
83      * An {@link AsyncTask} that will construct the corresponding launch Intents for each of the
84      * activities represented by {@link #mResolveInfos}. Upon completion, that information is
85      * packaged into a {@link LensPickerItem} and stored within {@link #mItems}.
86      */
87     private class LoadTask extends AsyncTask<Void, Void, List<LensPickerItem>> {
88         @Override
doInBackground(Void... unused)89         protected List<LensPickerItem> doInBackground(Void... unused) {
90             List<LensPickerItem> items = new ArrayList<>();
91 
92             PackageManager packageManager = mContext.getPackageManager();
93 
94             for (ResolveInfo info : mResolveInfos) {
95                 String packageName = LensPickerUtils.getPackageName(info);
96 
97                 try {
98                     ApplicationInfo aInfo = packageManager.getApplicationInfo(packageName, 0);
99                     String displayName = "";
100                     if (LensPickerUtils.isMediaService(info)) {
101                         // For media services we take the service tag instead of the package name.
102                         // This is done to avoid Bluetooth showing Bluetooth Share as the package
103                         // name.
104                         displayName = info.loadLabel(packageManager).toString();
105                         if (Log.isLoggable(TAG, Log.DEBUG)) {
106                             Log.d(TAG, "Media service label set to: " + displayName);
107                         }
108                     }
109 
110                     // If we found an empty label for above case or if we did not hit the above if
111                     // block then simply set this string to package name.
112                     if (displayName.equals("")) {
113                         displayName = getComponentLabel(packageManager, aInfo);
114                     }
115 
116                     Intent intent;
117                     if (LensPickerUtils.isMediaService(info)) {
118                         intent = LensPickerUtils.getMediaLaunchIntent(packageManager, packageName,
119                                 info.serviceInfo.name);
120                     } else {
121                         intent = new Intent();
122                         ActivityInfo activity = info.activityInfo;
123                         intent.setComponent(
124                                 new ComponentName(activity.applicationInfo.packageName,
125                                         activity.name));
126                     }
127 
128                     items.add(new LensPickerItem(displayName,
129                             getComponentIcon(packageManager, aInfo), intent,
130                             null /* facetId */));
131                 } catch (PackageManager.NameNotFoundException e) {
132                     // skip this package.
133                 }
134             }
135 
136             return items;
137         }
138 
139         @Override
onPostExecute(List<LensPickerItem> items)140         protected void onPostExecute(List<LensPickerItem> items) {
141             mItems.addAll(items);
142             notifyDataSetChanged();
143         }
144 
145         /**
146          * Returns the icon for the application represented by the given parameters.
147          */
getComponentIcon(PackageManager packageManager, ApplicationInfo info)148         private Drawable getComponentIcon(PackageManager packageManager, ApplicationInfo info) {
149             return packageManager.getApplicationIcon(info);
150         }
151 
152         /**
153          * Returns the name of the application represented by the given parameters.
154          */
getComponentLabel(PackageManager packageManager, ApplicationInfo info)155         private String getComponentLabel(PackageManager packageManager, ApplicationInfo info) {
156             CharSequence appLabel = packageManager.getApplicationLabel(info);
157 
158             if (appLabel == null) {
159                 return null;
160             }
161 
162             return appLabel.toString();
163         }
164     }
165 
166 
167 }
168