Introduce Permission list for app_streaming and computer
Test: Test: atest CtsCompanionDeviceManagerCoreTestCases
atest CtsCompanionDeviceManagerUiAutomationTestCases
atest CtsOsTestCases:CompanionDeviceManagerTest
Bug: 216638097
Change-Id: I465b7e6492a935c94d4cc4537ed0c99f52a6d3a3
This commit is contained in:
34
packages/CompanionDeviceManager/res/drawable/ic_apps.xml
Normal file
34
packages/CompanionDeviceManager/res/drawable/ic_apps.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<group android:scaleX="5.142857"
|
||||
android:scaleY="5.142857"
|
||||
android:translateY="2.5714285">
|
||||
<path
|
||||
android:pathData="M13.1235,1.01L5.1235,1C4.0235,1 3.1235,1.9 3.1235,3V17C3.1235,18.1 4.0235,19 5.1235,19H13.1235C14.2235,19 15.1235,18.1 15.1235,17V12.9765H13.1235V14H5.1235V6H13.1235V6.0034H15.1235V3C15.1235,1.9 14.2235,1.01 13.1235,1.01ZM13.1235,17H5.1235V16H13.1235V17ZM5.1235,4V3H13.1235V4H5.1235Z"
|
||||
android:fillColor="#202124"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M10.6984,6.4016V13.3136L12.3596,12.3628H17.8731V6.4016H10.6984ZM16.3731,7.9016H12.1984V10.8628H16.3731V7.9016Z"
|
||||
android:fillColor="#202124"
|
||||
android:fillType="evenOdd"/>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path android:fillColor="@android:color/white"
|
||||
android:pathData="M4,19V17H6V10Q6,7.925 7.25,6.312Q8.5,4.7 10.5,4.2V3.5Q10.5,2.875 10.938,2.438Q11.375,2 12,2Q12.625,2 13.062,2.438Q13.5,2.875 13.5,3.5V4.2Q15.5,4.7 16.75,6.312Q18,7.925 18,10V17H20V19ZM12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5ZM12,22Q11.175,22 10.588,21.413Q10,20.825 10,20H14Q14,20.825 13.413,21.413Q12.825,22 12,22ZM8,17H16V10Q16,8.35 14.825,7.175Q13.65,6 12,6Q10.35,6 9.175,7.175Q8,8.35 8,10Z"/>
|
||||
</vector>
|
||||
25
packages/CompanionDeviceManager/res/drawable/ic_storage.xml
Normal file
25
packages/CompanionDeviceManager/res/drawable/ic_storage.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path android:fillColor="@android:color/white"
|
||||
android:pathData="M6,17H18L14.25,12L11.25,16L9,13ZM5,21Q4.175,21 3.587,20.413Q3,19.825 3,19V5Q3,4.175 3.587,3.587Q4.175,3 5,3H19Q19.825,3 20.413,3.587Q21,4.175 21,5V19Q21,19.825 20.413,20.413Q19.825,21 19,21ZM5,19H19Q19,19 19,19Q19,19 19,19V5Q19,5 19,5Q19,5 19,5H5Q5,5 5,5Q5,5 5,5V19Q5,19 5,19Q5,19 5,19ZM5,5Q5,5 5,5Q5,5 5,5V19Q5,19 5,19Q5,19 5,19Q5,19 5,19Q5,19 5,19V5Q5,5 5,5Q5,5 5,5Z"/>
|
||||
</vector>
|
||||
@@ -51,6 +51,11 @@
|
||||
android:scrollbars="vertical"
|
||||
android:layout_height="200dp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/permission_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/list_item_permission"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="5dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/permission_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginTop="7dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:contentDescription="Permission Icon"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="6dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/permission_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSmall"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/permission_summary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?android:attr/textColorSecondary"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -38,6 +38,12 @@
|
||||
|
||||
<!-- ================= DEVICE_PROFILE_APP_STREAMING ================= -->
|
||||
|
||||
<!-- Apps permission will be granted of APP_STREAMING profile [CHAR LIMIT=30] -->
|
||||
<string name="permission_apps">Apps</string>
|
||||
|
||||
<!-- Description of apps permission of APP_STREAMING profile [CHAR LIMIT=NONE] -->
|
||||
<string name="permission_apps_summary">Stream your phone\u2019s apps</string>
|
||||
|
||||
<!-- Confirmation for associating an application with a companion device of APP_STREAMING profile (type) [CHAR LIMIT=NONE] -->
|
||||
<string name="title_app_streaming">Allow <strong><xliff:g id="app_name" example="Exo">%1$s</xliff:g></strong> to access this information for your phone</string>
|
||||
|
||||
@@ -72,6 +78,18 @@
|
||||
<!-- Description of the privileges the application will get if associated with the companion device of COMPUTER profile (type) [CHAR LIMIT=NONE] -->
|
||||
<string name="summary_computer"></string>
|
||||
|
||||
<!-- Notification permission will be granted of COMPUTER profile [CHAR LIMIT=30] -->
|
||||
<string name="permission_notification">Notifications</string>
|
||||
|
||||
<!-- Description of notification permission of COMPUTER profile [CHAR LIMIT=NONE] -->
|
||||
<string name="permission_notification_summary">Can read all notifications, including information like contracts, messages, and photos</string>
|
||||
|
||||
<!-- Storage permission will be granted of COMPUTER profile [CHAR LIMIT=30] -->
|
||||
<string name="permission_storage">Photos and media</string>
|
||||
|
||||
<!-- Description of storage permission of COMPUTER profile [CHAR LIMIT=NONE] -->
|
||||
<string name="permission_storage_summary"></string>
|
||||
|
||||
<!-- Title of the helper dialog for COMPUTER profile [CHAR LIMIT=30]. -->
|
||||
<string name="helper_title_computer">Google Play services</string>
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE
|
||||
|
||||
import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState;
|
||||
import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT;
|
||||
import static com.android.companiondevicemanager.PermissionListAdapter.TYPE_APPS;
|
||||
import static com.android.companiondevicemanager.PermissionListAdapter.TYPE_NOTIFICATION;
|
||||
import static com.android.companiondevicemanager.PermissionListAdapter.TYPE_STORAGE;
|
||||
import static com.android.companiondevicemanager.Utils.getApplicationLabel;
|
||||
import static com.android.companiondevicemanager.Utils.getHtmlFromResources;
|
||||
import static com.android.companiondevicemanager.Utils.getVendorHeaderIcon;
|
||||
@@ -61,6 +64,7 @@ import androidx.fragment.app.FragmentManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -122,8 +126,12 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
|
||||
// The recycler view is only shown for multiple-device regular association request, after
|
||||
// at least one matching device is found.
|
||||
private @Nullable RecyclerView mRecyclerView;
|
||||
private @Nullable DeviceListAdapter mAdapter;
|
||||
private @Nullable RecyclerView mDeviceListRecyclerView;
|
||||
private @Nullable DeviceListAdapter mDeviceAdapter;
|
||||
|
||||
// The recycler view is only shown for selfManaged association request.
|
||||
private @Nullable RecyclerView mPermissionListRecyclerView;
|
||||
private @Nullable PermissionListAdapter mPermissionListAdapter;
|
||||
|
||||
// The flag used to prevent double taps, that may lead to sending several requests for creating
|
||||
// an association to CDM.
|
||||
@@ -133,6 +141,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
// onActivityResult() after the association is created.
|
||||
private @Nullable DeviceFilterPair<?> mSelectedDevice;
|
||||
|
||||
private @Nullable List<Integer> mPermissionTypes;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
if (DEBUG) Log.d(TAG, "onCreate()");
|
||||
@@ -242,8 +252,11 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
mVendorHeaderName = findViewById(R.id.vendor_header_name);
|
||||
mVendorHeaderButton = findViewById(R.id.vendor_header_button);
|
||||
|
||||
mRecyclerView = findViewById(R.id.device_list);
|
||||
mAdapter = new DeviceListAdapter(this, this::onListItemClick);
|
||||
mDeviceListRecyclerView = findViewById(R.id.device_list);
|
||||
mDeviceAdapter = new DeviceListAdapter(this, this::onListItemClick);
|
||||
|
||||
mPermissionListRecyclerView = findViewById(R.id.permission_list);
|
||||
mPermissionListAdapter = new PermissionListAdapter(this);
|
||||
|
||||
mButtonAllow = findViewById(R.id.btn_positive);
|
||||
mButtonNotAllow = findViewById(R.id.btn_negative);
|
||||
@@ -359,7 +372,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
final Drawable vendorIcon;
|
||||
final CharSequence vendorName;
|
||||
final Spanned title;
|
||||
final Spanned summary;
|
||||
|
||||
mPermissionTypes = new ArrayList<>();
|
||||
|
||||
try {
|
||||
vendorIcon = getVendorHeaderIcon(this, packageName, userId);
|
||||
@@ -372,33 +386,36 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
|
||||
switch (deviceProfile) {
|
||||
case DEVICE_PROFILE_APP_STREAMING:
|
||||
title = getHtmlFromResources(this, R.string.title_app_streaming, appLabel);
|
||||
summary = getHtmlFromResources(
|
||||
this, R.string.summary_app_streaming, appLabel, deviceName);
|
||||
title = getHtmlFromResources(this, R.string.title_app_streaming, deviceName);
|
||||
mPermissionTypes.add(TYPE_APPS);
|
||||
break;
|
||||
|
||||
case DEVICE_PROFILE_AUTOMOTIVE_PROJECTION:
|
||||
title = getHtmlFromResources(this, R.string.title_automotive_projection, appLabel);
|
||||
summary = getHtmlFromResources(
|
||||
this, R.string.summary_automotive_projection, appLabel, deviceName);
|
||||
title = getHtmlFromResources(
|
||||
this, R.string.title_automotive_projection, deviceName);
|
||||
break;
|
||||
|
||||
case DEVICE_PROFILE_COMPUTER:
|
||||
title = getHtmlFromResources(this, R.string.title_computer, appLabel);
|
||||
summary = getHtmlFromResources(
|
||||
this, R.string.summary_computer, appLabel, deviceName);
|
||||
title = getHtmlFromResources(this, R.string.title_computer, deviceName);
|
||||
mPermissionTypes.add(TYPE_NOTIFICATION);
|
||||
mPermissionTypes.add(TYPE_STORAGE);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Unsupported profile " + deviceProfile);
|
||||
}
|
||||
|
||||
mSummary.setVisibility(View.GONE);
|
||||
|
||||
mPermissionListAdapter.setPermissionType(mPermissionTypes);
|
||||
mPermissionListRecyclerView.setAdapter(mPermissionListAdapter);
|
||||
mPermissionListRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
|
||||
mTitle.setText(title);
|
||||
mSummary.setText(summary);
|
||||
mVendorHeaderImage.setImageDrawable(vendorIcon);
|
||||
mVendorHeaderName.setText(vendorName);
|
||||
|
||||
mRecyclerView.setVisibility(View.GONE);
|
||||
mDeviceListRecyclerView.setVisibility(View.GONE);
|
||||
mVendorHeader.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@@ -411,7 +428,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
deviceFilterPairs -> updateSingleDeviceUi(
|
||||
deviceFilterPairs, deviceProfile, appLabel));
|
||||
|
||||
mRecyclerView.setVisibility(View.GONE);
|
||||
mPermissionListRecyclerView.setVisibility(View.GONE);
|
||||
mDeviceListRecyclerView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void updateSingleDeviceUi(List<DeviceFilterPair<?>> deviceFilterPairs,
|
||||
@@ -460,15 +478,15 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
mTitle.setText(title);
|
||||
mSummary.setText(summary);
|
||||
|
||||
mAdapter = new DeviceListAdapter(this, this::onListItemClick);
|
||||
mDeviceAdapter = new DeviceListAdapter(this, this::onListItemClick);
|
||||
|
||||
// TODO: hide the list and show a spinner until a first device matching device is found.
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
mDeviceListRecyclerView.setAdapter(mDeviceAdapter);
|
||||
mDeviceListRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
|
||||
CompanionDeviceDiscoveryService.getScanResult().observe(
|
||||
/* lifecycleOwner */ this,
|
||||
/* observer */ mAdapter);
|
||||
/* observer */ mDeviceAdapter);
|
||||
|
||||
// "Remove" consent button: users would need to click on the list item.
|
||||
mButtonAllow.setVisibility(View.GONE);
|
||||
@@ -477,14 +495,14 @@ public class CompanionDeviceActivity extends FragmentActivity implements
|
||||
private void onListItemClick(int position) {
|
||||
if (DEBUG) Log.d(TAG, "onListItemClick() " + position);
|
||||
|
||||
final DeviceFilterPair<?> selectedDevice = mAdapter.getItem(position);
|
||||
final DeviceFilterPair<?> selectedDevice = mDeviceAdapter.getItem(position);
|
||||
|
||||
if (mSelectedDevice != null) {
|
||||
if (DEBUG) Log.w(TAG, "Already selected.");
|
||||
return;
|
||||
}
|
||||
// Notify the adapter to highlight the selected item.
|
||||
mAdapter.setSelectedPosition(position);
|
||||
mDeviceAdapter.setSelectedPosition(position);
|
||||
|
||||
mSelectedDevice = requireNonNull(selectedDevice);
|
||||
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
|
||||
package com.android.companiondevicemanager;
|
||||
|
||||
import static com.android.companiondevicemanager.Utils.getIcon;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -60,11 +61,11 @@ class DeviceListAdapter extends RecyclerView.Adapter<DeviceListAdapter.ViewHolde
|
||||
R.layout.list_item_device, parent, false);
|
||||
ViewHolder viewHolder = new ViewHolder(view);
|
||||
if (viewType == TYPE_WIFI) {
|
||||
viewHolder.mImageView.setImageDrawable(getIcon(
|
||||
com.android.internal.R.drawable.ic_wifi_signal_3));
|
||||
viewHolder.mImageView.setImageDrawable(
|
||||
getIcon(mContext, com.android.internal.R.drawable.ic_wifi_signal_3));
|
||||
} else {
|
||||
viewHolder.mImageView.setImageDrawable(getIcon(
|
||||
android.R.drawable.stat_sys_data_bluetooth));
|
||||
viewHolder.mImageView.setImageDrawable(
|
||||
getIcon(mContext, android.R.drawable.stat_sys_data_bluetooth));
|
||||
}
|
||||
return viewHolder;
|
||||
}
|
||||
@@ -115,12 +116,6 @@ class DeviceListAdapter extends RecyclerView.Adapter<DeviceListAdapter.ViewHolde
|
||||
return mDevices.get(position).getDevice() instanceof android.net.wifi.ScanResult;
|
||||
}
|
||||
|
||||
private Drawable getIcon(int resId) {
|
||||
Drawable icon = mContext.getResources().getDrawable(resId, null);
|
||||
icon.setTint(Color.DKGRAY);
|
||||
return icon;
|
||||
}
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onItemClick(int position);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.companiondevicemanager;
|
||||
|
||||
import static com.android.companiondevicemanager.Utils.getHtmlFromResources;
|
||||
import static com.android.companiondevicemanager.Utils.getIcon;
|
||||
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Spanned;
|
||||
import android.util.ArrayMap;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class PermissionListAdapter extends RecyclerView.Adapter<PermissionListAdapter.ViewHolder> {
|
||||
private final Context mContext;
|
||||
|
||||
private List<Integer> mPermissions;
|
||||
|
||||
static final int TYPE_NOTIFICATION = 0;
|
||||
static final int TYPE_STORAGE = 1;
|
||||
static final int TYPE_APPS = 2;
|
||||
|
||||
private static final Map<Integer, Integer> sTitleMap;
|
||||
static {
|
||||
final Map<Integer, Integer> map = new ArrayMap<>();
|
||||
map.put(TYPE_NOTIFICATION, R.string.permission_notification);
|
||||
map.put(TYPE_STORAGE, R.string.permission_storage);
|
||||
map.put(TYPE_APPS, R.string.permission_apps);
|
||||
sTitleMap = unmodifiableMap(map);
|
||||
}
|
||||
|
||||
private static final Map<Integer, Integer> sSummaryMap;
|
||||
static {
|
||||
final Map<Integer, Integer> map = new ArrayMap<>();
|
||||
map.put(TYPE_NOTIFICATION, R.string.permission_notification_summary);
|
||||
map.put(TYPE_STORAGE, R.string.permission_storage_summary);
|
||||
map.put(TYPE_APPS, R.string.permission_apps_summary);
|
||||
sSummaryMap = unmodifiableMap(map);
|
||||
}
|
||||
|
||||
private static final Map<Integer, Integer> sIconMap;
|
||||
static {
|
||||
final Map<Integer, Integer> map = new ArrayMap<>();
|
||||
map.put(TYPE_NOTIFICATION, R.drawable.ic_notifications);
|
||||
map.put(TYPE_STORAGE, R.drawable.ic_storage);
|
||||
map.put(TYPE_APPS, R.drawable.ic_apps);
|
||||
sIconMap = unmodifiableMap(map);
|
||||
}
|
||||
|
||||
PermissionListAdapter(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(
|
||||
R.layout.list_item_permission, parent, false);
|
||||
ViewHolder viewHolder = new ViewHolder(view);
|
||||
viewHolder.mPermissionIcon.setImageDrawable(getIcon(mContext, sIconMap.get(viewType)));
|
||||
|
||||
return viewHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
int type = getItemViewType(position);
|
||||
final Spanned title = getHtmlFromResources(mContext, sTitleMap.get(type));
|
||||
final Spanned summary = getHtmlFromResources(mContext, sSummaryMap.get(type));
|
||||
|
||||
holder.mPermissionName.setText(title);
|
||||
holder.mPermissionSummary.setText(summary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return mPermissions.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mPermissions != null ? mPermissions.size() : 0;
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private final TextView mPermissionName;
|
||||
private final TextView mPermissionSummary;
|
||||
private final ImageView mPermissionIcon;
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
mPermissionName = itemView.findViewById(R.id.permission_name);
|
||||
mPermissionSummary = itemView.findViewById(R.id.permission_summary);
|
||||
mPermissionIcon = itemView.findViewById(R.id.permission_icon);
|
||||
}
|
||||
}
|
||||
|
||||
void setPermissionType(List<Integer> permissions) {
|
||||
mPermissions = permissions;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.ApplicationInfoFlags;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -121,6 +122,12 @@ class Utils {
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
static @NonNull Drawable getIcon(@NonNull Context context, int resId) {
|
||||
Drawable icon = context.getResources().getDrawable(resId, null);
|
||||
icon.setTint(Color.DKGRAY);
|
||||
return icon;
|
||||
}
|
||||
|
||||
static void runOnMainThread(Runnable runnable) {
|
||||
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
|
||||
runnable.run();
|
||||
|
||||
Reference in New Issue
Block a user