Loading packages/CompanionDeviceManager/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -36,5 +36,11 @@ android_app { defaults: ["platform_app_defaults"], srcs: ["src/**/*.java"], static_libs: [ "androidx.lifecycle_lifecycle-livedata", "androidx.lifecycle_lifecycle-extensions", "androidx.appcompat_appcompat", ], platform_apis: true, } packages/CompanionDeviceManager/res/drawable/dialog_background.xml +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ <inset xmlns:android="http://schemas.android.com/apk/res/android"> <shape android:shape="rectangle"> <corners android:radius="?android:attr/dialogCornerRadius" /> <corners android:radius="@*android:dimen/config_dialogCornerRadius" /> <solid android:color="?android:attr/colorBackground" /> </shape> </inset> packages/CompanionDeviceManager/res/values/themes.xml +3 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ <resources> <style name="ChooserActivity" parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"> parent="@style/Theme.AppCompat.Light.Dialog"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> <item name="*android:windowFixedHeightMajor">100%</item> <item name="*android:windowFixedHeightMinor">100%</item> <item name="android:windowBackground">@android:color/transparent</item> Loading packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java +23 −10 Original line number Diff line number Diff line Loading @@ -22,8 +22,8 @@ import static android.companion.AssociationRequest.DEVICE_PROFILE_COMPUTER; import static android.companion.AssociationRequest.DEVICE_PROFILE_WATCH; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.SCAN_RESULTS_OBSERVABLE; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.TIMEOUT_OBSERVABLE; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT; import static com.android.companiondevicemanager.Utils.getApplicationLabel; import static com.android.companiondevicemanager.Utils.getHtmlFromResources; import static com.android.companiondevicemanager.Utils.prepareResultReceiverForIpc; Loading @@ -32,7 +32,6 @@ import static java.util.Objects.requireNonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; Loading @@ -50,7 +49,13 @@ import android.widget.Button; import android.widget.ListView; import android.widget.TextView; public class CompanionDeviceActivity extends Activity { import androidx.appcompat.app.AppCompatActivity; /** * A CompanionDevice activity response for showing the available * nearby devices to be associated with. */ public class CompanionDeviceActivity extends AppCompatActivity { private static final boolean DEBUG = false; private static final String TAG = CompanionDeviceActivity.class.getSimpleName(); Loading Loading @@ -126,7 +131,9 @@ public class CompanionDeviceActivity extends Activity { // Start discovery services if needed. if (!mRequest.isSelfManaged()) { CompanionDeviceDiscoveryService.startForRequest(this, mRequest); TIMEOUT_OBSERVABLE.addObserver((o, arg) -> cancel(true)); // TODO(b/217749191): Create the ViewModel for the LiveData CompanionDeviceDiscoveryService.getDiscoveryState().observe( /* LifeCycleOwner */ this, this::onDiscoveryStateChanged); } // Init UI. initUI(); Loading Loading @@ -158,10 +165,6 @@ public class CompanionDeviceActivity extends Activity { if (!isDone()) { cancel(false); // will finish() } TIMEOUT_OBSERVABLE.deleteObservers(); // mAdapter may also be observing - need to remove it. SCAN_RESULTS_OBSERVABLE.deleteObservers(); } @Override Loading Loading @@ -210,6 +213,13 @@ public class CompanionDeviceActivity extends Activity { } } private void onDiscoveryStateChanged(DiscoveryState newState) { if (newState == FINISHED_TIMEOUT && CompanionDeviceDiscoveryService.getScanResult().getValue().isEmpty()) { cancel(true); } } private void onUserSelectedDevice(@NonNull DeviceFilterPair<?> selectedDevice) { if (mSelectedDevice != null) { if (DEBUG) Log.w(TAG, "Already selected."); Loading Loading @@ -380,9 +390,12 @@ public class CompanionDeviceActivity extends Activity { mSummary.setText(summary); mAdapter = new DeviceListAdapter(this); SCAN_RESULTS_OBSERVABLE.addObserver(mAdapter); // TODO: hide the list and show a spinner until a first device matching device is found. mListView.setAdapter(mAdapter); CompanionDeviceDiscoveryService.getScanResult().observe( /* lifecycleOwner */ this, /* observer */ mAdapter); // "Remove" consent button: users would need to click on the list item. mButtonAllow.setVisibility(View.GONE); Loading packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java +35 −26 Original line number Diff line number Diff line Loading @@ -56,13 +56,18 @@ import android.os.SystemProperties; import android.text.TextUtils; import android.util.Log; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Observable; /** * A CompanionDevice service response for scanning nearby devices */ public class CompanionDeviceDiscoveryService extends Service { private static final boolean DEBUG = false; private static final String TAG = CompanionDeviceDiscoveryService.class.getSimpleName(); Loading @@ -78,12 +83,10 @@ public class CompanionDeviceDiscoveryService extends Service { "com.android.companiondevicemanager.action.ACTION_STOP_DISCOVERY"; private static final String EXTRA_ASSOCIATION_REQUEST = "association_request"; // TODO: replace with LiveData-s? static final Observable TIMEOUT_OBSERVABLE = new MyObservable(); static final Observable SCAN_RESULTS_OBSERVABLE = new MyObservable(); private static CompanionDeviceDiscoveryService sInstance; private static MutableLiveData<List<DeviceFilterPair<?>>> sScanResultsLiveData = new MutableLiveData<>(Collections.emptyList()); private static MutableLiveData<DiscoveryState> sStateLiveData = new MutableLiveData<>(DiscoveryState.NOT_STARTED); private BluetoothManager mBtManager; private BluetoothAdapter mBtAdapter; Loading @@ -100,12 +103,25 @@ public class CompanionDeviceDiscoveryService extends Service { private final Runnable mTimeoutRunnable = this::timeout; /** * A state enum for devices' discovery. */ enum DiscoveryState { NOT_STARTED, STARTING, DISCOVERY_IN_PROGRESS, FINISHED_STOPPED, FINISHED_TIMEOUT } static void startForRequest( @NonNull Context context, @NonNull AssociationRequest associationRequest) { requireNonNull(associationRequest); final Intent intent = new Intent(context, CompanionDeviceDiscoveryService.class); intent.setAction(ACTION_START_DISCOVERY); intent.putExtra(EXTRA_ASSOCIATION_REQUEST, associationRequest); sStateLiveData.setValue(DiscoveryState.STARTING); context.startService(intent); } Loading @@ -115,10 +131,12 @@ public class CompanionDeviceDiscoveryService extends Service { context.startService(intent); } @MainThread static @NonNull List<DeviceFilterPair<?>> getScanResults() { return sInstance != null ? new ArrayList<>(sInstance.mDevicesFound) : Collections.emptyList(); static LiveData<List<DeviceFilterPair<?>>> getScanResult() { return sScanResultsLiveData; } static LiveData<DiscoveryState> getDiscoveryState() { return sStateLiveData; } @Override Loading @@ -126,8 +144,6 @@ public class CompanionDeviceDiscoveryService extends Service { super.onCreate(); if (DEBUG) Log.d(TAG, "onCreate()"); sInstance = this; mBtManager = getSystemService(BluetoothManager.class); mBtAdapter = mBtManager.getAdapter(); mBleScanner = mBtAdapter.getBluetoothLeScanner(); Loading @@ -148,6 +164,7 @@ public class CompanionDeviceDiscoveryService extends Service { case ACTION_STOP_DISCOVERY: stopDiscoveryAndFinish(); sStateLiveData.setValue(DiscoveryState.FINISHED_STOPPED); break; } return START_NOT_STICKY; Loading @@ -157,8 +174,6 @@ public class CompanionDeviceDiscoveryService extends Service { public void onDestroy() { super.onDestroy(); if (DEBUG) Log.d(TAG, "onDestroy()"); sInstance = null; } @MainThread Loading @@ -168,6 +183,8 @@ public class CompanionDeviceDiscoveryService extends Service { if (mDiscoveryStarted) throw new RuntimeException("Discovery in progress."); mDiscoveryStarted = true; sStateLiveData.setValue(DiscoveryState.DISCOVERY_IN_PROGRESS); sScanResultsLiveData.setValue(Collections.emptyList()); final List<DeviceFilter<?>> allFilters = request.getDeviceFilters(); final List<BluetoothDeviceFilter> btFilters = Loading Loading @@ -329,7 +346,7 @@ public class CompanionDeviceDiscoveryService extends Service { // First: make change. mDevicesFound.add(device); // Then: notify observers. SCAN_RESULTS_OBSERVABLE.notifyObservers(); sScanResultsLiveData.setValue(mDevicesFound); }); } Loading @@ -340,7 +357,7 @@ public class CompanionDeviceDiscoveryService extends Service { // First: make change. mDevicesFound.remove(device); // Then: notify observers. SCAN_RESULTS_OBSERVABLE.notifyObservers(); sScanResultsLiveData.setValue(mDevicesFound); }); } Loading @@ -362,7 +379,7 @@ public class CompanionDeviceDiscoveryService extends Service { private void timeout() { if (DEBUG) Log.i(TAG, "timeout()"); stopDiscoveryAndFinish(); TIMEOUT_OBSERVABLE.notifyObservers(); sStateLiveData.setValue(DiscoveryState.FINISHED_TIMEOUT); } @Override Loading Loading @@ -470,12 +487,4 @@ public class CompanionDeviceDiscoveryService extends Service { } return result; } private static class MyObservable extends Observable { @Override public void notifyObservers() { setChanged(); super.notifyObservers(); } } } Loading
packages/CompanionDeviceManager/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -36,5 +36,11 @@ android_app { defaults: ["platform_app_defaults"], srcs: ["src/**/*.java"], static_libs: [ "androidx.lifecycle_lifecycle-livedata", "androidx.lifecycle_lifecycle-extensions", "androidx.appcompat_appcompat", ], platform_apis: true, }
packages/CompanionDeviceManager/res/drawable/dialog_background.xml +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ <inset xmlns:android="http://schemas.android.com/apk/res/android"> <shape android:shape="rectangle"> <corners android:radius="?android:attr/dialogCornerRadius" /> <corners android:radius="@*android:dimen/config_dialogCornerRadius" /> <solid android:color="?android:attr/colorBackground" /> </shape> </inset>
packages/CompanionDeviceManager/res/values/themes.xml +3 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ <resources> <style name="ChooserActivity" parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"> parent="@style/Theme.AppCompat.Light.Dialog"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> <item name="*android:windowFixedHeightMajor">100%</item> <item name="*android:windowFixedHeightMinor">100%</item> <item name="android:windowBackground">@android:color/transparent</item> Loading
packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java +23 −10 Original line number Diff line number Diff line Loading @@ -22,8 +22,8 @@ import static android.companion.AssociationRequest.DEVICE_PROFILE_COMPUTER; import static android.companion.AssociationRequest.DEVICE_PROFILE_WATCH; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.SCAN_RESULTS_OBSERVABLE; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.TIMEOUT_OBSERVABLE; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT; import static com.android.companiondevicemanager.Utils.getApplicationLabel; import static com.android.companiondevicemanager.Utils.getHtmlFromResources; import static com.android.companiondevicemanager.Utils.prepareResultReceiverForIpc; Loading @@ -32,7 +32,6 @@ import static java.util.Objects.requireNonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; Loading @@ -50,7 +49,13 @@ import android.widget.Button; import android.widget.ListView; import android.widget.TextView; public class CompanionDeviceActivity extends Activity { import androidx.appcompat.app.AppCompatActivity; /** * A CompanionDevice activity response for showing the available * nearby devices to be associated with. */ public class CompanionDeviceActivity extends AppCompatActivity { private static final boolean DEBUG = false; private static final String TAG = CompanionDeviceActivity.class.getSimpleName(); Loading Loading @@ -126,7 +131,9 @@ public class CompanionDeviceActivity extends Activity { // Start discovery services if needed. if (!mRequest.isSelfManaged()) { CompanionDeviceDiscoveryService.startForRequest(this, mRequest); TIMEOUT_OBSERVABLE.addObserver((o, arg) -> cancel(true)); // TODO(b/217749191): Create the ViewModel for the LiveData CompanionDeviceDiscoveryService.getDiscoveryState().observe( /* LifeCycleOwner */ this, this::onDiscoveryStateChanged); } // Init UI. initUI(); Loading Loading @@ -158,10 +165,6 @@ public class CompanionDeviceActivity extends Activity { if (!isDone()) { cancel(false); // will finish() } TIMEOUT_OBSERVABLE.deleteObservers(); // mAdapter may also be observing - need to remove it. SCAN_RESULTS_OBSERVABLE.deleteObservers(); } @Override Loading Loading @@ -210,6 +213,13 @@ public class CompanionDeviceActivity extends Activity { } } private void onDiscoveryStateChanged(DiscoveryState newState) { if (newState == FINISHED_TIMEOUT && CompanionDeviceDiscoveryService.getScanResult().getValue().isEmpty()) { cancel(true); } } private void onUserSelectedDevice(@NonNull DeviceFilterPair<?> selectedDevice) { if (mSelectedDevice != null) { if (DEBUG) Log.w(TAG, "Already selected."); Loading Loading @@ -380,9 +390,12 @@ public class CompanionDeviceActivity extends Activity { mSummary.setText(summary); mAdapter = new DeviceListAdapter(this); SCAN_RESULTS_OBSERVABLE.addObserver(mAdapter); // TODO: hide the list and show a spinner until a first device matching device is found. mListView.setAdapter(mAdapter); CompanionDeviceDiscoveryService.getScanResult().observe( /* lifecycleOwner */ this, /* observer */ mAdapter); // "Remove" consent button: users would need to click on the list item. mButtonAllow.setVisibility(View.GONE); Loading
packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java +35 −26 Original line number Diff line number Diff line Loading @@ -56,13 +56,18 @@ import android.os.SystemProperties; import android.text.TextUtils; import android.util.Log; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Observable; /** * A CompanionDevice service response for scanning nearby devices */ public class CompanionDeviceDiscoveryService extends Service { private static final boolean DEBUG = false; private static final String TAG = CompanionDeviceDiscoveryService.class.getSimpleName(); Loading @@ -78,12 +83,10 @@ public class CompanionDeviceDiscoveryService extends Service { "com.android.companiondevicemanager.action.ACTION_STOP_DISCOVERY"; private static final String EXTRA_ASSOCIATION_REQUEST = "association_request"; // TODO: replace with LiveData-s? static final Observable TIMEOUT_OBSERVABLE = new MyObservable(); static final Observable SCAN_RESULTS_OBSERVABLE = new MyObservable(); private static CompanionDeviceDiscoveryService sInstance; private static MutableLiveData<List<DeviceFilterPair<?>>> sScanResultsLiveData = new MutableLiveData<>(Collections.emptyList()); private static MutableLiveData<DiscoveryState> sStateLiveData = new MutableLiveData<>(DiscoveryState.NOT_STARTED); private BluetoothManager mBtManager; private BluetoothAdapter mBtAdapter; Loading @@ -100,12 +103,25 @@ public class CompanionDeviceDiscoveryService extends Service { private final Runnable mTimeoutRunnable = this::timeout; /** * A state enum for devices' discovery. */ enum DiscoveryState { NOT_STARTED, STARTING, DISCOVERY_IN_PROGRESS, FINISHED_STOPPED, FINISHED_TIMEOUT } static void startForRequest( @NonNull Context context, @NonNull AssociationRequest associationRequest) { requireNonNull(associationRequest); final Intent intent = new Intent(context, CompanionDeviceDiscoveryService.class); intent.setAction(ACTION_START_DISCOVERY); intent.putExtra(EXTRA_ASSOCIATION_REQUEST, associationRequest); sStateLiveData.setValue(DiscoveryState.STARTING); context.startService(intent); } Loading @@ -115,10 +131,12 @@ public class CompanionDeviceDiscoveryService extends Service { context.startService(intent); } @MainThread static @NonNull List<DeviceFilterPair<?>> getScanResults() { return sInstance != null ? new ArrayList<>(sInstance.mDevicesFound) : Collections.emptyList(); static LiveData<List<DeviceFilterPair<?>>> getScanResult() { return sScanResultsLiveData; } static LiveData<DiscoveryState> getDiscoveryState() { return sStateLiveData; } @Override Loading @@ -126,8 +144,6 @@ public class CompanionDeviceDiscoveryService extends Service { super.onCreate(); if (DEBUG) Log.d(TAG, "onCreate()"); sInstance = this; mBtManager = getSystemService(BluetoothManager.class); mBtAdapter = mBtManager.getAdapter(); mBleScanner = mBtAdapter.getBluetoothLeScanner(); Loading @@ -148,6 +164,7 @@ public class CompanionDeviceDiscoveryService extends Service { case ACTION_STOP_DISCOVERY: stopDiscoveryAndFinish(); sStateLiveData.setValue(DiscoveryState.FINISHED_STOPPED); break; } return START_NOT_STICKY; Loading @@ -157,8 +174,6 @@ public class CompanionDeviceDiscoveryService extends Service { public void onDestroy() { super.onDestroy(); if (DEBUG) Log.d(TAG, "onDestroy()"); sInstance = null; } @MainThread Loading @@ -168,6 +183,8 @@ public class CompanionDeviceDiscoveryService extends Service { if (mDiscoveryStarted) throw new RuntimeException("Discovery in progress."); mDiscoveryStarted = true; sStateLiveData.setValue(DiscoveryState.DISCOVERY_IN_PROGRESS); sScanResultsLiveData.setValue(Collections.emptyList()); final List<DeviceFilter<?>> allFilters = request.getDeviceFilters(); final List<BluetoothDeviceFilter> btFilters = Loading Loading @@ -329,7 +346,7 @@ public class CompanionDeviceDiscoveryService extends Service { // First: make change. mDevicesFound.add(device); // Then: notify observers. SCAN_RESULTS_OBSERVABLE.notifyObservers(); sScanResultsLiveData.setValue(mDevicesFound); }); } Loading @@ -340,7 +357,7 @@ public class CompanionDeviceDiscoveryService extends Service { // First: make change. mDevicesFound.remove(device); // Then: notify observers. SCAN_RESULTS_OBSERVABLE.notifyObservers(); sScanResultsLiveData.setValue(mDevicesFound); }); } Loading @@ -362,7 +379,7 @@ public class CompanionDeviceDiscoveryService extends Service { private void timeout() { if (DEBUG) Log.i(TAG, "timeout()"); stopDiscoveryAndFinish(); TIMEOUT_OBSERVABLE.notifyObservers(); sStateLiveData.setValue(DiscoveryState.FINISHED_TIMEOUT); } @Override Loading Loading @@ -470,12 +487,4 @@ public class CompanionDeviceDiscoveryService extends Service { } return result; } private static class MyObservable extends Observable { @Override public void notifyObservers() { setChanged(); super.notifyObservers(); } } }