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

Commit 1d1fa857 authored by Diya Bera's avatar Diya Bera Committed by Android (Google) Code Review
Browse files

Merge "[3/N] Add a default implementation for ProximityProviderService" into main

parents d48354a5 04c981c8
Loading
Loading
Loading
Loading
+74 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.proximity;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.ICancellationSignal;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.R;

/**
 * Default implementation for {@link IProximityProviderService}.
 *
 * The implementation can be changed by providing a different service.
 *
 * <service android:name="{SERVICE_NAME}"
 *   android:exported="true">
 *   <intent-filter>
 *      <action android:name="android.proximity.ProximityProviderService" />
 *   </intent-filter>
 * </service>
 *
 * An overlay needs to overwrite the following strings in
 * frameworks/base/core/res/res/values/config.xml:
 *{@link R.string.proximity_provider_service_package_name} should represent the package name of
 * where the service is declared.
 * {@link R.string.proximity_provider_service_class_name} should represent the class name.
 *
 * @hide
 */
public class DefaultProximityProviderService extends Service {
    private static final IProximityProviderService.Stub sProximityProviderServiceImpl =
            new IProximityProviderService.Stub() {
                @Override
                public synchronized ICancellationSignal anyWatchNearby(RangingParams params,
                        IProximityResultCallback callback) {
                    return null;
                }

                @Override
                public boolean isProximityCheckingSupported() {
                    return false;
                }

                @Override
                public int isProximityCheckingAvailable() {
                    return ProximityResultCode.NO_ASSOCIATED_DEVICE;
                }
            };

    @Nullable
    @Override
    public IBinder onBind(@NonNull Intent intent) {
        return sProximityProviderServiceImpl;
    }
}
+4 −2
Original line number Diff line number Diff line
@@ -29,8 +29,10 @@ interface IProximityProviderService {
    /**
     * Finds nearby watch paired to this phone. If the watch is not found within the
     * specified timeout, the callback is called with result set to NO_RANGING_RESULT.
     * If timeout is <= 0, it will use a default timeout of 5 seconds. Returns an integer
     * handle identifying the ranging session.
     * If timeout is <= 0, it will use a default timeout of 5 seconds.
     *
     * Returns a cancellation signal associated with the watch ranging operation.
     * The cancellation signal can be null if watch ranging does not start.
     */
    ICancellationSignal anyWatchNearby(
            in RangingParams params, in IProximityResultCallback callback);
+7 −0
Original line number Diff line number Diff line
@@ -9671,6 +9671,13 @@
            android:permission="android.permission.LOCATION_HARDWARE"
            android:exported="false" />
        <service android:name="android.proximity.DefaultProximityProviderService"
            android:exported="false">
            <intent-filter>
                <action android:name="android.proximity.ProximityProviderService" />
            </intent-filter>
        </service>
        <service android:name="com.android.server.MountServiceIdler"
                 android:exported="true"
                 android:permission="android.permission.BIND_JOB_SERVICE" >
+2 −2
Original line number Diff line number Diff line
@@ -7605,7 +7605,7 @@
    <bool name="config_enableMaterialDesignInPackageInstaller">true</bool>

    <!-- Package and class info to bind to ProximityProviderService -->
    <string name="proximity_provider_service_package_name" translatable="false"></string>
    <string name="proximity_provider_service_class_name" translatable="false"></string>
    <string name="proximity_provider_service_package_name" translatable="false">android</string>
    <string name="proximity_provider_service_class_name" translatable="false">android.proximity.DefaultProximityProviderService</string>

</resources>
+73 −46
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.RemoteException;
@@ -35,6 +37,7 @@ import androidx.annotation.NonNull;
import com.android.internal.R;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.biometrics.BiometricHandlerProvider;

import java.util.function.Function;

@@ -52,13 +55,15 @@ public class WatchRangingService implements WatchRangingServiceInternal {
    private final String mProximityProviderServicePackageName;
    private final String mProximityProviderServiceClassName;
    private final Function<IBinder, IProximityProviderService> mProximityProviderServiceFunction;
    private final Handler mHandler;
    private ServiceConnection mProximityProviderServiceConnection;
    private CancellationSignalForWatchRanging mCancellationSignalForWatchRanging;
    private IProximityProviderService mProximityProviderService;

    WatchRangingService(@NonNull Context context, @NonNull Function<IBinder,
            IProximityProviderService> proximityProviderServiceFunction) {
            IProximityProviderService> proximityProviderServiceFunction, @NonNull Handler handler) {
        mContext = context;
        mHandler = handler;
        mProximityProviderServiceFunction = proximityProviderServiceFunction;
        mProximityProviderServicePackageName = mContext.getString(
                R.string.proximity_provider_service_package_name);
@@ -73,15 +78,18 @@ public class WatchRangingService implements WatchRangingServiceInternal {
     * @param proximityResultCallback callback to receive watch ranging results
     */
    @Override
    public synchronized void startWatchRangingForIdentityCheck(long authenticationRequestId,
    public void startWatchRangingForIdentityCheck(long authenticationRequestId,
            @NonNull IProximityResultCallback proximityResultCallback) {
        mHandler.post(() -> {
            if (mCancellationSignalForWatchRanging == null) {
                bindAndStartWatchRanging(authenticationRequestId, proximityResultCallback);
            } else {
            Slog.e(TAG, "Watch ranging requested but previous request was not cancelled");
                Slog.e(TAG, "Watch ranging requested but previous request was not cancelled."
                        + "This is a bug.");
                cancelWatchRangingForRequestId(0 /* authenticationRequestId */);
                bindAndStartWatchRanging(authenticationRequestId, proximityResultCallback);
            }
        });
    }

    /**
@@ -90,7 +98,8 @@ public class WatchRangingService implements WatchRangingServiceInternal {
     * @param authenticationRequestId request id for authentication session
     */
    @Override
    public synchronized void cancelWatchRangingForRequestId(long authenticationRequestId) {
    public void cancelWatchRangingForRequestId(long authenticationRequestId) {
        mHandler.post(() -> {
            if (mCancellationSignalForWatchRanging != null) {
                final long currentAuthenticationRequestId =
                        mCancellationSignalForWatchRanging.getAuthenticationRequestId();
@@ -103,16 +112,21 @@ public class WatchRangingService implements WatchRangingServiceInternal {
                        Slog.d(TAG, "Couldn't cancel watch ranging " + e);
                    }
                    mCancellationSignalForWatchRanging = null;
                if (mProximityProviderServiceConnection != null) {
                    mContext.unbindService(mProximityProviderServiceConnection);
                    mProximityProviderServiceConnection = null;
                }
                mProximityProviderService = null;
                    unbindProximityProviderService();
                } else {
                    Slog.e(TAG, "Watch ranging cancellation requested "
                            + "but auth request ID does not match");
                }
            }
        });
    }

    private void unbindProximityProviderService() {
        if (mProximityProviderServiceConnection != null) {
            mContext.unbindService(mProximityProviderServiceConnection);
            mProximityProviderServiceConnection = null;
        }
        mProximityProviderService = null;
    }

    private void start() {
@@ -127,6 +141,7 @@ public class WatchRangingService implements WatchRangingServiceInternal {
            public void onServiceConnected(ComponentName name, IBinder service) {
                if (service == null) {
                    Slog.d(TAG, "No service found for proximity provider.");
                    onError(proximityResultCallback, ProximityResultCode.NO_ASSOCIATED_DEVICE);
                    return;
                }
                mProximityProviderService = mProximityProviderServiceFunction.apply(service);
@@ -136,19 +151,19 @@ public class WatchRangingService implements WatchRangingServiceInternal {
                }
                final ICancellationSignal cancellationSignal =
                        anyWatchNearby(mProximityProviderService, proximityResultCallback);
                if (cancellationSignal != null) {
                    mCancellationSignalForWatchRanging = new CancellationSignalForWatchRanging(
                            authenticationRequestId, cancellationSignal);
                } else {
                    onError(proximityResultCallback, ProximityResultCode.NO_ASSOCIATED_DEVICE);
                    unbindProximityProviderService();
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                try {
                Slog.e(TAG, "Proximity provider service disconnected");
                    proximityResultCallback.onError(ProximityResultCode.NO_RANGING_RESULT);
                } catch (RemoteException e) {
                    Slog.e(TAG, "Remote exception thrown when trying to invoke"
                            + " proximity result callback.");
                }
                onError(proximityResultCallback, ProximityResultCode.NO_RANGING_RESULT);
            }
        };

@@ -156,22 +171,33 @@ public class WatchRangingService implements WatchRangingServiceInternal {
                .setClassName(mProximityProviderServicePackageName,
                        mProximityProviderServiceClassName);
        final boolean bindSuccessful =
                mContext.bindService(intent, mProximityProviderServiceConnection,
                        Context.BIND_IMPORTANT | Context.BIND_AUTO_CREATE);
                mContext.bindService(intent,
                        Context.BIND_IMPORTANT | Context.BIND_AUTO_CREATE /* flags */,
                        new HandlerExecutor(mHandler),
                        mProximityProviderServiceConnection);

        if (!bindSuccessful) {
            Slog.d(TAG, "Couldn't find service for ProximityProviderService");
            onError(proximityResultCallback, ProximityResultCode.NO_ASSOCIATED_DEVICE);
        }
    }

    private void onError(IProximityResultCallback proximityResultCallback,
            @ProximityResultCode int errorCode) {
        try {
            proximityResultCallback.onError(errorCode);
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception thrown when trying to invoke"
                    + " proximity result callback. Error code: " + errorCode);
        }
    }

    private ICancellationSignal anyWatchNearby(
            IProximityProviderService proximityProviderService,
    private ICancellationSignal anyWatchNearby(IProximityProviderService proximityProviderService,
            IProximityResultCallback proximityResultCallback) {
        final RangingParams rangingParams = new RangingParams.Builder()
                .build();
        try {
            return proximityProviderService.anyWatchNearby(rangingParams,
                    proximityResultCallback);
            return proximityProviderService.anyWatchNearby(rangingParams, proximityResultCallback);
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception thrown when trying to start watch ranging " + e);
        }
@@ -187,7 +213,8 @@ public class WatchRangingService implements WatchRangingServiceInternal {
        public Lifecycle(@android.annotation.NonNull Context context) {
            super(context);
            mService = new WatchRangingService(context, (service) ->
                    IProximityProviderService.Stub.asInterface(Binder.allowBlocking(service)));
                    IProximityProviderService.Stub.asInterface(Binder.allowBlocking(service)),
                    BiometricHandlerProvider.getInstance().getBiometricCallbackHandler());
        }

        @Override
@@ -203,7 +230,7 @@ public class WatchRangingService implements WatchRangingServiceInternal {
        private final ICancellationSignal mCancellationSignal;

        CancellationSignalForWatchRanging(long authenticationRequestId,
                ICancellationSignal cancellationSignal) {
                @NonNull ICancellationSignal cancellationSignal) {
            mAuthenticationRequestId = authenticationRequestId;
            mCancellationSignal = cancellationSignal;
        }
Loading