Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d343f9f7 authored by Evan Chen's avatar Evan Chen
Browse files

Introduce LiveData for CDM Activity and Discovery

Test: atest CtsCompanionDeviceManagerCoreTestCases
      atest CtsCompanionDeviceManagerUiAutomationTestCases
      atest CtsOsTestCases:CompanionDeviceManagerTest

Bug: 211722613
Change-Id: Icb84fe42cf02b1e0db4546fefee70afdd97ee7f3
parent 2be25975
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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,
}
+1 −1
Original line number Diff line number Diff line
@@ -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>
+3 −1
Original line number Diff line number Diff line
@@ -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>
+23 −10
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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();

@@ -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();
@@ -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
@@ -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.");
@@ -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);
+35 −26
Original line number Diff line number Diff line
@@ -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();
@@ -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;
@@ -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);
    }

@@ -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
@@ -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();
@@ -148,6 +164,7 @@ public class CompanionDeviceDiscoveryService extends Service {

            case ACTION_STOP_DISCOVERY:
                stopDiscoveryAndFinish();
                sStateLiveData.setValue(DiscoveryState.FINISHED_STOPPED);
                break;
        }
        return START_NOT_STICKY;
@@ -157,8 +174,6 @@ public class CompanionDeviceDiscoveryService extends Service {
    public void onDestroy() {
        super.onDestroy();
        if (DEBUG) Log.d(TAG, "onDestroy()");

        sInstance = null;
    }

    @MainThread
@@ -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 =
@@ -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);
        });
    }

@@ -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);
        });
    }

@@ -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
@@ -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