Add T&C URL to T&C string
Bug: 279611921
Test: Local build
Test: atest DeviceLockControllerRoboTests
Change-Id: Ica9bdc684646c60a376535da7d0a9fc81bcc6cf2
diff --git a/DeviceLockController/res/values/strings.xml b/DeviceLockController/res/values/strings.xml
index b3cf9d5..371af56 100644
--- a/DeviceLockController/res/values/strings.xml
+++ b/DeviceLockController/res/values/strings.xml
@@ -87,7 +87,7 @@
<!-- Text explaining that the device can be restricted if payment is missing. [CHAR_LIMIT=NONE] -->
<string name="restrict_device_if_missing_payment"><xliff:g id="provider name">%1$s</xliff:g> can restrict this device if you miss a payment</string>
<!-- Text explaining that the device can be restricted if the user does not make payments. [CHAR_LIMIT=NONE] -->
- <string name="restrict_device_if_dont_make_payment"><xliff:g id="provider name">%1$s</xliff:g> can restrict this device if you don\'t make the necessary payments. For details, view the Terms & Conditions.</string>
+ <string name="restrict_device_if_dont_make_payment"><xliff:g id="provider name">%1$s</xliff:g> can restrict this device if you don\'t make the necessary payments. For details, view the <xliff:g id="terms_and_conditions_link_start"><a href="%2$s"></xliff:g>Terms & Conditions<xliff:g id="terms_and_conditions_link_end"></a></xliff:g>.</string>
<!-- Text explaining that the device can be restricted if the owner of the device does not make payments. [CHAR_LIMIT=NONE] -->
<string name="restrict_device_if_owner_doesnt_make_payment"><xliff:g id="provider name">%1$s</xliff:g> can restrict this device if the owner doesn\'t make payments</string>
<!-- Button text. This button lets a user go back to previous screen. [CHAR_LIMIT=20] -->
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapter.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapter.java
index 4a22d06..7f4debb 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapter.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapter.java
@@ -73,6 +73,10 @@
newValue -> notifyItemChanged(position));
return;
}
- provisionInfoViewHolder.bind(getItem(position), providerName);
+
+ // TODO(b/282248521): Refactor ProvisionInfoList, ProviderName, and TermsAndConditionsUrl
+ // Live Data.
+ provisionInfoViewHolder.bind(getItem(position), providerName,
+ mViewModel.mTermsAndConditionsUrlLiveData.getValue());
}
}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewHolder.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewHolder.java
index be3bc85..3695d21 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewHolder.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewHolder.java
@@ -17,11 +17,19 @@
package com.android.devicelockcontroller.activities;
import android.content.Context;
+import android.content.Intent;
+import android.text.Html;
+import android.text.Spannable;
+import android.text.SpannableString;
import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.text.style.URLSpan;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.android.devicelockcontroller.R;
@@ -42,16 +50,65 @@
mTextView = itemView.findViewById(R.id.text_view_item_provision_info);
}
- void bind(ProvisionInfo provisionInfo, String providerName) {
+ void bind(ProvisionInfo provisionInfo, String providerName,
+ @Nullable String termsAndConditionsUrl) {
Context context = itemView.getContext();
if (TextUtils.isEmpty(providerName)) {
LogUtil.e(TAG, "Device provider name is empty, should not reach here.");
return;
}
- mTextView.setText(context.getString(provisionInfo.getTextId(), providerName));
+
+ // The Terms and Conditions URL is known at runtime and required for the string used for the
+ // Device Subsidy program.
+ if (provisionInfo.getTextId() == R.string.restrict_device_if_dont_make_payment) {
+ if (TextUtils.isEmpty(termsAndConditionsUrl)) {
+ LogUtil.e(TAG, "Terms and Conditions URL is empty, should not reach here.");
+ return;
+ }
+
+ SpannableString spannedTextView = new SpannableString(Html.fromHtml(
+ String.format(
+ context.getString(R.string.restrict_device_if_dont_make_payment),
+ providerName, termsAndConditionsUrl),
+ Html.FROM_HTML_MODE_LEGACY));
+ URLSpan[] spans = spannedTextView.getSpans(0, spannedTextView.length(),
+ URLSpan.class);
+
+ for (URLSpan span : spans) {
+ int start = spannedTextView.getSpanStart(span);
+ int end = spannedTextView.getSpanEnd(span);
+
+ ClickableSpan clickableSpan = new CustomClickableSpan(span.getURL());
+ spannedTextView.removeSpan(span);
+ spannedTextView.setSpan(clickableSpan, start, end,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+
+ mTextView.setText(spannedTextView);
+ mTextView.setMovementMethod(LinkMovementMethod.getInstance());
+ } else {
+ mTextView.setText(context.getString(provisionInfo.getTextId(), providerName));
+ }
+
mTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(provisionInfo.getDrawableId(),
/* top=*/ 0,
/* end=*/ 0,
/* bottom=*/ 0);
}
+
+ private static final class CustomClickableSpan extends ClickableSpan {
+
+ final String mUrl;
+
+ CustomClickableSpan(String url) {
+ mUrl = url;
+ }
+
+ @Override
+ public void onClick(@NonNull View view) {
+ Intent webIntent = new Intent(view.getContext(), HelpActivity.class);
+ webIntent.putExtra(HelpActivity.EXTRA_URL_PARAM, mUrl);
+ view.getContext().startActivity(webIntent);
+ }
+ }
}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewModel.java
index 3d8593e..12c3652 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewModel.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewModel.java
@@ -46,16 +46,17 @@
final MutableLiveData<Integer> mSubheaderTextIdLiveData;
final MutableLiveData<List<ProvisionInfo>> mProvisionInfoListLiveData;
final MutableLiveData<String> mProviderNameLiveData;
+ final MutableLiveData<String> mTermsAndConditionsUrlLiveData;
final MediatorLiveData<Pair<Integer, String>> mHeaderTextLiveData;
final MediatorLiveData<Pair<Integer, String>> mSubHeaderTextLiveData;
-
public ProvisionInfoViewModel() {
mProvisionInfoListLiveData = new MutableLiveData<>();
mHeaderDrawableIdLiveData = new MutableLiveData<>();
mHeaderTextIdLiveData = new MutableLiveData<>();
mSubheaderTextIdLiveData = new MutableLiveData<>();
mProviderNameLiveData = new MutableLiveData<>();
+ mTermsAndConditionsUrlLiveData = new MutableLiveData<>();
mHeaderTextLiveData = new MediatorLiveData<>();
mHeaderTextLiveData.addSource(mHeaderTextIdLiveData,
id -> {
@@ -104,5 +105,24 @@
LogUtil.e(TAG, "Failed to get Kiosk app provider name", t);
}
}, MoreExecutors.directExecutor());
+
+ Futures.addCallback(
+ SetupParametersClient.getInstance().getTermsAndConditionsUrl(),
+ new FutureCallback<>() {
+ @Override
+ public void onSuccess(String termsAndConditionsUrl) {
+ if (TextUtils.isEmpty(termsAndConditionsUrl)) {
+ LogUtil.e(TAG,
+ "Terms and Conditions URL is empty, should not reach here.");
+ return;
+ }
+ mTermsAndConditionsUrlLiveData.postValue(termsAndConditionsUrl);
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ LogUtil.e(TAG, "Failed to get Terms and Conditions URL", t);
+ }
+ }, MoreExecutors.directExecutor());
}
}