[go: nahoru, domu]

wearos-whs: Add ExerciseTypeConfig definitions and UpdateExerciseRequest impl

1. Add ExerciseTypeConfig definitions
Main changes based on aosp/2172806:
- Rename DynamicExerciseConfig to be ExerciseTypeConfig
- Removed autopause from ExerciseTypeConfig
- Removed builder from ExerciseTypeConfig
- Make ExerciseTypeConfig nullable in ExerciseConfig
- Added factory method createGolfExerciseTypeConfig to ExerciseTypeConfig and make ExerciseTypeConfig constructor private

2. Add updateExerciseTypeConfigForActiveExercise in
   IExerciseApiService.aidl, and bump up exerciseApiVersion
   1->3(considering in APK we're already using version 2)
- Add UpdateExerciseTypeConfigRequest definition as impl
- Implement in ExerciseClient and ServiceBackedExerciseClient

Relnote: add factory method to create golf place tracking info exercise type config
Test: ./gradlew :health:health-services-client:assemble --info
Test: ./gradlew :health:health-services-client:test
Change-Id: I4c539e1abde8e51e65dcc82e3495f202b10282ea
diff --git a/health/health-services-client/api/1.0.0-beta02.txt b/health/health-services-client/api/1.0.0-beta02.txt
index 590e802..d65cfd6 100644
--- a/health/health-services-client/api/1.0.0-beta02.txt
+++ b/health/health-services-client/api/1.0.0-beta02.txt
@@ -17,6 +17,7 @@
     method public void setUpdateCallback(androidx.health.services.client.ExerciseUpdateCallback callback);
     method public void setUpdateCallback(java.util.concurrent.Executor executor, androidx.health.services.client.ExerciseUpdateCallback callback);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> startExerciseAsync(androidx.health.services.client.data.ExerciseConfig configuration);
+    method public default com.google.common.util.concurrent.ListenableFuture<java.lang.Void> updateExerciseTypeConfigAsync(androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig);
   }
 
   public final class ExerciseClientExtensionKt {
@@ -33,6 +34,7 @@
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? removeGoalFromActiveExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseGoal<?> exerciseGoal, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? resumeExercise(androidx.health.services.client.ExerciseClient, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? startExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseConfig configuration, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
+    method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? updateExerciseTypeConfig(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
   }
 
   public interface ExerciseUpdateCallback {
@@ -308,12 +310,17 @@
   }
 
   public final class ExerciseConfig {
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters, optional androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled);
     method public static androidx.health.services.client.data.ExerciseConfig.Builder builder(androidx.health.services.client.data.ExerciseType exerciseType);
     method public java.util.Set<androidx.health.services.client.data.DataType<?,?>> getDataTypes();
     method public java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> getExerciseGoals();
     method public android.os.Bundle getExerciseParams();
     method public androidx.health.services.client.data.ExerciseType getExerciseType();
+    method public androidx.health.services.client.data.ExerciseTypeConfig? getExerciseTypeConfig();
     method public float getSwimmingPoolLengthMeters();
     method public boolean isAutoPauseAndResumeEnabled();
     method public boolean isGpsEnabled();
@@ -321,6 +328,7 @@
     property public final java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals;
     property public final android.os.Bundle exerciseParams;
     property public final androidx.health.services.client.data.ExerciseType exerciseType;
+    property public final androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig;
     property public final boolean isAutoPauseAndResumeEnabled;
     property public final boolean isGpsEnabled;
     property public final float swimmingPoolLengthMeters;
@@ -334,6 +342,7 @@
     method public androidx.health.services.client.data.ExerciseConfig.Builder setDataTypes(java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseGoals(java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseParams(android.os.Bundle exerciseParams);
+    method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseTypeConfig(androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsAutoPauseAndResumeEnabled(boolean isAutoPauseAndResumeEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsGpsEnabled(boolean isGpsEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setSwimmingPoolLengthMeters(float swimmingPoolLength);
@@ -556,6 +565,17 @@
     property public final boolean supportsAutoPauseAndResume;
   }
 
+  public final class ExerciseTypeConfig {
+    method public static androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+    method public int getGolfShotTrackingPlaceInfo();
+    property public final int golfShotTrackingPlaceInfo;
+    field public static final androidx.health.services.client.data.ExerciseTypeConfig.Companion Companion;
+  }
+
+  public static final class ExerciseTypeConfig.Companion {
+    method public androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+  }
+
   public final class ExerciseUpdate {
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
diff --git a/health/health-services-client/api/api_lint.ignore b/health/health-services-client/api/api_lint.ignore
index 4b2826d..844c583 100644
--- a/health/health-services-client/api/api_lint.ignore
+++ b/health/health-services-client/api/api_lint.ignore
@@ -1,4 +1,8 @@
 // Baseline format: 1.0
+DocumentExceptions: androidx.health.services.client.ExerciseClient#updateExerciseTypeConfigAsync(androidx.health.services.client.data.ExerciseTypeConfig):
+    Method ExerciseClient.updateExerciseTypeConfigAsync appears to be throwing kotlin.NotImplementedError; this should be listed in the documentation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions
+
+
 ExecutorRegistration: androidx.health.services.client.ExerciseClient#clearUpdateCallbackAsync(androidx.health.services.client.ExerciseUpdateCallback):
     Registration methods should have overload that accepts delivery Executor: `clearUpdateCallbackAsync`
 
@@ -7,8 +11,6 @@
     Invalid nullability on method `onBind` return. Overrides of unannotated super method cannot be Nullable.
 InvalidNullabilityOverride: androidx.health.services.client.PassiveListenerService#onBind(android.content.Intent) parameter #0:
     Invalid nullability on parameter `intent` in method `onBind`. Parameters of overrides cannot be NonNull if the super parameter is unannotated.
-InvalidNullabilityOverride: androidx.health.services.client.VersionApiService#onBind(android.content.Intent):
-    Invalid nullability on method `onBind` return. Overrides of unannotated super method cannot be Nullable.
 
 
 PairedRegistration: androidx.health.services.client.MeasureClient#registerMeasureCallback(androidx.health.services.client.data.DeltaDataType<?,?>, androidx.health.services.client.MeasureCallback):
diff --git a/health/health-services-client/api/current.txt b/health/health-services-client/api/current.txt
index 590e802..d65cfd6 100644
--- a/health/health-services-client/api/current.txt
+++ b/health/health-services-client/api/current.txt
@@ -17,6 +17,7 @@
     method public void setUpdateCallback(androidx.health.services.client.ExerciseUpdateCallback callback);
     method public void setUpdateCallback(java.util.concurrent.Executor executor, androidx.health.services.client.ExerciseUpdateCallback callback);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> startExerciseAsync(androidx.health.services.client.data.ExerciseConfig configuration);
+    method public default com.google.common.util.concurrent.ListenableFuture<java.lang.Void> updateExerciseTypeConfigAsync(androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig);
   }
 
   public final class ExerciseClientExtensionKt {
@@ -33,6 +34,7 @@
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? removeGoalFromActiveExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseGoal<?> exerciseGoal, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? resumeExercise(androidx.health.services.client.ExerciseClient, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? startExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseConfig configuration, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
+    method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? updateExerciseTypeConfig(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
   }
 
   public interface ExerciseUpdateCallback {
@@ -308,12 +310,17 @@
   }
 
   public final class ExerciseConfig {
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters, optional androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled);
     method public static androidx.health.services.client.data.ExerciseConfig.Builder builder(androidx.health.services.client.data.ExerciseType exerciseType);
     method public java.util.Set<androidx.health.services.client.data.DataType<?,?>> getDataTypes();
     method public java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> getExerciseGoals();
     method public android.os.Bundle getExerciseParams();
     method public androidx.health.services.client.data.ExerciseType getExerciseType();
+    method public androidx.health.services.client.data.ExerciseTypeConfig? getExerciseTypeConfig();
     method public float getSwimmingPoolLengthMeters();
     method public boolean isAutoPauseAndResumeEnabled();
     method public boolean isGpsEnabled();
@@ -321,6 +328,7 @@
     property public final java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals;
     property public final android.os.Bundle exerciseParams;
     property public final androidx.health.services.client.data.ExerciseType exerciseType;
+    property public final androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig;
     property public final boolean isAutoPauseAndResumeEnabled;
     property public final boolean isGpsEnabled;
     property public final float swimmingPoolLengthMeters;
@@ -334,6 +342,7 @@
     method public androidx.health.services.client.data.ExerciseConfig.Builder setDataTypes(java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseGoals(java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseParams(android.os.Bundle exerciseParams);
+    method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseTypeConfig(androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsAutoPauseAndResumeEnabled(boolean isAutoPauseAndResumeEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsGpsEnabled(boolean isGpsEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setSwimmingPoolLengthMeters(float swimmingPoolLength);
@@ -556,6 +565,17 @@
     property public final boolean supportsAutoPauseAndResume;
   }
 
+  public final class ExerciseTypeConfig {
+    method public static androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+    method public int getGolfShotTrackingPlaceInfo();
+    property public final int golfShotTrackingPlaceInfo;
+    field public static final androidx.health.services.client.data.ExerciseTypeConfig.Companion Companion;
+  }
+
+  public static final class ExerciseTypeConfig.Companion {
+    method public androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+  }
+
   public final class ExerciseUpdate {
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
diff --git a/health/health-services-client/api/public_plus_experimental_1.0.0-beta02.txt b/health/health-services-client/api/public_plus_experimental_1.0.0-beta02.txt
index 590e802..d65cfd6 100644
--- a/health/health-services-client/api/public_plus_experimental_1.0.0-beta02.txt
+++ b/health/health-services-client/api/public_plus_experimental_1.0.0-beta02.txt
@@ -17,6 +17,7 @@
     method public void setUpdateCallback(androidx.health.services.client.ExerciseUpdateCallback callback);
     method public void setUpdateCallback(java.util.concurrent.Executor executor, androidx.health.services.client.ExerciseUpdateCallback callback);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> startExerciseAsync(androidx.health.services.client.data.ExerciseConfig configuration);
+    method public default com.google.common.util.concurrent.ListenableFuture<java.lang.Void> updateExerciseTypeConfigAsync(androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig);
   }
 
   public final class ExerciseClientExtensionKt {
@@ -33,6 +34,7 @@
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? removeGoalFromActiveExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseGoal<?> exerciseGoal, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? resumeExercise(androidx.health.services.client.ExerciseClient, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? startExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseConfig configuration, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
+    method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? updateExerciseTypeConfig(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
   }
 
   public interface ExerciseUpdateCallback {
@@ -308,12 +310,17 @@
   }
 
   public final class ExerciseConfig {
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters, optional androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled);
     method public static androidx.health.services.client.data.ExerciseConfig.Builder builder(androidx.health.services.client.data.ExerciseType exerciseType);
     method public java.util.Set<androidx.health.services.client.data.DataType<?,?>> getDataTypes();
     method public java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> getExerciseGoals();
     method public android.os.Bundle getExerciseParams();
     method public androidx.health.services.client.data.ExerciseType getExerciseType();
+    method public androidx.health.services.client.data.ExerciseTypeConfig? getExerciseTypeConfig();
     method public float getSwimmingPoolLengthMeters();
     method public boolean isAutoPauseAndResumeEnabled();
     method public boolean isGpsEnabled();
@@ -321,6 +328,7 @@
     property public final java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals;
     property public final android.os.Bundle exerciseParams;
     property public final androidx.health.services.client.data.ExerciseType exerciseType;
+    property public final androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig;
     property public final boolean isAutoPauseAndResumeEnabled;
     property public final boolean isGpsEnabled;
     property public final float swimmingPoolLengthMeters;
@@ -334,6 +342,7 @@
     method public androidx.health.services.client.data.ExerciseConfig.Builder setDataTypes(java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseGoals(java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseParams(android.os.Bundle exerciseParams);
+    method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseTypeConfig(androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsAutoPauseAndResumeEnabled(boolean isAutoPauseAndResumeEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsGpsEnabled(boolean isGpsEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setSwimmingPoolLengthMeters(float swimmingPoolLength);
@@ -556,6 +565,17 @@
     property public final boolean supportsAutoPauseAndResume;
   }
 
+  public final class ExerciseTypeConfig {
+    method public static androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+    method public int getGolfShotTrackingPlaceInfo();
+    property public final int golfShotTrackingPlaceInfo;
+    field public static final androidx.health.services.client.data.ExerciseTypeConfig.Companion Companion;
+  }
+
+  public static final class ExerciseTypeConfig.Companion {
+    method public androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+  }
+
   public final class ExerciseUpdate {
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
diff --git a/health/health-services-client/api/public_plus_experimental_current.txt b/health/health-services-client/api/public_plus_experimental_current.txt
index 590e802..d65cfd6 100644
--- a/health/health-services-client/api/public_plus_experimental_current.txt
+++ b/health/health-services-client/api/public_plus_experimental_current.txt
@@ -17,6 +17,7 @@
     method public void setUpdateCallback(androidx.health.services.client.ExerciseUpdateCallback callback);
     method public void setUpdateCallback(java.util.concurrent.Executor executor, androidx.health.services.client.ExerciseUpdateCallback callback);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> startExerciseAsync(androidx.health.services.client.data.ExerciseConfig configuration);
+    method public default com.google.common.util.concurrent.ListenableFuture<java.lang.Void> updateExerciseTypeConfigAsync(androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig);
   }
 
   public final class ExerciseClientExtensionKt {
@@ -33,6 +34,7 @@
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? removeGoalFromActiveExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseGoal<?> exerciseGoal, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? resumeExercise(androidx.health.services.client.ExerciseClient, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? startExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseConfig configuration, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
+    method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? updateExerciseTypeConfig(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
   }
 
   public interface ExerciseUpdateCallback {
@@ -308,12 +310,17 @@
   }
 
   public final class ExerciseConfig {
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters, optional androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled);
     method public static androidx.health.services.client.data.ExerciseConfig.Builder builder(androidx.health.services.client.data.ExerciseType exerciseType);
     method public java.util.Set<androidx.health.services.client.data.DataType<?,?>> getDataTypes();
     method public java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> getExerciseGoals();
     method public android.os.Bundle getExerciseParams();
     method public androidx.health.services.client.data.ExerciseType getExerciseType();
+    method public androidx.health.services.client.data.ExerciseTypeConfig? getExerciseTypeConfig();
     method public float getSwimmingPoolLengthMeters();
     method public boolean isAutoPauseAndResumeEnabled();
     method public boolean isGpsEnabled();
@@ -321,6 +328,7 @@
     property public final java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals;
     property public final android.os.Bundle exerciseParams;
     property public final androidx.health.services.client.data.ExerciseType exerciseType;
+    property public final androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig;
     property public final boolean isAutoPauseAndResumeEnabled;
     property public final boolean isGpsEnabled;
     property public final float swimmingPoolLengthMeters;
@@ -334,6 +342,7 @@
     method public androidx.health.services.client.data.ExerciseConfig.Builder setDataTypes(java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseGoals(java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseParams(android.os.Bundle exerciseParams);
+    method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseTypeConfig(androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsAutoPauseAndResumeEnabled(boolean isAutoPauseAndResumeEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsGpsEnabled(boolean isGpsEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setSwimmingPoolLengthMeters(float swimmingPoolLength);
@@ -556,6 +565,17 @@
     property public final boolean supportsAutoPauseAndResume;
   }
 
+  public final class ExerciseTypeConfig {
+    method public static androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+    method public int getGolfShotTrackingPlaceInfo();
+    property public final int golfShotTrackingPlaceInfo;
+    field public static final androidx.health.services.client.data.ExerciseTypeConfig.Companion Companion;
+  }
+
+  public static final class ExerciseTypeConfig.Companion {
+    method public androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+  }
+
   public final class ExerciseUpdate {
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
diff --git a/health/health-services-client/api/restricted_1.0.0-beta02.txt b/health/health-services-client/api/restricted_1.0.0-beta02.txt
index 590e802..d65cfd6 100644
--- a/health/health-services-client/api/restricted_1.0.0-beta02.txt
+++ b/health/health-services-client/api/restricted_1.0.0-beta02.txt
@@ -17,6 +17,7 @@
     method public void setUpdateCallback(androidx.health.services.client.ExerciseUpdateCallback callback);
     method public void setUpdateCallback(java.util.concurrent.Executor executor, androidx.health.services.client.ExerciseUpdateCallback callback);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> startExerciseAsync(androidx.health.services.client.data.ExerciseConfig configuration);
+    method public default com.google.common.util.concurrent.ListenableFuture<java.lang.Void> updateExerciseTypeConfigAsync(androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig);
   }
 
   public final class ExerciseClientExtensionKt {
@@ -33,6 +34,7 @@
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? removeGoalFromActiveExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseGoal<?> exerciseGoal, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? resumeExercise(androidx.health.services.client.ExerciseClient, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? startExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseConfig configuration, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
+    method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? updateExerciseTypeConfig(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
   }
 
   public interface ExerciseUpdateCallback {
@@ -308,12 +310,17 @@
   }
 
   public final class ExerciseConfig {
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters, optional androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled);
     method public static androidx.health.services.client.data.ExerciseConfig.Builder builder(androidx.health.services.client.data.ExerciseType exerciseType);
     method public java.util.Set<androidx.health.services.client.data.DataType<?,?>> getDataTypes();
     method public java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> getExerciseGoals();
     method public android.os.Bundle getExerciseParams();
     method public androidx.health.services.client.data.ExerciseType getExerciseType();
+    method public androidx.health.services.client.data.ExerciseTypeConfig? getExerciseTypeConfig();
     method public float getSwimmingPoolLengthMeters();
     method public boolean isAutoPauseAndResumeEnabled();
     method public boolean isGpsEnabled();
@@ -321,6 +328,7 @@
     property public final java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals;
     property public final android.os.Bundle exerciseParams;
     property public final androidx.health.services.client.data.ExerciseType exerciseType;
+    property public final androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig;
     property public final boolean isAutoPauseAndResumeEnabled;
     property public final boolean isGpsEnabled;
     property public final float swimmingPoolLengthMeters;
@@ -334,6 +342,7 @@
     method public androidx.health.services.client.data.ExerciseConfig.Builder setDataTypes(java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseGoals(java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseParams(android.os.Bundle exerciseParams);
+    method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseTypeConfig(androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsAutoPauseAndResumeEnabled(boolean isAutoPauseAndResumeEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsGpsEnabled(boolean isGpsEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setSwimmingPoolLengthMeters(float swimmingPoolLength);
@@ -556,6 +565,17 @@
     property public final boolean supportsAutoPauseAndResume;
   }
 
+  public final class ExerciseTypeConfig {
+    method public static androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+    method public int getGolfShotTrackingPlaceInfo();
+    property public final int golfShotTrackingPlaceInfo;
+    field public static final androidx.health.services.client.data.ExerciseTypeConfig.Companion Companion;
+  }
+
+  public static final class ExerciseTypeConfig.Companion {
+    method public androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+  }
+
   public final class ExerciseUpdate {
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
diff --git a/health/health-services-client/api/restricted_current.txt b/health/health-services-client/api/restricted_current.txt
index 590e802..d65cfd6 100644
--- a/health/health-services-client/api/restricted_current.txt
+++ b/health/health-services-client/api/restricted_current.txt
@@ -17,6 +17,7 @@
     method public void setUpdateCallback(androidx.health.services.client.ExerciseUpdateCallback callback);
     method public void setUpdateCallback(java.util.concurrent.Executor executor, androidx.health.services.client.ExerciseUpdateCallback callback);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> startExerciseAsync(androidx.health.services.client.data.ExerciseConfig configuration);
+    method public default com.google.common.util.concurrent.ListenableFuture<java.lang.Void> updateExerciseTypeConfigAsync(androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig);
   }
 
   public final class ExerciseClientExtensionKt {
@@ -33,6 +34,7 @@
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? removeGoalFromActiveExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseGoal<?> exerciseGoal, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? resumeExercise(androidx.health.services.client.ExerciseClient, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? startExercise(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseConfig configuration, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
+    method @kotlin.jvm.Throws(exceptionClasses=android.os.RemoteException::class) public static suspend Object? updateExerciseTypeConfig(androidx.health.services.client.ExerciseClient, androidx.health.services.client.data.ExerciseTypeConfig exerciseTypeConfig, kotlin.coroutines.Continuation<? super java.lang.Void>) throws android.os.RemoteException;
   }
 
   public interface ExerciseUpdateCallback {
@@ -308,12 +310,17 @@
   }
 
   public final class ExerciseConfig {
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters, optional androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams, optional @FloatRange(from=0.0) float swimmingPoolLengthMeters);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals, optional android.os.Bundle exerciseParams);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled, optional java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
+    ctor public ExerciseConfig(androidx.health.services.client.data.ExerciseType exerciseType, java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes, boolean isAutoPauseAndResumeEnabled, boolean isGpsEnabled);
     method public static androidx.health.services.client.data.ExerciseConfig.Builder builder(androidx.health.services.client.data.ExerciseType exerciseType);
     method public java.util.Set<androidx.health.services.client.data.DataType<?,?>> getDataTypes();
     method public java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> getExerciseGoals();
     method public android.os.Bundle getExerciseParams();
     method public androidx.health.services.client.data.ExerciseType getExerciseType();
+    method public androidx.health.services.client.data.ExerciseTypeConfig? getExerciseTypeConfig();
     method public float getSwimmingPoolLengthMeters();
     method public boolean isAutoPauseAndResumeEnabled();
     method public boolean isGpsEnabled();
@@ -321,6 +328,7 @@
     property public final java.util.List<androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals;
     property public final android.os.Bundle exerciseParams;
     property public final androidx.health.services.client.data.ExerciseType exerciseType;
+    property public final androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig;
     property public final boolean isAutoPauseAndResumeEnabled;
     property public final boolean isGpsEnabled;
     property public final float swimmingPoolLengthMeters;
@@ -334,6 +342,7 @@
     method public androidx.health.services.client.data.ExerciseConfig.Builder setDataTypes(java.util.Set<? extends androidx.health.services.client.data.DataType<?,?>> dataTypes);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseGoals(java.util.List<? extends androidx.health.services.client.data.ExerciseGoal<?>> exerciseGoals);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseParams(android.os.Bundle exerciseParams);
+    method public androidx.health.services.client.data.ExerciseConfig.Builder setExerciseTypeConfig(androidx.health.services.client.data.ExerciseTypeConfig? exerciseTypeConfig);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsAutoPauseAndResumeEnabled(boolean isAutoPauseAndResumeEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setIsGpsEnabled(boolean isGpsEnabled);
     method public androidx.health.services.client.data.ExerciseConfig.Builder setSwimmingPoolLengthMeters(float swimmingPoolLength);
@@ -556,6 +565,17 @@
     property public final boolean supportsAutoPauseAndResume;
   }
 
+  public final class ExerciseTypeConfig {
+    method public static androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+    method public int getGolfShotTrackingPlaceInfo();
+    property public final int golfShotTrackingPlaceInfo;
+    field public static final androidx.health.services.client.data.ExerciseTypeConfig.Companion Companion;
+  }
+
+  public static final class ExerciseTypeConfig.Companion {
+    method public androidx.health.services.client.data.ExerciseTypeConfig createGolfExerciseTypeConfig(int golfShotTrackingPlaceInfo);
+  }
+
   public final class ExerciseUpdate {
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.IntervalDataPoint<?> dataPoint);
     method public java.time.Duration getActiveDurationAtDataPoint(androidx.health.services.client.data.SampleDataPoint<?> dataPoint);
diff --git a/health/health-services-client/src/main/aidl/androidx/health/services/client/impl/IExerciseApiService.aidl b/health/health-services-client/src/main/aidl/androidx/health/services/client/impl/IExerciseApiService.aidl
index c4f225e..87f3b3e 100644
--- a/health/health-services-client/src/main/aidl/androidx/health/services/client/impl/IExerciseApiService.aidl
+++ b/health/health-services-client/src/main/aidl/androidx/health/services/client/impl/IExerciseApiService.aidl
@@ -25,12 +25,13 @@
 import androidx.health.services.client.impl.request.ExerciseGoalRequest;
 import androidx.health.services.client.impl.request.PrepareExerciseRequest;
 import androidx.health.services.client.impl.request.StartExerciseRequest;
+import androidx.health.services.client.impl.request.UpdateExerciseTypeConfigRequest;
 import androidx.health.services.client.impl.response.ExerciseCapabilitiesResponse;
 
 /**
  * Interface to make ipc calls for health services exercise api.
  *
- * The next method added to the interface should use ID: 15
+ * The next method added to the interface should use ID: 17
  * (this id needs to be incremented for each added method)
  *
  * @hide
@@ -41,7 +42,7 @@
      * method is added.
      *
      */
-    const int API_VERSION = 1;
+    const int API_VERSION = 3;
 
     /**
      * Returns version of this AIDL interface.
@@ -127,4 +128,11 @@
 
     /** Method to flush data metrics. */
     void flushExercise(in FlushRequest request, in IStatusCallback statusCallback) = 12;
+
+    /**
+     * Handles a given request to update an exercise.
+
+     * <p>Added in API version 3.
+     */
+    void updateExerciseTypeConfigForActiveExercise(in UpdateExerciseTypeConfigRequest updateExerciseTypeConfigRequest, IStatusCallback statuscallback) = 16;
 }
diff --git a/health/health-services-client/src/main/aidl/androidx/health/services/client/impl/request/UpdateExerciseTypeConfigRequest.aidl b/health/health-services-client/src/main/aidl/androidx/health/services/client/impl/request/UpdateExerciseTypeConfigRequest.aidl
new file mode 100644
index 0000000..3b3a016
--- /dev/null
+++ b/health/health-services-client/src/main/aidl/androidx/health/services/client/impl/request/UpdateExerciseTypeConfigRequest.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 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 androidx.health.services.client.impl.request;
+
+/** @hide */
+parcelable UpdateExerciseTypeConfigRequest;
\ No newline at end of file
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/ExerciseClient.kt b/health/health-services-client/src/main/java/androidx/health/services/client/ExerciseClient.kt
index fd572f3..311cdcd 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/ExerciseClient.kt
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/ExerciseClient.kt
@@ -25,6 +25,7 @@
 import androidx.health.services.client.data.ExerciseState
 import androidx.health.services.client.data.ExerciseEndReason
 import androidx.health.services.client.data.ExerciseType
+import androidx.health.services.client.data.ExerciseTypeConfig
 import androidx.health.services.client.data.ExerciseUpdate
 import androidx.health.services.client.data.WarmUpConfig
 import com.google.common.util.concurrent.ListenableFuture
@@ -281,4 +282,24 @@
      * @return a [ListenableFuture] containing the [ExerciseCapabilities] for this device
      */
     public fun getCapabilitiesAsync(): ListenableFuture<ExerciseCapabilities>
+
+    /**
+     * Updates the configurable exercise type attributes for the current exercise.
+     *
+     * This can be used to update the configurable attributes for the ongoing exercise, as defined
+     * in [ExerciseTypeConfig]. Minimum Exercise API version for this function is 3.
+     *
+     * @param exerciseTypeConfig a configuration containing the new values for the configurable
+     * attributes
+     * @return a [ListenableFuture] that completes when the configuration has been updated.
+     * @throws [NotImplementedError] if there is an existing [ExerciseClient] that has not
+     * implemented this method. Developers should use [ServiceBackedExerciseClient], which is
+     * guaranteed to have this method implemented.
+     * @see ServiceBackedExerciseClient
+     */
+    public fun updateExerciseTypeConfigAsync(
+        exerciseTypeConfig: ExerciseTypeConfig
+    ): ListenableFuture<Void> {
+        throw NotImplementedError()
+    }
 }
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/ExerciseClientExtension.kt b/health/health-services-client/src/main/java/androidx/health/services/client/ExerciseClientExtension.kt
index 2e54b70..13106ac 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/ExerciseClientExtension.kt
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/ExerciseClientExtension.kt
@@ -25,6 +25,7 @@
 import androidx.health.services.client.data.ExerciseInfo
 import androidx.health.services.client.data.ExerciseState
 import androidx.health.services.client.data.ExerciseType
+import androidx.health.services.client.data.ExerciseTypeConfig
 import androidx.health.services.client.data.ExerciseUpdate
 import androidx.health.services.client.data.WarmUpConfig
 
@@ -247,4 +248,20 @@
  * @throws [android.os.RemoteException] if Health Service fails to process the call
  */
 @kotlin.jvm.Throws(android.os.RemoteException::class)
-public suspend fun ExerciseClient.getCapabilities() = getCapabilitiesAsync().await()
\ No newline at end of file
+public suspend fun ExerciseClient.getCapabilities() = getCapabilitiesAsync().await()
+
+/**
+ * Updates the configurable exercise type attributes for the current exercise.
+ *
+ * This can be used to update the configurable attributes for the ongoing exercise, as defined
+ * in [ExerciseTypeConfig].
+ *
+ * @param exerciseTypeConfig a configuration containing the new values for the configurable
+ * attributes
+ *
+ * @throws [android.os.RemoteException] if Health Service fails to process the call
+ */
+@kotlin.jvm.Throws(android.os.RemoteException::class)
+public suspend fun ExerciseClient.updateExerciseTypeConfig(
+    exerciseTypeConfig: ExerciseTypeConfig
+) = updateExerciseTypeConfigAsync(exerciseTypeConfig).await()
\ No newline at end of file
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseConfig.kt b/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseConfig.kt
index 57ee614..a125add 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseConfig.kt
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseConfig.kt
@@ -39,9 +39,11 @@
  * on-going exercise which can be used to pre-populate a new exercise.
  * @property swimmingPoolLengthMeters length (in meters) of the swimming pool, or 0 if not relevant to
  * this exercise
+ * @property exerciseTypeConfig [ExerciseTypeConfig] containing attributes which may be
+ * modified after the exercise has started
  */
 @Suppress("ParcelCreator")
-class ExerciseConfig(
+class ExerciseConfig @JvmOverloads constructor(
     val exerciseType: ExerciseType,
     val dataTypes: Set<DataType<*, *>>,
     val isAutoPauseAndResumeEnabled: Boolean,
@@ -49,6 +51,7 @@
     val exerciseGoals: List<ExerciseGoal<*>> = listOf(),
     val exerciseParams: Bundle = Bundle(),
     @FloatRange(from = 0.0) val swimmingPoolLengthMeters: Float = SWIMMING_POOL_LENGTH_UNSPECIFIED,
+    val exerciseTypeConfig: ExerciseTypeConfig? = null
 ) {
 
     internal constructor(
@@ -65,7 +68,10 @@
           proto.swimmingPoolLength
         } else {
           SWIMMING_POOL_LENGTH_UNSPECIFIED
-        }
+        },
+        if (proto.hasExerciseTypeConfig()) {
+            ExerciseTypeConfig(proto.exerciseTypeConfig)
+        } else null
     )
 
     init {
@@ -98,6 +104,7 @@
         private var exerciseGoals: List<ExerciseGoal<*>> = emptyList()
         private var exerciseParams: Bundle = Bundle.EMPTY
         private var swimmingPoolLength: Float = SWIMMING_POOL_LENGTH_UNSPECIFIED
+        private var exerciseTypeConfig: ExerciseTypeConfig? = null
 
         /**
          * Sets the requested [DataType]s that should be tracked during this exercise. If not
@@ -171,11 +178,22 @@
 
         /** Sets the swimming pool length (in m). */
         @Suppress("MissingGetterMatchingBuilder")
-        public fun setSwimmingPoolLengthMeters(swimmingPoolLength: Float): Builder {
+        fun setSwimmingPoolLengthMeters(swimmingPoolLength: Float): Builder {
           this.swimmingPoolLength = swimmingPoolLength
           return this
         }
 
+        /**
+         * Sets the [ExerciseTypeConfig] which are configurable attributes for the ongoing exercise.
+         *
+         * @param exerciseTypeConfig [ExerciseTypeConfig] specifying active exercise type
+         * configurations
+         */
+        fun setExerciseTypeConfig(exerciseTypeConfig: ExerciseTypeConfig?): Builder {
+            this.exerciseTypeConfig = exerciseTypeConfig
+            return this
+        }
+
         /** Returns the built [ExerciseConfig]. */
         fun build(): ExerciseConfig {
             return ExerciseConfig(
@@ -185,7 +203,8 @@
                 isGpsEnabled,
                 exerciseGoals,
                 exerciseParams,
-                swimmingPoolLength
+                swimmingPoolLength,
+                exerciseTypeConfig
             )
         }
     }
@@ -197,19 +216,24 @@
             "isAutoPauseAndResumeEnabled=$isAutoPauseAndResumeEnabled, " +
             "isGpsEnabled=$isGpsEnabled, " +
             "exerciseGoals=$exerciseGoals, " +
-            "swimmingPoolLengthMeters=$swimmingPoolLengthMeters)"
+            "swimmingPoolLengthMeters=$swimmingPoolLengthMeters, " +
+            "exerciseTypeConfig=$exerciseTypeConfig)"
 
-    internal fun toProto(): DataProto.ExerciseConfig =
-        DataProto.ExerciseConfig.newBuilder()
-            .setExerciseType(exerciseType.toProto())
-            .addAllDataTypes(dataTypes.filter { !it.isAggregate }.map { it.proto })
-            .addAllAggregateDataTypes(dataTypes.filter { it.isAggregate }.map { it.proto })
-            .setIsAutoPauseAndResumeEnabled(isAutoPauseAndResumeEnabled)
-            .setIsGpsUsageEnabled(isGpsEnabled)
-            .addAllExerciseGoals(exerciseGoals.map { it.proto })
-            .setExerciseParams(BundlesUtil.toProto(exerciseParams))
-            .setSwimmingPoolLength(swimmingPoolLengthMeters)
-            .build()
+   internal fun toProto(): DataProto.ExerciseConfig {
+       val builder = DataProto.ExerciseConfig.newBuilder()
+           .setExerciseType(exerciseType.toProto())
+           .addAllDataTypes(dataTypes.filter { !it.isAggregate }.map { it.proto })
+           .addAllAggregateDataTypes(dataTypes.filter { it.isAggregate }.map { it.proto })
+           .setIsAutoPauseAndResumeEnabled(isAutoPauseAndResumeEnabled)
+           .setIsGpsUsageEnabled(isGpsEnabled)
+           .addAllExerciseGoals(exerciseGoals.map { it.proto })
+           .setExerciseParams(BundlesUtil.toProto(exerciseParams))
+           .setSwimmingPoolLength(swimmingPoolLengthMeters)
+       if (exerciseTypeConfig != null) {
+           builder.exerciseTypeConfig = exerciseTypeConfig.toProto()
+       }
+       return builder.build()
+   }
 
     companion object {
         /**
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseTypeConfig.kt b/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseTypeConfig.kt
new file mode 100644
index 0000000..3d643b7
--- /dev/null
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/data/ExerciseTypeConfig.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 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 androidx.health.services.client.data
+
+import androidx.health.services.client.data.GolfShotTrackingPlaceInfo.Companion.toProto
+import androidx.health.services.client.proto.DataProto
+
+/**
+ * Configuration attributes for a specific exercise type that may be modified after the exercise has
+ * started.
+ *
+ * @property golfShotTrackingPlaceInfo location where user takes [DataType.GOLF_SHOT_COUNT] during
+ * [ExerciseType.GOLF] activity
+ */
+class ExerciseTypeConfig private constructor(
+  @GolfShotTrackingPlaceInfo
+  val golfShotTrackingPlaceInfo: Int = GolfShotTrackingPlaceInfo.UNSPECIFIED
+) {
+
+  internal constructor(
+    proto: DataProto.ExerciseTypeConfig
+  ) : this (
+    GolfShotTrackingPlaceInfo.fromProto(proto.golfShotTrackingPlaceInfo)
+  )
+
+  internal fun toProto(): DataProto.ExerciseTypeConfig {
+    return DataProto.ExerciseTypeConfig.newBuilder()
+      .setGolfShotTrackingPlaceInfo(golfShotTrackingPlaceInfo.toProto())
+      .build()
+  }
+
+  override fun toString(): String =
+    "ExerciseTypeConfig(golfShotTrackingPlaceInfo=$golfShotTrackingPlaceInfo)"
+
+  companion object {
+    /**
+     * Creates golf-specific exercise type configuration.
+     *
+     * @param golfShotTrackingPlaceInfo location where user takes [DataType.GOLF_SHOT_COUNT] during
+     * [ExerciseType.GOLF] activity
+     *
+     * @return an instance of [ExerciseTypeConfig] with specific [GolfShotTrackingPlaceInfo]
+     */
+    @JvmStatic
+    fun createGolfExerciseTypeConfig(
+      @GolfShotTrackingPlaceInfo golfShotTrackingPlaceInfo: Int
+    ): ExerciseTypeConfig {
+      return ExerciseTypeConfig(golfShotTrackingPlaceInfo)
+    }
+  }
+}
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/data/GolfShotTrackingPlaceInfo.kt b/health/health-services-client/src/main/java/androidx/health/services/client/data/GolfShotTrackingPlaceInfo.kt
new file mode 100644
index 0000000..5cf89cb
--- /dev/null
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/data/GolfShotTrackingPlaceInfo.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 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 androidx.health.services.client.data
+
+import androidx.annotation.IntDef
+import androidx.health.services.client.proto.DataProto
+import kotlin.annotation.AnnotationRetention.SOURCE
+
+/**
+ * The tracking information for a golf shot used in [ExerciseTypeConfig]. It is the semantic
+ * location of a user while golfing to assist golf swing activity recognition algorithms.
+ *
+ * @hide
+ */
+@Retention(AnnotationRetention.SOURCE)
+@IntDef(
+  GolfShotTrackingPlaceInfo.UNSPECIFIED,
+  GolfShotTrackingPlaceInfo.FAIRWAY,
+  GolfShotTrackingPlaceInfo.PUTTING_GREEN,
+  GolfShotTrackingPlaceInfo.TEE_BOX
+)
+annotation class GolfShotTrackingPlaceInfo {
+  companion object {
+    /** The golf shot is being taken from an unknown place. */
+    const val UNSPECIFIED: Int = 0
+    /** The golf shot is being taken from the fairway. */
+    const val FAIRWAY: Int = 1
+    /** The golf shot is being taken from the putting green. */
+    const val PUTTING_GREEN: Int = 2
+    /** The golf shot is being taken from the tee box area. */
+    const val TEE_BOX: Int = 3
+
+    internal fun @receiver:GolfShotTrackingPlaceInfo Int.toProto():
+      DataProto.GolfShotTrackingPlaceInfoType =
+      when (this) {
+        FAIRWAY -> DataProto.GolfShotTrackingPlaceInfoType.GOLF_SHOT_TRACKING_PLACE_INFO_FAIRWAY
+        PUTTING_GREEN ->
+          DataProto.GolfShotTrackingPlaceInfoType.GOLF_SHOT_TRACKING_PLACE_INFO_PUTTING_GREEN
+        TEE_BOX -> DataProto.GolfShotTrackingPlaceInfoType.GOLF_SHOT_TRACKING_PLACE_INFO_TEE_BOX
+        else -> DataProto.GolfShotTrackingPlaceInfoType.GOLF_SHOT_TRACKING_PLACE_INFO_UNSPECIFIED
+      }
+
+    @GolfShotTrackingPlaceInfo
+    internal fun fromProto(proto: DataProto.GolfShotTrackingPlaceInfoType): Int =
+      when (proto) {
+        DataProto.GolfShotTrackingPlaceInfoType.GOLF_SHOT_TRACKING_PLACE_INFO_PUTTING_GREEN ->
+          PUTTING_GREEN
+        DataProto.GolfShotTrackingPlaceInfoType.GOLF_SHOT_TRACKING_PLACE_INFO_TEE_BOX -> TEE_BOX
+        DataProto.GolfShotTrackingPlaceInfoType.GOLF_SHOT_TRACKING_PLACE_INFO_FAIRWAY -> FAIRWAY
+        else -> UNSPECIFIED
+      }
+  }
+}
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ServiceBackedExerciseClient.kt b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ServiceBackedExerciseClient.kt
index 786f636..9f92ad7 100644
--- a/health/health-services-client/src/main/java/androidx/health/services/client/impl/ServiceBackedExerciseClient.kt
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/impl/ServiceBackedExerciseClient.kt
@@ -27,6 +27,7 @@
 import androidx.health.services.client.data.ExerciseConfig
 import androidx.health.services.client.data.ExerciseGoal
 import androidx.health.services.client.data.ExerciseInfo
+import androidx.health.services.client.data.ExerciseTypeConfig
 import androidx.health.services.client.data.WarmUpConfig
 import androidx.health.services.client.impl.IpcConstants.EXERCISE_API_BIND_ACTION
 import androidx.health.services.client.impl.IpcConstants.SERVICE_PACKAGE_NAME
@@ -42,6 +43,7 @@
 import androidx.health.services.client.impl.request.FlushRequest
 import androidx.health.services.client.impl.request.PrepareExerciseRequest
 import androidx.health.services.client.impl.request.StartExerciseRequest
+import androidx.health.services.client.impl.request.UpdateExerciseTypeConfigRequest
 import com.google.common.util.concurrent.FutureCallback
 import com.google.common.util.concurrent.Futures
 import com.google.common.util.concurrent.ListenableFuture
@@ -216,6 +218,20 @@
             ContextCompat.getMainExecutor(context)
         )
 
+    override fun updateExerciseTypeConfigAsync(
+        exerciseTypeConfig: ExerciseTypeConfig
+    ): ListenableFuture<Void> {
+        return executeWithVersionCheck(
+            { service, resultFuture ->
+                service.updateExerciseTypeConfigForActiveExercise(
+                    UpdateExerciseTypeConfigRequest(packageName, exerciseTypeConfig),
+                    StatusCallback(resultFuture)
+                )
+            },
+            3
+        )
+    }
+
     internal companion object {
         internal const val CLIENT = "HealthServicesExerciseClient"
         internal val CLIENT_CONFIGURATION =
diff --git a/health/health-services-client/src/main/java/androidx/health/services/client/impl/request/UpdateExerciseTypeConfigRequest.kt b/health/health-services-client/src/main/java/androidx/health/services/client/impl/request/UpdateExerciseTypeConfigRequest.kt
new file mode 100644
index 0000000..584f05a
--- /dev/null
+++ b/health/health-services-client/src/main/java/androidx/health/services/client/impl/request/UpdateExerciseTypeConfigRequest.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 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 androidx.health.services.client.impl.request
+
+import android.os.Parcelable
+import androidx.annotation.RestrictTo
+import androidx.health.services.client.data.GolfShotTrackingPlaceInfo
+import androidx.health.services.client.data.ExerciseTypeConfig
+import androidx.health.services.client.data.ProtoParcelable
+import androidx.health.services.client.proto.RequestsProto
+
+/**
+ * Request for updating exercise type configuration in an [ExerciseTypeConfig].
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+class UpdateExerciseTypeConfigRequest(
+    val packageName: String,
+    val exerciseTypeConfig: ExerciseTypeConfig,
+) : ProtoParcelable<RequestsProto.UpdateExerciseTypeConfigRequest>() {
+    override val proto: RequestsProto.UpdateExerciseTypeConfigRequest =
+        RequestsProto.UpdateExerciseTypeConfigRequest.newBuilder()
+            .setPackageName(packageName)
+            .setConfig(exerciseTypeConfig.toProto())
+            .build()
+
+    companion object {
+        @JvmField
+        val CREATOR: Parcelable.Creator<UpdateExerciseTypeConfigRequest> = newCreator { bytes ->
+            val proto = RequestsProto.UpdateExerciseTypeConfigRequest.parseFrom(bytes)
+            UpdateExerciseTypeConfigRequest(
+                proto.packageName,
+                ExerciseTypeConfig.createGolfExerciseTypeConfig(
+                    GolfShotTrackingPlaceInfo.fromProto(proto.config.golfShotTrackingPlaceInfo))
+                )
+        }
+    }
+}
\ No newline at end of file
diff --git a/health/health-services-client/src/main/proto/data.proto b/health/health-services-client/src/main/proto/data.proto
index 420bbc6..65e2287 100644
--- a/health/health-services-client/src/main/proto/data.proto
+++ b/health/health-services-client/src/main/proto/data.proto
@@ -173,16 +173,31 @@
   reserved 2 to max;  // Next ID
 }
 
+enum GolfShotTrackingPlaceInfoType {
+  GOLF_SHOT_TRACKING_PLACE_INFO_UNSPECIFIED = 0;
+  GOLF_SHOT_TRACKING_PLACE_INFO_FAIRWAY = 1;
+  GOLF_SHOT_TRACKING_PLACE_INFO_PUTTING_GREEN = 2;
+  GOLF_SHOT_TRACKING_PLACE_INFO_TEE_BOX = 3;
+  reserved 4 to max; // Next ID
+}
+
+message ExerciseTypeConfig {
+  optional GolfShotTrackingPlaceInfoType golf_shot_tracking_place_info = 1;
+  reserved 2 to max; // Next ID
+}
+
 message ExerciseConfig {
   optional ExerciseType exercise_type = 1;
   repeated DataType data_types = 2;
   repeated DataType aggregate_data_types = 3;
-  optional bool is_auto_pause_and_resume_enabled = 4; // TODO(sarakato): Move to dynamicExericseConfig
+  optional bool is_auto_pause_and_resume_enabled = 4;
   optional bool is_gps_usage_enabled = 5;
   repeated ExerciseGoal exercise_goals = 6;
   optional Bundle exercise_params = 7; // TODO(b/241015676): Deprecate
   optional float swimming_pool_length = 8;
-  reserved 9 to max;  // Next ID
+  optional ExerciseTypeConfig exercise_type_config = 10;
+  reserved 9;
+  reserved 11 to max;  // Next ID
 }
 
 message ExerciseInfo {
diff --git a/health/health-services-client/src/main/proto/requests.proto b/health/health-services-client/src/main/proto/requests.proto
index d71c3a7..39e0b7c 100644
--- a/health/health-services-client/src/main/proto/requests.proto
+++ b/health/health-services-client/src/main/proto/requests.proto
@@ -116,3 +116,9 @@
   optional ExerciseConfig config = 2;
   reserved 3 to max;  // Next ID
 }
+
+message UpdateExerciseTypeConfigRequest {
+  optional string package_name = 1;
+  optional ExerciseTypeConfig config = 2;
+  reserved 3 to max;  // Next ID
+}
diff --git a/health/health-services-client/src/test/java/androidx/health/services/client/ExerciseClientTest.kt b/health/health-services-client/src/test/java/androidx/health/services/client/ExerciseClientTest.kt
index 8d2e322..41be3a0d 100644
--- a/health/health-services-client/src/test/java/androidx/health/services/client/ExerciseClientTest.kt
+++ b/health/health-services-client/src/test/java/androidx/health/services/client/ExerciseClientTest.kt
@@ -34,7 +34,9 @@
 import androidx.health.services.client.data.ExerciseTrackedStatus
 import androidx.health.services.client.data.ExerciseType
 import androidx.health.services.client.data.ExerciseTypeCapabilities
+import androidx.health.services.client.data.ExerciseTypeConfig
 import androidx.health.services.client.data.ExerciseUpdate
+import androidx.health.services.client.data.GolfShotTrackingPlaceInfo
 import androidx.health.services.client.data.WarmUpConfig
 import androidx.health.services.client.impl.IExerciseApiService
 import androidx.health.services.client.impl.IExerciseUpdateListener
@@ -51,6 +53,7 @@
 import androidx.health.services.client.impl.request.FlushRequest
 import androidx.health.services.client.impl.request.PrepareExerciseRequest
 import androidx.health.services.client.impl.request.StartExerciseRequest
+import androidx.health.services.client.impl.request.UpdateExerciseTypeConfigRequest
 import androidx.health.services.client.impl.response.AvailabilityResponse
 import androidx.health.services.client.impl.response.ExerciseCapabilitiesResponse
 import androidx.health.services.client.impl.response.ExerciseInfoResponse
@@ -644,6 +647,23 @@
             .isEqualTo(passiveMonitoringCapabilities.toString())
     }
 
+    @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
+    @Test
+    fun updateExerciseTypeConfigForActiveExercise() = runTest {
+        service.exerciseConfig = ExerciseConfig.builder(ExerciseType.GOLF).build()
+        val exerciseTypeConfig =
+            ExerciseTypeConfig.createGolfExerciseTypeConfig(GolfShotTrackingPlaceInfo.FAIRWAY)
+        val request =
+            UpdateExerciseTypeConfigRequest(
+                CLIENT_CONFIGURATION.servicePackageName, exerciseTypeConfig
+            )
+        val statusCallback = IStatusCallback.Default()
+
+        service.updateExerciseTypeConfigForActiveExercise(request, statusCallback)
+
+        Truth.assertThat(service.exerciseConfig?.exerciseTypeConfig).isEqualTo(exerciseTypeConfig)
+    }
+
     class FakeExerciseUpdateCallback : ExerciseUpdateCallback {
         val availabilities = mutableMapOf<DataType<*, *>, Availability>()
         val registrationFailureThrowables = mutableListOf<Throwable>()
@@ -855,6 +875,18 @@
             statusCallbackAction.invoke(statusCallback)
         }
 
+        override fun updateExerciseTypeConfigForActiveExercise(
+            updateExerciseTypeConfigRequest: UpdateExerciseTypeConfigRequest,
+            statuscallback: IStatusCallback
+        ) {
+            val newExerciseTypeConfig = updateExerciseTypeConfigRequest.exerciseTypeConfig
+            val newExerciseConfig =
+                ExerciseConfig.builder(
+                    exerciseConfig!!.exerciseType
+                ).setExerciseTypeConfig(newExerciseTypeConfig).build()
+            this.exerciseConfig = newExerciseConfig
+        }
+
         fun setException() {
             throwException = true
         }
diff --git a/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseConfigTest.kt b/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseConfigTest.kt
index 8567fa6..c23763f 100644
--- a/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseConfigTest.kt
+++ b/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseConfigTest.kt
@@ -43,6 +43,8 @@
                     DataTypeCondition(DISTANCE_TOTAL, 150.0, GREATER_THAN)
                 ),
             ),
+            exerciseTypeConfig = ExerciseTypeConfig.createGolfExerciseTypeConfig(
+                GolfShotTrackingPlaceInfo.FAIRWAY)
         ).toProto()
 
         val config = ExerciseConfig(proto)
@@ -57,6 +59,51 @@
         assertThat(config.exerciseGoals[1].dataTypeCondition.dataType).isEqualTo(DISTANCE_TOTAL)
         assertThat(config.exerciseGoals[1].dataTypeCondition.threshold).isEqualTo(150.0)
         assertThat(config.exerciseGoals[1].dataTypeCondition.comparisonType).isEqualTo(GREATER_THAN)
+        assertThat((config.exerciseTypeConfig)?.golfShotTrackingPlaceInfo).isEqualTo(
+         GolfShotTrackingPlaceInfo.FAIRWAY)
+    }
+
+    @Test
+    fun exerciseTypeConfigNull_protoRoundTrip() {
+        val proto = ExerciseConfig(
+            ExerciseType.RUNNING,
+            setOf(LOCATION, DISTANCE_TOTAL, HEART_RATE_BPM),
+            isAutoPauseAndResumeEnabled = true,
+            isGpsEnabled = true,
+            exerciseGoals = listOf(
+                ExerciseGoal.createOneTimeGoal(
+                    DataTypeCondition(DISTANCE_TOTAL, 50.0, GREATER_THAN)
+                ),
+                ExerciseGoal.createOneTimeGoal(
+                    DataTypeCondition(DISTANCE_TOTAL, 150.0, GREATER_THAN)
+                ),
+            )
+        ).toProto()
+
+        val config = ExerciseConfig(proto)
+
+        assertThat(config.exerciseType).isEqualTo(ExerciseType.RUNNING)
+        assertThat(config.dataTypes).containsExactly(LOCATION, HEART_RATE_BPM, DISTANCE_TOTAL)
+        assertThat(config.isAutoPauseAndResumeEnabled).isEqualTo(true)
+        assertThat(config.isGpsEnabled).isEqualTo(true)
+        assertThat(config.exerciseGoals[0].dataTypeCondition.dataType).isEqualTo(DISTANCE_TOTAL)
+        assertThat(config.exerciseGoals[0].dataTypeCondition.threshold).isEqualTo(50.0)
+        assertThat(config.exerciseGoals[0].dataTypeCondition.comparisonType).isEqualTo(GREATER_THAN)
+        assertThat(config.exerciseGoals[1].dataTypeCondition.dataType).isEqualTo(DISTANCE_TOTAL)
+        assertThat(config.exerciseGoals[1].dataTypeCondition.threshold).isEqualTo(150.0)
+        assertThat(config.exerciseGoals[1].dataTypeCondition.comparisonType).isEqualTo(GREATER_THAN)
+        assertThat((config.exerciseTypeConfig)).isNull()
+    }
+
+    @Test
+    fun builder_exerciseTypeConfigNull() {
+        val exerciseTypeConfigNotSetExerciseConfig =
+            ExerciseConfig.builder(ExerciseType.UNKNOWN).build()
+        val setNullExerciseTypeConfigExerciseConfig =
+            ExerciseConfig.builder(ExerciseType.UNKNOWN).setExerciseTypeConfig(null).build()
+
+        assertThat(exerciseTypeConfigNotSetExerciseConfig.exerciseTypeConfig).isNull()
+        assertThat(setNullExerciseTypeConfigExerciseConfig.exerciseTypeConfig).isNull()
     }
 
     @Test
diff --git a/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseTypeConfigTest.kt b/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseTypeConfigTest.kt
new file mode 100644
index 0000000..10cf21d
--- /dev/null
+++ b/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseTypeConfigTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 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 androidx.health.services.client.data
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@RunWith(RobolectricTestRunner::class)
+class ExerciseTypeConfigTest {
+    @Test
+    fun protoRoundTrip() {
+        val proto = ExerciseTypeConfig.createGolfExerciseTypeConfig(
+            GolfShotTrackingPlaceInfo.FAIRWAY).toProto()
+        val config = ExerciseTypeConfig(proto)
+
+        assertThat(config.golfShotTrackingPlaceInfo).isEqualTo(GolfShotTrackingPlaceInfo.FAIRWAY)
+    }
+
+    @Test
+    fun createGolfExerciseTypeConfigFromFactoryMethod() {
+        val golfExerciseStyleConfig = ExerciseTypeConfig.createGolfExerciseTypeConfig(
+            GolfShotTrackingPlaceInfo.FAIRWAY)
+
+        assertThat(golfExerciseStyleConfig.golfShotTrackingPlaceInfo).isEqualTo(
+            GolfShotTrackingPlaceInfo.FAIRWAY)
+    }
+}
diff --git a/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseUpdateTest.kt b/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseUpdateTest.kt
index e5c0a69..b4b0537 100644
--- a/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseUpdateTest.kt
+++ b/health/health-services-client/src/test/java/androidx/health/services/client/data/ExerciseUpdateTest.kt
@@ -59,9 +59,12 @@
             exerciseConfig = ExerciseConfig(
                 WALKING,
                 setOf(CALORIES_TOTAL),
-                isAutoPauseAndResumeEnabled = true,
+                isAutoPauseAndResumeEnabled = false,
                 isGpsEnabled = false,
-                exerciseGoals = listOf(goal)
+                exerciseGoals = listOf(goal),
+                exerciseTypeConfig = ExerciseTypeConfig.createGolfExerciseTypeConfig(
+                    GolfShotTrackingPlaceInfo.FAIRWAY
+                )
             ),
             activeDurationCheckpoint = ActiveDurationCheckpoint(42.instant(), 30.duration()),
             updateDurationFromBoot = 42.duration(),
@@ -81,7 +84,62 @@
             .isEqualTo(CALORIES_TOTAL)
         assertThat(markerSummary.achievedGoal.dataTypeCondition.dataType).isEqualTo(CALORIES_TOTAL)
         assertThat(update.exerciseConfig!!.exerciseType).isEqualTo(WALKING)
+        assertThat(
+            update.exerciseConfig!!.exerciseTypeConfig!!.golfShotTrackingPlaceInfo).isEqualTo(
+            GolfShotTrackingPlaceInfo.FAIRWAY)
         assertThat(update.activeDurationCheckpoint!!.activeDuration).isEqualTo(30.duration())
         assertThat(update.exerciseStateInfo.state).isEqualTo(ExerciseState.ACTIVE)
     }
-}
\ No newline at end of file
+
+    @Test
+    fun exerciseTypeConfigNull_protoRoundTrip() {
+        val goal = createOneTimeGoal(
+            DataTypeCondition(CALORIES_TOTAL, 125.0, GREATER_THAN_OR_EQUAL)
+        )
+        val proto = ExerciseUpdate(
+            latestMetrics = DataPointContainer(
+                listOf(DataPoints.calories(130.0, 15.duration(), 35.duration()))
+            ),
+            latestAchievedGoals = setOf(goal),
+            latestMilestoneMarkerSummaries = setOf(
+                MilestoneMarkerSummary(
+                    15.instant(),
+                    40.instant(),
+                    20.duration(),
+                    goal,
+                    DataPointContainer(
+                        listOf(DataPoints.calories(130.0, 15.duration(), 35.duration()))
+                    )
+                )
+            ),
+            exerciseStateInfo = ExerciseStateInfo(ExerciseState.ACTIVE, ExerciseEndReason.UNKNOWN),
+            exerciseConfig = ExerciseConfig(
+                WALKING,
+                setOf(CALORIES_TOTAL),
+                isAutoPauseAndResumeEnabled = false,
+                isGpsEnabled = false,
+                exerciseGoals = listOf(goal),
+            ),
+            activeDurationCheckpoint = ActiveDurationCheckpoint(42.instant(), 30.duration()),
+            updateDurationFromBoot = 42.duration(),
+            startTime = 10.instant()
+        ).proto
+
+        val update = ExerciseUpdate(proto)
+
+        val caloriesDataPoint = update.latestMetrics.getData(DataType.CALORIES).first()
+        val markerSummary = update.latestMilestoneMarkerSummaries.first()
+        assertThat(update.startTime).isEqualTo(10.instant())
+        assertThat(update.getUpdateDurationFromBoot()).isEqualTo(42.duration())
+        assertThat(caloriesDataPoint.value).isEqualTo(130.0)
+        assertThat(caloriesDataPoint.startDurationFromBoot).isEqualTo(15.duration())
+        assertThat(caloriesDataPoint.endDurationFromBoot).isEqualTo(35.duration())
+        assertThat(update.latestAchievedGoals.first().dataTypeCondition.dataType)
+            .isEqualTo(CALORIES_TOTAL)
+        assertThat(markerSummary.achievedGoal.dataTypeCondition.dataType).isEqualTo(CALORIES_TOTAL)
+        assertThat(update.exerciseConfig!!.exerciseType).isEqualTo(WALKING)
+        assertThat(update.exerciseConfig!!.exerciseTypeConfig).isNull()
+        assertThat(update.activeDurationCheckpoint!!.activeDuration).isEqualTo(30.duration())
+        assertThat(update.exerciseStateInfo.state).isEqualTo(ExerciseState.ACTIVE)
+    }
+}
diff --git a/health/health-services-client/src/test/java/androidx/health/services/client/impl/ServiceBackedExerciseClientTest.kt b/health/health-services-client/src/test/java/androidx/health/services/client/impl/ServiceBackedExerciseClientTest.kt
index 32e90cf..b519939 100644
--- a/health/health-services-client/src/test/java/androidx/health/services/client/impl/ServiceBackedExerciseClientTest.kt
+++ b/health/health-services-client/src/test/java/androidx/health/services/client/impl/ServiceBackedExerciseClientTest.kt
@@ -31,6 +31,8 @@
 import androidx.health.services.client.data.ExerciseType
 import androidx.health.services.client.data.ExerciseUpdate
 import androidx.health.services.client.data.WarmUpConfig
+import androidx.health.services.client.data.ExerciseTypeConfig
+import androidx.health.services.client.data.GolfShotTrackingPlaceInfo
 import androidx.health.services.client.impl.event.ExerciseUpdateListenerEvent
 import androidx.health.services.client.impl.internal.IExerciseInfoCallback
 import androidx.health.services.client.impl.internal.IStatusCallback
@@ -41,6 +43,7 @@
 import androidx.health.services.client.impl.request.FlushRequest
 import androidx.health.services.client.impl.request.PrepareExerciseRequest
 import androidx.health.services.client.impl.request.StartExerciseRequest
+import androidx.health.services.client.impl.request.UpdateExerciseTypeConfigRequest
 import androidx.health.services.client.impl.response.AvailabilityResponse
 import androidx.health.services.client.impl.response.ExerciseCapabilitiesResponse
 import androidx.test.core.app.ApplicationProvider
@@ -107,7 +110,7 @@
             ExerciseType.WALKING,
             setOf(HEART_RATE_BPM),
             isAutoPauseAndResumeEnabled = false,
-            isGpsEnabled = false
+            isGpsEnabled = false,
         )
         val availabilityEvent = ExerciseUpdateListenerEvent.createAvailabilityUpdateEvent(
             AvailabilityResponse(HEART_RATE_BPM, ACQUIRING)
@@ -171,6 +174,34 @@
     }
 
     @Test
+    fun withExerciseTypeConfig_statsAndSample_startExercise() {
+        val exerciseConfig = ExerciseConfig(
+            ExerciseType.GOLF,
+            setOf(HEART_RATE_BPM, HEART_RATE_BPM_STATS),
+            isAutoPauseAndResumeEnabled = false,
+            isGpsEnabled = false,
+            exerciseTypeConfig = ExerciseTypeConfig.createGolfExerciseTypeConfig(
+                GolfShotTrackingPlaceInfo.FAIRWAY
+            )
+        )
+        val availabilityEvent = ExerciseUpdateListenerEvent.createAvailabilityUpdateEvent(
+            // Currently the proto form of HEART_RATE_BPM and HEART_RATE_BPM_STATS is identical. The
+            // APK doesn't know about _STATS, so pass the sample type to mimic that behavior.
+            AvailabilityResponse(HEART_RATE_BPM, ACQUIRING)
+        )
+        client.setUpdateCallback(callback)
+        client.startExerciseAsync(exerciseConfig)
+        shadowOf(getMainLooper()).idle()
+
+        fakeService.listener!!.onExerciseUpdateListenerEvent(availabilityEvent)
+        shadowOf(getMainLooper()).idle()
+
+        // When both the sample type and stat type are requested, both should be notified
+        assertThat(callback.availabilities).containsEntry(HEART_RATE_BPM, ACQUIRING)
+        assertThat(callback.availabilities).containsEntry(HEART_RATE_BPM_STATS, ACQUIRING)
+    }
+
+    @Test
     fun dataTypeInAvailabilityCallbackShouldMatchRequested_justSampleType_prepare() {
         val warmUpConfig = WarmUpConfig(
             ExerciseType.WALKING,
@@ -302,5 +333,12 @@
         override fun flushExercise(request: FlushRequest?, statusCallback: IStatusCallback?) {
             throw NotImplementedError()
         }
+
+        override fun updateExerciseTypeConfigForActiveExercise(
+            updateExerciseTypeConfigRequest: UpdateExerciseTypeConfigRequest?,
+            statuscallback: IStatusCallback?
+        ) {
+            throw NotImplementedError()
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/health/health-services-client/src/test/java/androidx/health/services/client/impl/request/UpdateExerciseTypeConfigRequestTest.kt b/health/health-services-client/src/test/java/androidx/health/services/client/impl/request/UpdateExerciseTypeConfigRequestTest.kt
new file mode 100644
index 0000000..1e2a23c
--- /dev/null
+++ b/health/health-services-client/src/test/java/androidx/health/services/client/impl/request/UpdateExerciseTypeConfigRequestTest.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2022 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 androidx.health.services.client.impl.request
+
+import android.os.Parcel
+import androidx.health.services.client.data.ExerciseTypeConfig
+import androidx.health.services.client.data.GolfShotTrackingPlaceInfo
+import com.google.common.truth.Truth
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@RunWith(RobolectricTestRunner::class)
+class UpdateExerciseTypeConfigRequestTest {
+    @Test
+    fun parcelableRoundTrip() {
+        val request =
+            UpdateExerciseTypeConfigRequest(
+                "package",
+                ExerciseTypeConfig.createGolfExerciseTypeConfig(GolfShotTrackingPlaceInfo.TEE_BOX)
+            )
+        val parcel = Parcel.obtain()
+
+        request.writeToParcel(parcel, 0)
+        parcel.setDataPosition(0)
+        val fromParcel = UpdateExerciseTypeConfigRequest.CREATOR.createFromParcel(parcel)
+
+        Truth.assertThat(request).isEqualTo(fromParcel)
+    }
+}
\ No newline at end of file