Loading core/java/android/proximity/DefaultProximityProviderService.java 0 → 100644 +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; } } core/java/android/proximity/IProximityProviderService.aidl +4 −2 Original line number Diff line number Diff line Loading @@ -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); Loading core/res/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -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" > Loading core/res/res/values/config.xml +2 −2 Original line number Diff line number Diff line Loading @@ -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> services/core/java/com/android/server/security/authenticationpolicy/WatchRangingService.java +73 −46 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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); Loading @@ -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); } }); } /** Loading @@ -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(); Loading @@ -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() { Loading @@ -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); Loading @@ -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); } }; Loading @@ -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); } Loading @@ -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 Loading @@ -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 Loading
core/java/android/proximity/DefaultProximityProviderService.java 0 → 100644 +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; } }
core/java/android/proximity/IProximityProviderService.aidl +4 −2 Original line number Diff line number Diff line Loading @@ -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); Loading
core/res/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -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" > Loading
core/res/res/values/config.xml +2 −2 Original line number Diff line number Diff line Loading @@ -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>
services/core/java/com/android/server/security/authenticationpolicy/WatchRangingService.java +73 −46 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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); Loading @@ -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); } }); } /** Loading @@ -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(); Loading @@ -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() { Loading @@ -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); Loading @@ -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); } }; Loading @@ -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); } Loading @@ -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 Loading @@ -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