Merge "Use Activity Context for CDM ListView Adapter" into sc-dev
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 91bad7b..f9795c6 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -41,13 +41,13 @@
android:supportsRtl="true">
<service
- android:name=".DeviceDiscoveryService"
+ android:name=".CompanionDeviceDiscoveryService"
android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
android:exported="true">
</service>
<activity
- android:name=".DeviceChooserActivity"
+ android:name=".CompanionDeviceActivity"
android:theme="@style/ChooserActivity"
android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
android:exported="true">
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
similarity index 62%
rename from packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
rename to packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index c30d4bf..28072ca 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -24,6 +24,7 @@
import static java.util.Objects.requireNonNull;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.companion.AssociationRequest;
@@ -31,41 +32,52 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.database.DataSetObserver;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
+import android.util.SparseArray;
+import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
-import android.widget.AdapterView;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
-import com.android.companiondevicemanager.DeviceDiscoveryService.DeviceFilterPair;
+import com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DeviceFilterPair;
import com.android.internal.util.Preconditions;
-public class DeviceChooserActivity extends Activity {
+public class CompanionDeviceActivity extends Activity {
private static final boolean DEBUG = false;
- private static final String LOG_TAG = "DeviceChooserActivity";
+ private static final String LOG_TAG = CompanionDeviceActivity.class.getSimpleName();
+
+ static CompanionDeviceActivity sInstance;
View mLoadingIndicator = null;
ListView mDeviceListView;
private View mPairButton;
private View mCancelButton;
+ DevicesAdapter mDevicesAdapter;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (DEBUG) Log.i(LOG_TAG, "Started with intent " + getIntent());
+ Log.i(LOG_TAG, "Starting UI for " + getService().mRequest);
if (getService().mDevicesFound.isEmpty()) {
Log.e(LOG_TAG, "About to show UI, but no devices to show");
}
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ sInstance = this;
String deviceProfile = getRequest().getDeviceProfile();
String profilePrivacyDisclaimer = emptyIfNull(getRequest()
@@ -96,17 +108,14 @@
profileName,
getCallingAppName()), 0));
mDeviceListView = findViewById(R.id.device_list);
- final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
- mDeviceListView.setAdapter(adapter);
- mDeviceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int pos, long l) {
- getService().mSelectedDevice =
- (DeviceFilterPair) adapterView.getItemAtPosition(pos);
- adapter.notifyDataSetChanged();
- }
+ mDevicesAdapter = new DevicesAdapter();
+ mDeviceListView.setAdapter(mDevicesAdapter);
+ mDeviceListView.setOnItemClickListener((adapterView, view, pos, l) -> {
+ getService().mSelectedDevice =
+ (DeviceFilterPair) adapterView.getItemAtPosition(pos);
+ mDevicesAdapter.notifyDataSetChanged();
});
- adapter.registerDataSetObserver(new DataSetObserver() {
+ mDevicesAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
onSelectionUpdate();
@@ -133,6 +142,12 @@
mCancelButton.setOnClickListener(v -> cancel());
}
+ static void notifyDevicesChanged() {
+ if (sInstance != null && !sInstance.isFinishing()) {
+ sInstance.mDevicesAdapter.notifyDataSetChanged();
+ }
+ }
+
private AssociationRequest getRequest() {
return getService().mRequest;
}
@@ -156,6 +171,7 @@
}
private void cancel() {
+ Log.i(LOG_TAG, "cancel()");
getService().onCancel();
setResult(RESULT_CANCELED);
finish();
@@ -170,6 +186,14 @@
}
}
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (sInstance == this) {
+ sInstance = null;
+ }
+ }
+
private CharSequence getCallingAppName() {
try {
final PackageManager packageManager = getPackageManager();
@@ -217,15 +241,91 @@
}
}
- private DeviceDiscoveryService getService() {
- return DeviceDiscoveryService.sInstance;
+ private CompanionDeviceDiscoveryService getService() {
+ return CompanionDeviceDiscoveryService.sInstance;
}
- protected void onDeviceConfirmed(DeviceFilterPair selectedDevice) {
+ protected void onDeviceConfirmed(DeviceFilterPair selectedDevice) {
+ Log.i(LOG_TAG, "onDeviceConfirmed(selectedDevice = " + selectedDevice + ")");
getService().onDeviceSelected(
getCallingPackage(), getDeviceMacAddress(selectedDevice.device));
setResult(RESULT_OK,
new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice.device));
finish();
}
+
+ class DevicesAdapter extends BaseAdapter {
+ private final Drawable mBluetoothIcon = icon(android.R.drawable.stat_sys_data_bluetooth);
+ private final Drawable mWifiIcon = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
+
+ private SparseArray<Integer> mColors = new SparseArray();
+
+ private Drawable icon(int drawableRes) {
+ Drawable icon = getResources().getDrawable(drawableRes, null);
+ icon.setTint(Color.DKGRAY);
+ return icon;
+ }
+
+ @Override
+ public View getView(
+ int position,
+ @Nullable View convertView,
+ @NonNull ViewGroup parent) {
+ TextView view = convertView instanceof TextView
+ ? (TextView) convertView
+ : newView();
+ bind(view, getItem(position));
+ return view;
+ }
+
+ private void bind(TextView textView, DeviceFilterPair device) {
+ textView.setText(device.getDisplayName());
+ textView.setBackgroundColor(
+ device.equals(getService().mSelectedDevice)
+ ? getColor(android.R.attr.colorControlHighlight)
+ : Color.TRANSPARENT);
+ textView.setCompoundDrawablesWithIntrinsicBounds(
+ device.device instanceof android.net.wifi.ScanResult
+ ? mWifiIcon
+ : mBluetoothIcon,
+ null, null, null);
+ textView.getCompoundDrawables()[0].setTint(getColor(android.R.attr.colorForeground));
+ }
+
+ private TextView newView() {
+ final TextView textView = new TextView(CompanionDeviceActivity.this);
+ textView.setTextColor(getColor(android.R.attr.colorForeground));
+ final int padding = CompanionDeviceActivity.getPadding(getResources());
+ textView.setPadding(padding, padding, padding, padding);
+ textView.setCompoundDrawablePadding(padding);
+ return textView;
+ }
+
+ private int getColor(int colorAttr) {
+ if (mColors.contains(colorAttr)) {
+ return mColors.get(colorAttr);
+ }
+ TypedValue typedValue = new TypedValue();
+ TypedArray a = obtainStyledAttributes(typedValue.data, new int[] { colorAttr });
+ int result = a.getColor(0, 0);
+ a.recycle();
+ mColors.put(colorAttr, result);
+ return result;
+ }
+
+ @Override
+ public int getCount() {
+ return getService().mDevicesFound.size();
+ }
+
+ @Override
+ public DeviceFilterPair getItem(int position) {
+ return getService().mDevicesFound.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+ }
}
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
similarity index 80%
rename from packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
rename to packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index 67d4b41..e620dfb 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -50,9 +50,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
@@ -60,12 +57,6 @@
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
-import android.util.SparseArray;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.ArrayUtils;
@@ -76,14 +67,14 @@
import java.util.List;
import java.util.Objects;
-public class DeviceDiscoveryService extends Service {
+public class CompanionDeviceDiscoveryService extends Service {
private static final boolean DEBUG = false;
- private static final String LOG_TAG = "DeviceDiscoveryService";
+ private static final String LOG_TAG = CompanionDeviceDiscoveryService.class.getSimpleName();
private static final long SCAN_TIMEOUT = 20000;
- static DeviceDiscoveryService sInstance;
+ static CompanionDeviceDiscoveryService sInstance;
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
@@ -102,12 +93,12 @@
AssociationRequest mRequest;
List<DeviceFilterPair> mDevicesFound;
DeviceFilterPair mSelectedDevice;
- DevicesAdapter mDevicesAdapter;
IFindDeviceCallback mFindCallback;
AndroidFuture<Association> mServiceCallback;
boolean mIsScanning = false;
- @Nullable DeviceChooserActivity mActivity = null;
+ @Nullable
+ CompanionDeviceActivity mActivity = null;
private final ICompanionDeviceDiscoveryService mBinder =
new ICompanionDeviceDiscoveryService.Stub() {
@@ -125,7 +116,8 @@
mFindCallback = findCallback;
mServiceCallback = serviceCallback;
Handler.getMain().sendMessage(obtainMessage(
- DeviceDiscoveryService::startDiscovery, DeviceDiscoveryService.this, request));
+ CompanionDeviceDiscoveryService::startDiscovery,
+ CompanionDeviceDiscoveryService.this, request));
}
};
@@ -151,7 +143,6 @@
mWifiManager = getSystemService(WifiManager.class);
mDevicesFound = new ArrayList<>();
- mDevicesAdapter = new DevicesAdapter();
sInstance = this;
}
@@ -165,7 +156,8 @@
mWifiFilters = CollectionUtils.filter(mFilters, WifiDeviceFilter.class);
mBluetoothFilters = CollectionUtils.filter(mFilters, BluetoothDeviceFilter.class);
mBLEFilters = CollectionUtils.filter(mFilters, BluetoothLeDeviceFilter.class);
- mBLEScanFilters = CollectionUtils.map(mBLEFilters, BluetoothLeDeviceFilter::getScanFilter);
+ mBLEScanFilters
+ = CollectionUtils.map(mBLEFilters, BluetoothLeDeviceFilter::getScanFilter);
reset();
} else if (DEBUG) Log.i(LOG_TAG, "startDiscovery: duplicate request: " + request);
@@ -223,7 +215,7 @@
}
mIsScanning = true;
Handler.getMain().sendMessageDelayed(
- obtainMessage(DeviceDiscoveryService::stopScan, this),
+ obtainMessage(CompanionDeviceDiscoveryService::stopScan, this),
SCAN_TIMEOUT);
}
@@ -237,7 +229,7 @@
stopScan();
mDevicesFound.clear();
mSelectedDevice = null;
- mDevicesAdapter.notifyDataSetChanged();
+ CompanionDeviceActivity.notifyDevicesChanged();
}
@Override
@@ -252,7 +244,7 @@
if (!mIsScanning) return;
mIsScanning = false;
- DeviceChooserActivity activity = mActivity;
+ CompanionDeviceActivity activity = mActivity;
if (activity != null) {
if (activity.mDeviceListView != null) {
activity.mDeviceListView.removeFooterView(activity.mLoadingIndicator);
@@ -276,7 +268,7 @@
if (device == null) return;
Handler.getMain().sendMessage(obtainMessage(
- DeviceDiscoveryService::onDeviceFoundMainThread, this, device));
+ CompanionDeviceDiscoveryService::onDeviceFoundMainThread, this, device));
}
@MainThread
@@ -292,7 +284,7 @@
onReadyToShowUI();
}
mDevicesFound.add(device);
- mDevicesAdapter.notifyDataSetChanged();
+ CompanionDeviceActivity.notifyDevicesChanged();
}
//TODO also, on timeout -> call onFailure
@@ -300,7 +292,7 @@
try {
mFindCallback.onSuccess(PendingIntent.getActivity(
this, 0,
- new Intent(this, DeviceChooserActivity.class),
+ new Intent(this, CompanionDeviceActivity.class),
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_IMMUTABLE));
} catch (RemoteException e) {
@@ -311,13 +303,13 @@
private void onDeviceLost(@Nullable DeviceFilterPair device) {
Log.i(LOG_TAG, "Lost device " + device.getDisplayName());
Handler.getMain().sendMessage(obtainMessage(
- DeviceDiscoveryService::onDeviceLostMainThread, this, device));
+ CompanionDeviceDiscoveryService::onDeviceLostMainThread, this, device));
}
@MainThread
void onDeviceLostMainThread(@Nullable DeviceFilterPair device) {
mDevicesFound.remove(device);
- mDevicesAdapter.notifyDataSetChanged();
+ CompanionDeviceActivity.notifyDevicesChanged();
}
void onDeviceSelected(String callingPackage, String deviceAddress) {
@@ -331,81 +323,6 @@
mServiceCallback.cancel(true);
}
- class DevicesAdapter extends BaseAdapter {
- private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
- private Drawable WIFI_ICON = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
-
- private SparseArray<Integer> mColors = new SparseArray();
-
- private Drawable icon(int drawableRes) {
- Drawable icon = getResources().getDrawable(drawableRes, null);
- icon.setTint(Color.DKGRAY);
- return icon;
- }
-
- @Override
- public View getView(
- int position,
- @Nullable View convertView,
- @NonNull ViewGroup parent) {
- TextView view = convertView instanceof TextView
- ? (TextView) convertView
- : newView();
- bind(view, getItem(position));
- return view;
- }
-
- private void bind(TextView textView, DeviceFilterPair device) {
- textView.setText(device.getDisplayName());
- textView.setBackgroundColor(
- device.equals(mSelectedDevice)
- ? getColor(android.R.attr.colorControlHighlight)
- : Color.TRANSPARENT);
- textView.setCompoundDrawablesWithIntrinsicBounds(
- device.device instanceof android.net.wifi.ScanResult
- ? WIFI_ICON
- : BLUETOOTH_ICON,
- null, null, null);
- textView.getCompoundDrawables()[0].setTint(getColor(android.R.attr.colorForeground));
- }
-
- private TextView newView() {
- final TextView textView = new TextView(DeviceDiscoveryService.this);
- textView.setTextColor(getColor(android.R.attr.colorForeground));
- final int padding = DeviceChooserActivity.getPadding(getResources());
- textView.setPadding(padding, padding, padding, padding);
- textView.setCompoundDrawablePadding(padding);
- return textView;
- }
-
- private int getColor(int colorAttr) {
- if (mColors.contains(colorAttr)) {
- return mColors.get(colorAttr);
- }
- TypedValue typedValue = new TypedValue();
- TypedArray a = obtainStyledAttributes(typedValue.data, new int[] { colorAttr });
- int result = a.getColor(0, 0);
- a.recycle();
- mColors.put(colorAttr, result);
- return result;
- }
-
- @Override
- public int getCount() {
- return mDevicesFound.size();
- }
-
- @Override
- public DeviceFilterPair getItem(int position) {
- return mDevicesFound.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
- }
-
/**
* A pair of device and a filter that matched this device if any.
*
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 01055be..ebfa917 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -142,18 +142,13 @@
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
-//TODO onStop schedule unbind in 5 seconds
-//TODO make sure APIs are only callable from currently focused app
-//TODO schedule stopScan on activity destroy(except if configuration change)
-//TODO on associate called again after configuration change -> replace old callback with new
-//TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example)
/** @hide */
@SuppressLint("LongLogTag")
public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {
private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
- ".DeviceDiscoveryService");
+ ".CompanionDeviceDiscoveryService");
private static final long DEVICE_DISAPPEARED_TIMEOUT_MS = 10 * 1000;
private static final long DEVICE_DISAPPEARED_UNBIND_TIMEOUT_MS = 10 * 60 * 1000;