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

Commit 39255ff4 authored by Evan Chen's avatar Evan Chen Committed by Android (Google) Code Review
Browse files

Merge "Introduce CDM device presence base on UUID" into main

parents 628f3935 1ea0411b
Loading
Loading
Loading
Loading
+36 −7
Original line number Diff line number Diff line
@@ -274,6 +274,7 @@ package android {
    field public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
    field public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
    field public static final String REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE = "android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE";
    field @FlaggedApi("android.companion.flags.device_presence") public static final String REQUEST_OBSERVE_DEVICE_UUID_PRESENCE = "android.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE";
    field public static final String REQUEST_PASSWORD_COMPLEXITY = "android.permission.REQUEST_PASSWORD_COMPLEXITY";
    field @Deprecated public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
    field public static final String RUN_USER_INITIATED_JOBS = "android.permission.RUN_USER_INITIATED_JOBS";
@@ -9696,8 +9697,10 @@ package android.companion {
    method public void requestNotificationAccess(android.content.ComponentName);
    method @FlaggedApi("android.companion.association_tag") public void setAssociationTag(int, @NonNull String);
    method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
    method @FlaggedApi("android.companion.device_presence") @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull android.companion.ObservingDevicePresenceRequest);
    method public void startSystemDataTransfer(int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.companion.CompanionException>) throws android.companion.DeviceNotAssociatedException;
    method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
    method @FlaggedApi("android.companion.device_presence") @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull android.companion.ObservingDevicePresenceRequest);
    field public static final String EXTRA_ASSOCIATION = "android.companion.extra.ASSOCIATION";
    field @Deprecated public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
    field public static final int FLAG_CALL_METADATA = 1; // 0x1
@@ -9725,13 +9728,7 @@ package android.companion {
    method @MainThread public void onDeviceAppeared(@NonNull android.companion.AssociationInfo);
    method @Deprecated @MainThread public void onDeviceDisappeared(@NonNull String);
    method @MainThread public void onDeviceDisappeared(@NonNull android.companion.AssociationInfo);
    method @FlaggedApi("android.companion.device_presence") @MainThread public void onDeviceEvent(@NonNull android.companion.AssociationInfo, int);
    field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BLE_APPEARED = 0; // 0x0
    field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BLE_DISAPPEARED = 1; // 0x1
    field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BT_CONNECTED = 2; // 0x2
    field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BT_DISCONNECTED = 3; // 0x3
    field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_SELF_MANAGED_APPEARED = 4; // 0x4
    field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_SELF_MANAGED_DISAPPEARED = 5; // 0x5
    method @FlaggedApi("android.companion.device_presence") @MainThread public void onDevicePresenceEvent(@NonNull android.companion.DevicePresenceEvent);
    field public static final String SERVICE_INTERFACE = "android.companion.CompanionDeviceService";
  }
@@ -9744,6 +9741,38 @@ package android.companion {
  public class DeviceNotAssociatedException extends java.lang.RuntimeException {
  }
  @FlaggedApi("android.companion.device_presence") public final class DevicePresenceEvent implements android.os.Parcelable {
    ctor public DevicePresenceEvent(int, int, @Nullable android.os.ParcelUuid);
    method public int describeContents();
    method public int getAssociationId();
    method public int getEvent();
    method @Nullable public android.os.ParcelUuid getUuid();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.companion.DevicePresenceEvent> CREATOR;
    field public static final int EVENT_BLE_APPEARED = 0; // 0x0
    field public static final int EVENT_BLE_DISAPPEARED = 1; // 0x1
    field public static final int EVENT_BT_CONNECTED = 2; // 0x2
    field public static final int EVENT_BT_DISCONNECTED = 3; // 0x3
    field public static final int EVENT_SELF_MANAGED_APPEARED = 4; // 0x4
    field public static final int EVENT_SELF_MANAGED_DISAPPEARED = 5; // 0x5
    field public static final int NO_ASSOCIATION = -1; // 0xffffffff
  }
  @FlaggedApi("android.companion.device_presence") public final class ObservingDevicePresenceRequest implements android.os.Parcelable {
    method public int describeContents();
    method public int getAssociationId();
    method @Nullable public android.os.ParcelUuid getUuid();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.companion.ObservingDevicePresenceRequest> CREATOR;
  }
  public static final class ObservingDevicePresenceRequest.Builder {
    ctor public ObservingDevicePresenceRequest.Builder();
    method @NonNull public android.companion.ObservingDevicePresenceRequest build();
    method @NonNull public android.companion.ObservingDevicePresenceRequest.Builder setAssociationId(int);
    method @NonNull @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE) public android.companion.ObservingDevicePresenceRequest.Builder setUuid(@NonNull android.os.ParcelUuid);
  }
  public final class WifiDeviceFilter implements android.companion.DeviceFilter<android.net.wifi.ScanResult> {
    method public int describeContents();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
+60 −1
Original line number Diff line number Diff line
@@ -1038,6 +1038,7 @@ public final class CompanionDeviceManager {
        }
    }

    // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut.
    /**
     * Register to receive callbacks whenever the associated device comes in and out of range.
     *
@@ -1094,7 +1095,7 @@ public final class CompanionDeviceManager {
                            callingUid, callingPid);
        }
    }

    // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut.
    /**
     * Unregister for receiving callbacks whenever the associated device comes in and out of range.
     *
@@ -1136,6 +1137,64 @@ public final class CompanionDeviceManager {
        }
    }

    /**
     * Register to receive callbacks whenever the associated device comes in and out of range.
     *
     * <p>The app doesn't need to remain running in order to receive its callbacks.</p>
     *
     * <p>Calling app must check for feature presence of
     * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} before calling this API.</p>
     *
     * <p>For Bluetooth LE devices, this is based on scanning for device with the given address.
     * The system will scan for the device when Bluetooth is ON or Bluetooth scanning is ON.</p>
     *
     * <p>For Bluetooth classic devices this is triggered when the device connects/disconnects.</p>
     *
     * <p>WiFi devices are not supported.</p>
     *
     * <p>If a Bluetooth LE device wants to use a rotating mac address, it is recommended to use
     * Resolvable Private Address, and ensure the device is bonded to the phone so that android OS
     * is able to resolve the address.</p>
     *
     * @param request A request for setting the types of device for observing device presence.
     *
     * @see ObservingDevicePresenceRequest.Builder
     * @see CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)
     */
    @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
    @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE)
    public void startObservingDevicePresence(@NonNull ObservingDevicePresenceRequest request) {
        Objects.requireNonNull(request, "request cannot be null");

        try {
            mService.startObservingDevicePresence(
                    request, mContext.getOpPackageName(), mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Unregister for receiving callbacks whenever the associated device comes in and out of range.
     *
     * Calling app must check for feature presence of
     * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} before calling this API.
     *
     * @param request A request for setting the types of device for observing device presence.
     */
    @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
    @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE)
    public void stopObservingDevicePresence(@NonNull ObservingDevicePresenceRequest request) {
        Objects.requireNonNull(request, "request cannot be null");

        try {
            mService.stopObservingDevicePresence(
                    request, mContext.getOpPackageName(), mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Dispatch a message to system for processing. It should only be called by
     * {@link CompanionDeviceService#dispatchMessageToSystem(int, int, byte[])}
+9 −79
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@
package android.companion;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -33,8 +32,6 @@ import android.util.Log;

import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
import java.util.concurrent.Executor;

@@ -123,62 +120,6 @@ public abstract class CompanionDeviceService extends Service {
     */
    public static final String SERVICE_INTERFACE = "android.companion.CompanionDeviceService";

    /** @hide */
    @IntDef(prefix = {"DEVICE_EVENT"}, value = {
            DEVICE_EVENT_BLE_APPEARED,
            DEVICE_EVENT_BLE_DISAPPEARED,
            DEVICE_EVENT_BT_CONNECTED,
            DEVICE_EVENT_BT_DISCONNECTED,
            DEVICE_EVENT_SELF_MANAGED_APPEARED,
            DEVICE_EVENT_SELF_MANAGED_DISAPPEARED
    })

    @Retention(RetentionPolicy.SOURCE)
    public @interface DeviceEvent {}

    /**
     * Companion app receives {@link #onDeviceEvent(AssociationInfo, int)} callback
     * with this event if the device comes into BLE range.
     */
    @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
    public static final int DEVICE_EVENT_BLE_APPEARED = 0;

    /**
     * Companion app receives {@link #onDeviceEvent(AssociationInfo, int)} callback
     * with this event if the device is no longer in BLE range.
     */
    @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
    public static final int DEVICE_EVENT_BLE_DISAPPEARED = 1;

    /**
     * Companion app receives {@link #onDeviceEvent(AssociationInfo, int)} callback
     * with this event when the bluetooth device is connected.
     */
    @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
    public static final int DEVICE_EVENT_BT_CONNECTED = 2;

    /**
     * Companion app receives {@link #onDeviceEvent(AssociationInfo, int)} callback
     * with this event if the bluetooth device is disconnected.
     */
    @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
    public static final int DEVICE_EVENT_BT_DISCONNECTED = 3;

    /**
     * A companion app for a self-managed device will receive the callback
     * {@link #onDeviceEvent(AssociationInfo, int)} if it reports that a device has appeared on its
     * own.
     */
    @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
    public static final int DEVICE_EVENT_SELF_MANAGED_APPEARED = 4;

    /**
     * A companion app for a self-managed device will receive the callback
     * {@link #onDeviceEvent(AssociationInfo, int)} if it reports that a device has disappeared on
     * its own.
     */
    @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
    public static final int DEVICE_EVENT_SELF_MANAGED_DISAPPEARED = 5;

    private final Stub mRemote = new Stub();

@@ -306,6 +247,7 @@ public abstract class CompanionDeviceService extends Service {
                .detachSystemDataTransport(associationId);
    }

    // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut.
    /**
     * Called by system whenever a device associated with this app is connected.
     *
@@ -318,6 +260,7 @@ public abstract class CompanionDeviceService extends Service {
        }
    }

    // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut.
    /**
     * Called by system whenever a device associated with this app is disconnected.
     *
@@ -333,25 +276,11 @@ public abstract class CompanionDeviceService extends Service {
    /**
     * Called by the system during device events.
     *
     *  <p>E.g. Event {@link #DEVICE_EVENT_BLE_APPEARED} will be called when the associated
     *  companion device comes into BLE range.
     *  <p>Event {@link #DEVICE_EVENT_BLE_DISAPPEARED} will be called when the associated
     *  companion device is no longer in BLE range.
     *  <p> Event {@link #DEVICE_EVENT_BT_CONNECTED} will be called when the associated
     *  companion device is connected.
     *  <p>Event {@link #DEVICE_EVENT_BT_DISCONNECTED} will be called when the associated
     *  companion device is disconnected.
     *  Note that app must receive {@link #DEVICE_EVENT_BLE_APPEARED} first before
     *  {@link #DEVICE_EVENT_BLE_DISAPPEARED} and {@link #DEVICE_EVENT_BT_CONNECTED}
     *  before {@link #DEVICE_EVENT_BT_DISCONNECTED}.
     *
     * @param associationInfo A record for the companion device.
     * @param event Associated companion device's event.
     * @see CompanionDeviceManager#startObservingDevicePresence(ObservingDevicePresenceRequest)
     */
    @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
    @MainThread
    public void onDeviceEvent(@NonNull AssociationInfo associationInfo,
            @DeviceEvent int event) {
    public void onDevicePresenceEvent(@NonNull DevicePresenceEvent event) {
        // Do nothing. Companion apps can override this function.
    }

@@ -390,9 +319,10 @@ public abstract class CompanionDeviceService extends Service {
        }

        @Override
        public void onDeviceEvent(AssociationInfo associationInfo, int event) {
            mMainHandler.postAtFrontOfQueue(
                    () -> mService.onDeviceEvent(associationInfo, event));
        public void onDevicePresenceEvent(DevicePresenceEvent event) {
            if (Flags.devicePresence()) {
                mMainHandler.postAtFrontOfQueue(() -> mService.onDevicePresenceEvent(event));
            }
        }
    }
}
+19 −0
Original line number Diff line number Diff line
 /*
  * Copyright (C) 2024 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 android.companion;

 parcelable DevicePresenceEvent;
+218 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 android.companion;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;

/**
 * Event for observing device presence.
 *
 * @see CompanionDeviceManager#startObservingDevicePresence(ObservingDevicePresenceRequest)
 * @see ObservingDevicePresenceRequest.Builder#setUuid(ParcelUuid)
 * @see ObservingDevicePresenceRequest.Builder#setAssociationId(int)
 */
@FlaggedApi(Flags.FLAG_DEVICE_PRESENCE)
public final class DevicePresenceEvent implements Parcelable {

    /** @hide */
    @IntDef(prefix = {"EVENT"}, value = {
            EVENT_BLE_APPEARED,
            EVENT_BLE_DISAPPEARED,
            EVENT_BT_CONNECTED,
            EVENT_BT_DISCONNECTED,
            EVENT_SELF_MANAGED_APPEARED,
            EVENT_SELF_MANAGED_DISAPPEARED
    })

    @Retention(RetentionPolicy.SOURCE)
    public @interface Event {}

    /**
     * Indicate observing device presence base on the ParcelUuid but not association id.
     */
    public static final int NO_ASSOCIATION = -1;

    /**
     * Companion app receives
     * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} callback
     * with this event if the device comes into BLE range.
     */
    public static final int EVENT_BLE_APPEARED = 0;

    /**
     * Companion app receives
     * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} callback
     * with this event if the device is no longer in BLE range.
     */
    public static final int EVENT_BLE_DISAPPEARED = 1;

    /**
     * Companion app receives
     * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} callback
     * with this event when the bluetooth device is connected.
     */
    public static final int EVENT_BT_CONNECTED = 2;

    /**
     * Companion app receives
     * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} callback
     * with this event if the bluetooth device is disconnected.
     */
    public static final int EVENT_BT_DISCONNECTED = 3;

    /**
     * A companion app for a self-managed device will receive the callback
     * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)}
     * if it reports that a device has appeared on its
     * own.
     */
    public static final int EVENT_SELF_MANAGED_APPEARED = 4;

    /**
     * A companion app for a self-managed device will receive the callback
     * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} if it reports
     * that a device has disappeared on its own.
     */
    public static final int EVENT_SELF_MANAGED_DISAPPEARED = 5;
    private final int mAssociationId;
    private final int mEvent;
    @Nullable
    private final ParcelUuid mUuid;

    private static final int PARCEL_UUID_NULL = 0;

    private static final int PARCEL_UUID_NOT_NULL = 1;

    /**
     * Create a new DevicePresenceEvent.
     */
    public DevicePresenceEvent(
            int associationId, @Event int event, @Nullable ParcelUuid uuid) {
        mAssociationId = associationId;
        mEvent = event;
        mUuid = uuid;
    }

    /**
     * @return The association id has been used to observe device presence.
     *
     * Caller will receive the valid association id if only if using
     * {@link ObservingDevicePresenceRequest.Builder#setAssociationId(int)}, otherwise
     * return {@link #NO_ASSOCIATION}.
     *
     * @see ObservingDevicePresenceRequest.Builder#setAssociationId(int)
     */
    public int getAssociationId() {
        return mAssociationId;
    }

    /**
     * @return Associated companion device's event.
     */
    public int getEvent() {
        return mEvent;
    }

    /**
     * @return The ParcelUuid has been used to observe device presence.
     *
     * Caller will receive the ParcelUuid if only if using
     * {@link ObservingDevicePresenceRequest.Builder#setUuid(ParcelUuid)}, otherwise return null.
     *
     * @see ObservingDevicePresenceRequest.Builder#setUuid(ParcelUuid)
     */

    @Nullable
    public ParcelUuid getUuid() {
        return mUuid;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mAssociationId);
        dest.writeInt(mEvent);
        if (mUuid == null) {
            // Write 0 to the parcel to indicate the ParcelUuid is null.
            dest.writeInt(PARCEL_UUID_NULL);
        } else {
            dest.writeInt(PARCEL_UUID_NOT_NULL);
            mUuid.writeToParcel(dest, flags);
        }
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (this == o) return true;
        if (!(o instanceof DevicePresenceEvent that)) return false;

        return Objects.equals(mUuid, that.mUuid)
                && mAssociationId == that.mAssociationId
                && mEvent == that.mEvent;
    }

    @Override
    public String toString() {
        return "ObservingDevicePresenceResult { "
                + "Association Id= " + mAssociationId + ","
                + "ParcelUuid= " + mUuid + ","
                + "Event= " + mEvent + "}";
    }

    @Override
    public int hashCode() {
        return Objects.hash(mAssociationId, mEvent, mUuid);
    }

    @NonNull
    public static final Parcelable.Creator<DevicePresenceEvent> CREATOR =
            new Parcelable.Creator<DevicePresenceEvent>() {
                @Override
                public DevicePresenceEvent[] newArray(int size) {
                    return new DevicePresenceEvent[size];
                }

                @Override
                public DevicePresenceEvent createFromParcel(@NonNull Parcel in) {
                    return new DevicePresenceEvent(in);
                }
            };

    private DevicePresenceEvent(@NonNull Parcel in) {
        mAssociationId = in.readInt();
        mEvent = in.readInt();
        if (in.readInt() == PARCEL_UUID_NULL) {
            mUuid = null;
        } else {
            mUuid = ParcelUuid.CREATOR.createFromParcel(in);
        }
    }
}
Loading