[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: c6c977671f -s ours

am skip reason: contains skip directive

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/DeviceLock/+/26326515

Change-Id: I78008cd1d734edfcb83e00fffc59625e7dc818fd
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/DeviceLockController/Android.bp b/DeviceLockController/Android.bp
index ac0b07f..96924b3 100644
--- a/DeviceLockController/Android.bp
+++ b/DeviceLockController/Android.bp
@@ -38,10 +38,19 @@
     ],
 }
 
+genrule {
+    name: "statslog-devicelock-java-gen",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --java $(out) --module devicelock" +
+        " --javaPackage com.android.devicelockcontroller" +
+        " --javaClass DevicelockStatsLog",
+    out: ["com/android/devicelockcontroller/DevicelockStatsLog.java"],
+}
+
 java_library {
     name: "devicelockcontroller-interface",
     sdk_version: "module_current",
-    min_sdk_version: "33", // AIDL compiler does not know about UpsideDownCake
+    min_sdk_version: "UpsideDownCake",
     srcs: ["src/**/*.aidl"],
     apex_available: [
         "com.android.devicelock",
@@ -52,6 +61,19 @@
 }
 
 java_library {
+    name: "devicelockcontroller-thread-asserts-lib",
+    srcs: [
+        "src/com/android/devicelockcontroller/util/ThreadAsserts.java",
+    ],
+    sdk_version: "module_current",
+    min_sdk_version: "UpsideDownCake",
+    apex_available: ["com.android.devicelock"],
+    visibility: [
+        "//packages/modules/DeviceLock:__subpackages__",
+    ],
+}
+
+java_library {
     name: "devicelockcontroller-common-lib",
     srcs: [
         "src/com/android/devicelockcontroller/common/*.java",
@@ -62,6 +84,7 @@
     apex_available: ["com.android.devicelock"],
     static_libs: [
         "androidx.annotation_annotation",
+        "guava",
     ],
     visibility: [
         "//packages/modules/DeviceLock:__subpackages__",
@@ -89,18 +112,45 @@
     ],
 }
 
+java_test_helper_library {
+    name: "devicelockcontroller-stats",
+    sdk_version: "module_current",
+    srcs: [
+        "src/**/stats/*.java",
+        ":statslog-devicelock-java-gen",
+    ],
+    libs: [
+        "framework-statsd",
+        "modules-utils-expresslog",
+    ],
+    static_libs: [
+        "androidx.annotation_annotation",
+    ],
+    visibility: [
+        "//packages/modules/DeviceLock:__subpackages__",
+    ],
+}
+
 // Library with all dependencies for building DeviceLockController
 android_library {
     name: "devicelockcontroller-lib",
     sdk_version: "module_current",
     min_sdk_version: "UpsideDownCake",
-    srcs: ["src/**/*.java"],
-    exclude_srcs: [":devicelockcontroller-grpc-impl-sources"],
+    srcs: [
+        "src/**/*.java",
+        ":statslog-devicelock-java-gen",
+    ],
+    exclude_srcs: [
+        ":devicelockcontroller-grpc-impl-sources",
+        "src/com/android/devicelockcontroller/debug/*.java",
+    ],
     resource_dirs: ["res"],
     libs: [
         "framework-annotations-lib",
         "framework-devicelock.impl",
         "org.apache.http.legacy",
+        "framework-statsd",
+        "modules-utils-expresslog",
     ],
     static_libs: [
         "androidx.annotation_annotation",
@@ -146,10 +196,6 @@
         "devicelockcontroller-proto-lite",
     ],
 
-    lint: {
-        strict_updatability_linting: true,
-    },
-
     optimize: {
         proguard_flags_files: ["proguard.flags"],
         shrink_resources: true,
@@ -179,10 +225,6 @@
         "devicelockcontroller-proto-lite",
     ],
 
-    lint: {
-        strict_updatability_linting: true,
-    },
-
     optimize: {
         proguard_flags_files: ["proguard.flags"],
         shrink_resources: true,
diff --git a/DeviceLockController/AndroidManifestBase.xml b/DeviceLockController/AndroidManifestBase.xml
index d5057a9..bb3a89c 100644
--- a/DeviceLockController/AndroidManifestBase.xml
+++ b/DeviceLockController/AndroidManifestBase.xml
@@ -27,7 +27,6 @@
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
-    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
     <uses-permission android:name="android.permission.MASTER_CLEAR" />
     <uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_APPS_CONTROL" />
     <uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_CALLS" />
@@ -38,9 +37,9 @@
     <uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_TIME" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
     <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
-    <uses-permission android:name="com.android.permission.INSTALL_EXISTING_PACKAGES" />
     <uses-permission android:name="com.android.devicelockcontroller.permission.MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER" />
 
     <application
@@ -110,45 +109,6 @@
             </intent-filter>
         </activity-alias>
 
-        <activity-alias
-            android:name="com.android.devicelockcontroller.activities.DeviceFinancingProvisionNotRequiredLandingActivity"
-            android:exported="false"
-            android:targetActivity=".activities.LandingActivity">
-            <intent-filter>
-                <action android:name="com.android.devicelockcontroller.action.DEVICE_FINANCING_PROVISION_NOT_REQUIRED" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity-alias>
-
-        <activity-alias
-            android:name="com.android.devicelockcontroller.activities.DeviceSubsidyProvisionNotRequiredLandingActivity"
-            android:exported="false"
-            android:targetActivity=".activities.LandingActivity">
-            <intent-filter>
-                <action android:name="com.android.devicelockcontroller.action.DEVICE_SUBSIDY_PROVISION_NOT_REQUIRED" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity-alias>
-
-        <activity
-            android:name="com.android.devicelockcontroller.activities.DeviceEnrollmentActivity"
-            android:theme="@style/Theme.DeviceLock.NoActionBar"
-            android:exported="false">
-            <intent-filter>
-                <action android:name="com.android.devicelockcontroller.action.START_DEVICE_FINANCING_ENROLLMENT"/>
-                <category android:name="android.intent.category.DEFAULT"/>
-            </intent-filter>
-        </activity>
-        <activity-alias
-            android:name="com.android.devicelockcontroller.activities.DeviceSubsidyEnrollmentActivity"
-            android:targetActivity=".activities.DeviceEnrollmentActivity"
-            android:exported="false">
-            <intent-filter>
-                <action android:name="com.android.devicelockcontroller.action.START_DEVICE_SUBSIDY_ENROLLMENT"/>
-                <category android:name="android.intent.category.DEFAULT"/>
-            </intent-filter>
-        </activity-alias>
-
         <activity
             android:name="com.android.devicelockcontroller.activities.DeviceLockSettingsActivity"
             android:theme="@style/Theme.DeviceLock.NoActionBar"
@@ -164,7 +124,7 @@
             android:authorities="${applicationId}.androidx-startup"
             tools:node="remove" />
 
-        <!-- System user only boot completed broadcast receiver -->
+        <!-- System user only boot completed broadcast receiver. This should disabled after provision ready -->
         <receiver
             android:name="com.android.devicelockcontroller.receivers.CheckInBootCompletedReceiver"
             android:exported="false"
@@ -174,20 +134,34 @@
             </intent-filter>
         </receiver>
 
-        <!-- Multi users boot completed broadcast receiver -->
+        <!-- Multi users boot completed broadcast receiver. -->
         <receiver
-            android:name="com.android.devicelockcontroller.receivers.LockTaskBootCompletedReceiver"
+            android:name="com.android.devicelockcontroller.receivers.FinalizationBootCompletedReceiver"
             android:exported="false"
-            android:singleUser="false">
+            android:singleUser="false"
+            android:enabled="false">
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
 
-        <!-- Multi users locked boot completed broadcast receiver -->
+        <!-- Multi users locked boot completed broadcast receiver. This receiver should only be enabled after provision ready -->
         <receiver
             android:name="com.android.devicelockcontroller.receivers.LockedBootCompletedReceiver"
             android:directBootAware="true"
+            android:enabled="false"
+            android:exported="false"
+            android:singleUser="false">
+            <intent-filter>
+                <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Multi users locked boot completed broadcast receiver. This receiver records the boot
+         timestamp -->
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.RecordBootTimestampReceiver"
+            android:directBootAware="true"
             android:exported="false"
             android:singleUser="false">
             <intent-filter>
@@ -195,11 +169,45 @@
             </intent-filter>
         </receiver>
 
+        <!-- Multi users time changed broadcast receiver -->
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.TimeChangedBroadcastReceiver"
+            android:exported="false"
+            android:singleUser="false">
+            <intent-filter>
+                <action android:name="android.intent.action.TIME_SET" />
+            </intent-filter>
+        </receiver>
+
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.ProvisionReadyReceiver"
+            android:exported="false"
+            android:singleUser="false" />
+
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.ResumeProvisionReceiver"
+            android:exported="false"
+            android:singleUser="false" />
+
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.NextProvisionFailedStepReceiver"
+            android:exported="false"
+            android:singleUser="false" />
+
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.ResetDeviceReceiver"
+            android:exported="false"
+            android:singleUser="false" />
+
+        <receiver
+            android:name="com.android.devicelockcontroller.WorkManagerExceptionHandler$WorkFailureAlarmReceiver"
+            android:exported="false"
+            androidprv:systemUserOnly="true" />
+
         <service
             android:name="com.android.devicelockcontroller.DeviceLockControllerService"
             android:directBootAware="true"
-            android:exported="false"
-            androidprv:systemUserOnly="true">
+            android:exported="false">
             <intent-filter>
                 <action android:name="android.app.action.DEVICE_LOCK_CONTROLLER_SERVICE" />
             </intent-filter>
@@ -217,6 +225,15 @@
             android:exported="false"
             android:singleUser="true" />
 
+        <service
+            android:name="com.android.devicelockcontroller.services.DeviceLockKeepAliveService"
+            android:directBootAware="true"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="com.android.devicelock.action.KEEPALIVE" />
+            </intent-filter>
+        </service>
+
     </application>
 
 </manifest>
diff --git a/DeviceLockController/proto/Android.bp b/DeviceLockController/proto/Android.bp
index 4d87bd1..fd4b67b 100644
--- a/DeviceLockController/proto/Android.bp
+++ b/DeviceLockController/proto/Android.bp
@@ -16,19 +16,16 @@
 
 // Generate gRPC client code
 package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "packages_modules_DeviceLock_DeviceLockController_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: [
-        "Android-Apache-2.0",
         "packages_modules_DeviceLock_DeviceLockController_license",
     ],
 }
 
-LITE_PROTO_CMD = "mkdir -p $(genDir)/gen && " +
-    "$(location aprotoc) --java_opt=annotate_code=false " +
-    "-Iexternal/protobuf/src -Ipackages/modules/DeviceLock/DeviceLockController/proto " +
-    "--plugin=protoc-gen-grpc-java=$(location protoc-gen-grpc-java-plugin) " +
-    "--grpc-java_out=lite:$(genDir)/gen $(in) && " +
-    "$(location soong_zip) -o $(out) -C $(genDir)/gen -D $(genDir)/gen"
-
 genrule {
     name: "checkIn-service-stub-lite",
     tools: [
@@ -36,9 +33,15 @@
         "protoc-gen-grpc-java-plugin",
         "soong_zip",
     ],
-    cmd: LITE_PROTO_CMD,
+    cmd: "mkdir -p $(genDir)/gen && " +
+        "$(location aprotoc) --java_opt=annotate_code=false " +
+        "-Iexternal/protobuf/src -Ipackages/modules/DeviceLock/DeviceLockController/proto " +
+        "--plugin=protoc-gen-grpc-java=$(location protoc-gen-grpc-java-plugin) " +
+        "--grpc-java_out=lite:$(genDir)/gen $(locations *.proto) && " +
+        "$(location soong_zip) -o $(out) -C $(genDir)/gen -D $(genDir)/gen",
     srcs: [
         "*.proto",
+        ":libprotobuf-internal-protos",
     ],
     out: [
         "protos.srcjar",
diff --git a/DeviceLockController/proto/checkin_service.proto b/DeviceLockController/proto/checkin_service.proto
index 01ca3f3..71d7a38 100644
--- a/DeviceLockController/proto/checkin_service.proto
+++ b/DeviceLockController/proto/checkin_service.proto
@@ -22,6 +22,7 @@
 import "configuration_info.proto";
 import "device_checkin_info.proto";
 import "device_info.proto";
+import "enrollment_info.proto";
 
 option java_package = "com.android.devicelockcontroller.proto";
 option java_multiple_files = true;
@@ -61,6 +62,12 @@
   // device provided by the Device Lock Android client. The token is only used
   // for GMS devices.
   optional string fcm_registration_token = 3;
+  // The name of the manufacturer of the device.
+  optional string device_manufacturer = 4;
+  // The name of the model of the device.
+  optional string device_model = 5;
+  // The internal name of the device.
+  optional string device_internal_name = 6;
 }
 
 message ClientDeviceIdentifier {
@@ -121,10 +128,10 @@
 message DeviceProvisioningInformation {
   // The configuration information assigned to the device.
   optional ConfigurationInfo configuration_information = 1;
-  // The type of configuration assigned to the device. This is used by the
+  // The type of enrollment assigned to the device. This is used by the
   // Device Lock Android client to determine what type of strings should be
   // shown to the user.
-  optional ConfigurationType configuration_type = 2;
+  optional EnrollmentType enrollment_type = 2;
   // The provision type selected when enrolling the device into a locking
   // program. The Device Lock Android client would use this to determine which
   // provision approach should be used to provision the device.
@@ -176,46 +183,24 @@
 }
 
 // Response to a request to pause device provisioning of an eligible device.
-message PauseDeviceProvisioningResponse {
-  // The Device Lock server decision as to whether or not to force device
-  // provisioning after receiving the pause device provisioning request. If
-  // true, then device provisioning would be forced. Otherwise, if false, then
-  // the device provisioning can still be paused.
-  optional bool force_provisioning = 1;
-}
-
-// Request to report that device provisioning of an eligible device is complete.
-message ReportDeviceProvisionCompleteRequest {
-  // The device identifier that is registered with the Device Lock server that
-  // was provisioned.
-  optional string registered_device_identifier = 1;
-}
-
-// Response to a request reporting that device provisioning of an eligible
-// device is complete.
-message ReportDeviceProvisionCompleteResponse {
-  // An enrollment token the Device Lock Android client can use for future
-  // communication with the Device Lock server post-provisioning.
-  optional string enrollment_token = 1;
-}
+message PauseDeviceProvisioningResponse {}
 
 // The different reasons device provisioning can fail on a device.
 enum ClientProvisionFailureReason {
-  CLIENT_PROVISION_FAILURE_REASON_UNSPECIFIED = 0;
-  // Setup failed to complete on the device.
-  CLIENT_PROVISION_FAILURE_REASON_SETUP_FAILED = 1;
-  // Failed to download the creditor apk.
-  CLIENT_PROVISION_FAILURE_REASON_DOWNLOAD_FAILED = 2;
-  // Verification of the creditor apk failed.
-  CLIENT_PROVISION_FAILURE_REASON_VERIFICATION_FAILED = 3;
-  // Failed to install the creditor apk.
-  CLIENT_PROVISION_FAILURE_REASON_INSTALL_FAILED = 4;
-  // Pre-installed package not found.
-  CLIENT_PROVISION_FAILURE_REASON_PACKAGE_DOES_NOT_EXIST = 5;
-  // Delete apk failed.
-  CLIENT_PROVISION_FAILURE_REASON_DELETE_PACKAGE_FAILED = 6;
-  // Install package for secondary users failed.
-  CLIENT_PROVISION_FAILURE_REASON_INSTALL_EXISTING_FAILED = 7;
+  PROVISION_FAILURE_REASON_UNSPECIFIED = 0;
+  // Provision failed due to play installation task class is unavailable.
+  PROVISION_FAILURE_REASON_PLAY_TASK_UNAVAILABLE = 1;
+  // Provision failed due to play installation failed.
+  PROVISION_FAILURE_REASON_PLAY_INSTALLATION_FAILED = 2;
+  // Provision failed due to country eligibility information unavailable.
+  PROVISION_FAILURE_REASON_COUNTRY_INFO_UNAVAILABLE = 3;
+  // Provision failed due to device is not in an eligible country or region.
+  PROVISION_FAILURE_REASON_NOT_IN_ELIGIBLE_COUNTRY = 4;
+  // Provision failed due to inability to enforce policies.
+  PROVISION_FAILURE_REASON_POLICY_ENFORCEMENT_FAILED = 5;
+  // Provision failed previously and the device has stayed failing beyond
+  // the deadline.
+  PROVISION_FAILURE_REASON_DEADLINE_PASSED = 6;
 }
 
 // The different provision states of a device.
@@ -259,12 +244,8 @@
   // this provision state would be used as the previous provision state in the
   // request.
   optional ClientProvisionState next_client_provision_state = 1;
-  // An enrollment token the Device Lock Android client can use for future
-  // communication with the Device Lock server post-provisioning. This is only
-  // provided if device provisioning was a success.
-  optional string enrollment_token = 2;
   // The number of days left until the device should factory reset because of a failed provision.
   // This number should only be used when next_client_provision_state is
   // CLIENT_PROVISION_STATE_DISMISSIBLE_UI
-  optional uint32 days_left_until_reset = 3;
-}
\ No newline at end of file
+  optional uint32 days_left_until_reset = 2;
+}
diff --git a/DeviceLockController/proto/configuration_info.proto b/DeviceLockController/proto/configuration_info.proto
index c130b4b..34352ac 100644
--- a/DeviceLockController/proto/configuration_info.proto
+++ b/DeviceLockController/proto/configuration_info.proto
@@ -21,12 +21,6 @@
 option java_package = "com.android.devicelockcontroller.proto";
 option java_multiple_files = true;
 
-enum ConfigurationType {
-  CONFIGURATION_TYPE_UNSPECIFIED = 0;
-  CONFIGURATION_TYPE_FINANCED = 1;
-  CONFIGURATION_TYPE_SUBSIDY = 2;
-}
-
 enum ConfigurationStatus {
   CONFIGURATION_STATUS_UNSPECIFIED = 0;
   // The configuration created by a user passed all validation checks and was
diff --git a/DeviceLockController/proto/enrollment_info.proto b/DeviceLockController/proto/enrollment_info.proto
new file mode 100644
index 0000000..b3ad3ea
--- /dev/null
+++ b/DeviceLockController/proto/enrollment_info.proto
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+syntax = "proto2";
+
+package devicelockcontroller;
+
+option java_package = "com.android.devicelockcontroller.proto";
+option java_multiple_files = true;
+
+// The different Device Lock programs in which a device can be enrolled.
+enum EnrollmentType {
+  ENROLLMENT_TYPE_UNSPECIFIED = 0;
+  // Device Lock Financing program.
+  ENROLLMENT_TYPE_FINANCE = 1;
+  // Device Lock Subsidy program.
+  ENROLLMENT_TYPE_SUBSIDY = 2;
+}
+
+message EnrollmentInfo {}
diff --git a/DeviceLockController/proto/finalize_service.proto b/DeviceLockController/proto/finalize_service.proto
index fcd61a0..10398f1 100644
--- a/DeviceLockController/proto/finalize_service.proto
+++ b/DeviceLockController/proto/finalize_service.proto
@@ -35,9 +35,6 @@
   // The device identifier that is registered with the Device Lock server
   // obtained from the Device Lock Check-in service.
   optional string registered_device_identifier = 1;
-  // The enrollment token provided by the Device Lock Check-in service for
-  // future communication post-provisioning.
-  optional string enrollment_token = 2;
 }
 
 message ReportDeviceProgramCompleteResponse {}
\ No newline at end of file
diff --git a/DeviceLockController/res/drawable/ic_action_lock.xml b/DeviceLockController/res/drawable/ic_action_lock.xml
index 80f6a99..2efef18 100644
--- a/DeviceLockController/res/drawable/ic_action_lock.xml
+++ b/DeviceLockController/res/drawable/ic_action_lock.xml
@@ -1,10 +1,9 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="960"
+        android:viewportHeight="960">
   <path
-      android:pathData="M17,8H18C19.1,8 20,8.9 20,10V20C20,21.1 19.1,22 18,22H6C4.9,22 4,21.1 4,20V10C4,8.9 4.9,8 6,8H7V6C7,3.24 9.24,1 12,1C14.76,1 17,3.24 17,6V8ZM12,3C10.34,3 9,4.34 9,6V8H15V6C15,4.34 13.66,3 12,3ZM6,20V10H18V20H6ZM14,15C14,16.1 13.1,17 12,17C10.9,17 10,16.1 10,15C10,13.9 10.9,13 12,13C13.1,13 14,13.9 14,15Z"
-      android:fillColor="#1967D2"
-      android:fillType="evenOdd"/>
+      android:fillColor="@android:color/white"
+      android:pathData="M220,880Q195.25,880 177.63,862.38Q160,844.75 160,820L160,386Q160,361.25 177.63,343.63Q195.25,326 220,326L290,326L290,230Q290,151.15 345.61,95.58Q401.21,40 480.11,40Q559,40 614.5,95.58Q670,151.15 670,230L670,326L740,326Q764.75,326 782.38,343.63Q800,361.25 800,386L800,820Q800,844.75 782.38,862.38Q764.75,880 740,880L220,880ZM220,820L740,820Q740,820 740,820Q740,820 740,820L740,386Q740,386 740,386Q740,386 740,386L220,386Q220,386 220,386Q220,386 220,386L220,820Q220,820 220,820Q220,820 220,820ZM480.17,680Q512,680 534.5,657.97Q557,635.94 557,605Q557,575 534.33,550.5Q511.66,526 479.83,526Q448,526 425.5,550.5Q403,575 403,605.5Q403,636 425.67,658Q448.34,680 480.17,680ZM350,326L610,326L610,230Q610,175.83 572.12,137.92Q534.23,100 480.12,100Q426,100 388,137.92Q350,175.83 350,230L350,326ZM220,820Q220,820 220,820Q220,820 220,820L220,386Q220,386 220,386Q220,386 220,386L220,386Q220,386 220,386Q220,386 220,386L220,820Q220,820 220,820Q220,820 220,820L220,820Z"/>
 </vector>
diff --git a/DeviceLockController/res/drawable/ic_help_24px.xml b/DeviceLockController/res/drawable/ic_help_24px.xml
new file mode 100644
index 0000000..90ea5e9
--- /dev/null
+++ b/DeviceLockController/res/drawable/ic_help_24px.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="20dp"
+    android:height="20dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24">
+    <path
+        android:fillColor="#5F6368"
+        android:fillType="evenOdd"
+        android:pathData="M11.95,18C12.3,18 12.592,17.883 12.825,17.65C13.075,17.4 13.2,17.1 13.2,16.75C13.2,16.4 13.075,16.108 12.825,15.875C12.592,15.625 12.3,15.5 11.95,15.5C11.6,15.5 11.3,15.625 11.05,15.875C10.817,16.108 10.7,16.4 10.7,16.75C10.7,17.1 10.817,17.4 11.05,17.65C11.3,17.883 11.6,18 11.95,18ZM11.05,14.15H12.9C12.9,13.6 12.958,13.167 13.075,12.85C13.208,12.533 13.567,12.1 14.15,11.55C14.583,11.117 14.925,10.708 15.175,10.325C15.425,9.925 15.55,9.45 15.55,8.9C15.55,7.967 15.208,7.25 14.525,6.75C13.842,6.25 13.033,6 12.1,6C11.15,6 10.375,6.25 9.775,6.75C9.192,7.25 8.783,7.85 8.55,8.55L10.2,9.2C10.283,8.9 10.467,8.575 10.75,8.225C11.05,7.875 11.5,7.7 12.1,7.7C12.633,7.7 13.033,7.85 13.3,8.15C13.567,8.433 13.7,8.75 13.7,9.1C13.7,9.433 13.6,9.75 13.4,10.05C13.2,10.333 12.95,10.6 12.65,10.85C11.917,11.5 11.467,11.992 11.3,12.325C11.133,12.658 11.05,13.267 11.05,14.15ZM12,22C10.617,22 9.317,21.742 8.1,21.225C6.883,20.692 5.825,19.975 4.925,19.075C4.025,18.175 3.308,17.117 2.775,15.9C2.258,14.683 2,13.383 2,12C2,10.617 2.258,9.317 2.775,8.1C3.308,6.883 4.025,5.825 4.925,4.925C5.825,4.025 6.883,3.317 8.1,2.8C9.317,2.267 10.617,2 12,2C13.383,2 14.683,2.267 15.9,2.8C17.117,3.317 18.175,4.025 19.075,4.925C19.975,5.825 20.683,6.883 21.2,8.1C21.733,9.317 22,10.617 22,12C22,13.383 21.733,14.683 21.2,15.9C20.683,17.117 19.975,18.175 19.075,19.075C18.175,19.975 17.117,20.692 15.9,21.225C14.683,21.742 13.383,22 12,22ZM12,20C14.233,20 16.125,19.225 17.675,17.675C19.225,16.125 20,14.233 20,12C20,9.767 19.225,7.875 17.675,6.325C16.125,4.775 14.233,4 12,4C9.767,4 7.875,4.775 6.325,6.325C4.775,7.875 4,9.767 4,12C4,14.233 4.775,16.125 6.325,17.675C7.875,19.225 9.767,20 12,20Z" />
+</vector>
diff --git a/DeviceLockController/res/drawable/ic_warning_24px.xml b/DeviceLockController/res/drawable/ic_warning_24px.xml
new file mode 100644
index 0000000..e018487
--- /dev/null
+++ b/DeviceLockController/res/drawable/ic_warning_24px.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ Copyright (C) 2023 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="960"
+        android:viewportHeight="960"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M40,840L480,80L920,840L40,840ZM178,760L782,760L480,240L178,760ZM480,720Q497,720 508.5,708.5Q520,697 520,680Q520,663 508.5,651.5Q497,640 480,640Q463,640 451.5,651.5Q440,663 440,680Q440,697 451.5,708.5Q463,720 480,720ZM440,600L520,600L520,400L440,400L440,600ZM480,500L480,500L480,500L480,500Z"/>
+</vector>
diff --git a/DeviceLockController/res/layout/fragment_device_policies.xml b/DeviceLockController/res/layout/fragment_device_policies.xml
index fef6cff..bd457fa 100644
--- a/DeviceLockController/res/layout/fragment_device_policies.xml
+++ b/DeviceLockController/res/layout/fragment_device_policies.xml
@@ -72,19 +72,13 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toRightOf="parent">
-        <TextView
-            android:id="@+id/footer_text"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textSize="16sp"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent"/>
         <Button
             android:id="@+id/button_next"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="@string/next"
-            app:layout_constraintTop_toBottomOf="@id/footer_text"
+            android:visibility="gone"
+            app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintEnd_toEndOf="parent" />
     </androidx.constraintlayout.widget.ConstraintLayout>
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/DeviceLockController/res/layout/fragment_progress.xml b/DeviceLockController/res/layout/fragment_progress.xml
index 385dec5..b4c30b6 100644
--- a/DeviceLockController/res/layout/fragment_progress.xml
+++ b/DeviceLockController/res/layout/fragment_progress.xml
@@ -48,14 +48,58 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginTop="24dp"
-            android:textSize="16sp"
+            android:textSize="@dimen/provision_screen_sub_header_text_size"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toBottomOf="@+id/header_text"/>
+        <!-- TODO(b/296582802): Review this with UI/UX -->
+        <Chronometer
+            android:id="@+id/countdown_text"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="@dimen/provision_screen_sub_header_text_size"
+            android:countDown="true"
+            android:format="@string/device_reset_timer_notification_title"
+            android:visibility="gone"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/subheader_text" />
     </androidx.constraintlayout.widget.ConstraintLayout>
-    <ProgressBar
-        android:id="@+id/progress_bar"
-        android:layout_width="wrap_content"
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/content"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintTop_toBottomOf="@id/header"
+        app:layout_constraintBottom_toTopOf="@id/bottom"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent">
+        <ProgressBar
+            android:id="@+id/progress_bar"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"/>
+    </androidx.constraintlayout.widget.ConstraintLayout>
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/bottom"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/header"/>
+        android:visibility="gone"
+        app:layout_constraintTop_toBottomOf="@id/content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent">
+        <Button
+            android:id="@+id/button_exit"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/exit"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent" />
+        <Button
+            android:id="@+id/button_retry"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/retry"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+    </androidx.constraintlayout.widget.ConstraintLayout>
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/DeviceLockController/res/layout/fragment_provision_info.xml b/DeviceLockController/res/layout/fragment_provision_info.xml
index 459ea80..c9ac059 100644
--- a/DeviceLockController/res/layout/fragment_provision_info.xml
+++ b/DeviceLockController/res/layout/fragment_provision_info.xml
@@ -85,6 +85,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="@string/previous"
+            android:visibility="gone"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toStartOf="parent" />
         <Button
@@ -92,6 +93,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="@string/next"
+            android:visibility="gone"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent" />
     </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/DeviceLockController/res/layout/fragment_provision_not_required.xml b/DeviceLockController/res/layout/fragment_provision_not_required.xml
deleted file mode 100644
index 642e90b..0000000
--- a/DeviceLockController/res/layout/fragment_provision_not_required.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2023 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.
-  -->
-
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_margin="16dp">
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/header"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toTopOf="@id/content"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent">
-        <ImageView
-            android:id="@+id/header_icon"
-            android:layout_width="40dp"
-            android:layout_height="40dp"
-            android:scaleType="fitCenter"
-            android:contentDescription="@string/header_icon_content_description"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent"/>
-        <TextView
-            android:id="@+id/header_text"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="24dp"
-            android:textSize="32sp"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/header_icon"/>
-        <TextView
-            android:id="@+id/subheader_text"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="24dp"
-            android:textSize="16sp"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/header_text" />
-    </androidx.constraintlayout.widget.ConstraintLayout>
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/content"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        app:layout_constraintTop_toBottomOf="@id/header"
-        app:layout_constraintBottom_toTopOf="@id/bottom"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent">
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/recyclerview_provision_info"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"
-            android:layout_marginTop="16dp"
-            app:layoutManager="LinearLayoutManager"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toBottomOf="parent"/>
-    </androidx.constraintlayout.widget.ConstraintLayout>
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/bottom"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        app:layout_constraintTop_toBottomOf="@id/content"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent">
-        <Button
-            android:id="@+id/button_ok"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/ok"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"/>
-    </androidx.constraintlayout.widget.ConstraintLayout>
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/DeviceLockController/res/layout/reset_timer_notif_large.xml b/DeviceLockController/res/layout/reset_timer_notif_large.xml
new file mode 100644
index 0000000..cc87c21
--- /dev/null
+++ b/DeviceLockController/res/layout/reset_timer_notif_large.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 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.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <Chronometer
+        android:id="@+id/reset_timer_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:countDown="true"
+        android:singleLine="true"
+        android:textAppearance="@style/TextAppearance.Compat.Notification.Title" />
+
+    <TextView
+        android:id="@+id/reset_content"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="@style/TextAppearance.Compat.Notification" />
+
+</LinearLayout>
diff --git a/DeviceLockController/res/layout/activity_device_enrollment.xml b/DeviceLockController/res/layout/reset_timer_notif_small.xml
similarity index 66%
rename from DeviceLockController/res/layout/activity_device_enrollment.xml
rename to DeviceLockController/res/layout/reset_timer_notif_small.xml
index 71911b9..6ec1bd9 100644
--- a/DeviceLockController/res/layout/activity_device_enrollment.xml
+++ b/DeviceLockController/res/layout/reset_timer_notif_small.xml
@@ -16,12 +16,16 @@
   -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              android:orientation="vertical">
-    <androidx.fragment.app.FragmentContainerView
-        android:id="@+id/device_enrollment_info_fragment"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <Chronometer
+        android:id="@+id/reset_timer_title"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:name="com.android.devicelockcontroller.activities.DeviceEnrollmentInfoFragment"/>
+        android:layout_height="wrap_content"
+        android:countDown="true"
+        android:singleLine="true"
+        android:textAppearance="@style/TextAppearance.Compat.Notification.Title" />
+
 </LinearLayout>
diff --git a/DeviceLockController/res/values-af/strings.xml b/DeviceLockController/res/values-af/strings.xml
index 0b8f865..c4670d0 100644
--- a/DeviceLockController/res/values-af/strings.xml
+++ b/DeviceLockController/res/values-af/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Enige sluit- of ontsluitversoeke deur <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"As die <xliff:g id="CREDITOR_APP">%1$s</xliff:g>-app nie beskikbaar is nie"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Oopbronlisensies"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Die ander bestuurvermoëns in "<b>"Instellings &gt; Sekuriteit &gt; Inligting oor bestuurde toestel"</b>" is nie op hierdie toestel van toepassing nie"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Die bestuurvermoëns in Sekuriteitinstellings se afdeling oor gefinansierde toestel is nie op hierdie toestel van toepassing nie"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Hierdie toestel word verskaf deur <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Die Kiosk-app sal afgelaai en outomaties geïnstalleer word"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Die Kiosk-app sal vir hierdie gebruiker geïnstalleer word"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan hierdie toestel beperk as jy ’n betaling mis"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan die toestel beperk as jy ’n betaling mis. Lees die <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>bepalings en voorwaardes<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> vir besonderhede."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan hierdie toestel beperk as jy nie die nodige betalings doen nie. Lees die <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>bepalings en voorwaardes<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> vir besonderhede."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan hierdie toestel beperk as die eienaar nie betalings doen nie"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontak <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g> vir hulp."</string>
     <string name="previous" msgid="5241891780917802570">"Vorige"</string>
     <string name="next" msgid="8248291863254324326">"Volgende"</string>
     <string name="start" msgid="2842214844667658537">"Begin"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Inligting"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Opstelinginligting"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Skryf jou toestel in"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Jy kan jou toestel nou vir <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> se finansieringprogram inskryf"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Jy kan jou toestel nou vir <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> se finansiesprogram inskryf"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Jy kan jou toestel nou vir <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> se subsidieprogram inskryf"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Jy is in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> se subsidieprogram"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Toestelinskrywing"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan instellings op hierdie toestel verander"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Kom meer te wete"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Inligting oor gefinansierde toestel"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Jou kredietverskaffer kan instellings verander en die Kiosk-app op die toestel installeer.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan hierdie toestel beperk as jy nie die nodige betalings doen nie of ophou om <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> se SIM te gebruik.\n\nKontak <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> om meer te wete te kom."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan instellings verander en die Kiosk-app op die toestel installeer.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kan jou toestel beperk as jy ’n betaling mis.\n\nKontak <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> om meer te wete te kom."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan instellings verander en die Kiosk-app op die toestel installeer.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kan ook hierdie toestel beperk as jy ’n betaling mis of ophou om <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> se SIM te gebruik.\n\nKontak <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> om meer te wete te kom."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Voordat jy jou toestel afbetaal het, kan jy nie:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Jou toestel na veilige modus herselflaai"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Verander datum, tyd en tydsones"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Gebruik ontwikkelaaropsies"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"As iets fout is met jou toestel, kan <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Jy kan die <xliff:g id="KIOSK_APP">%1$s</xliff:g>-app deïnstalleer"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Om hulp te kry:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontak <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Stel op"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Toestel sal oor 1 dag teruggestel word}other{Toestel sal oor # dae teruggestel word}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Toestel sal oor <xliff:g id="TIMER">%s</xliff:g> teruggestel word"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Alle toesteldata sal uitgevee word. Kontak <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> vir hulp met die inskrywing van jou toestel"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Laat asseblief kennisgewings van Toestelslot af toe om aan te hou om die inskrywing van die toestel uit te stel."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Kon nie finansiering opstel nie"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Klik hier vir maniere om jou finansier te kontak. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Kom meer te wete<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Gaan uit"</string>
+    <string name="retry" msgid="7497287909193345356">"Herprobeer"</string>
 </resources>
diff --git a/DeviceLockController/res/values-am/strings.xml b/DeviceLockController/res/values-am/strings.xml
index 3f217dc..c12c0a5 100644
--- a/DeviceLockController/res/values-am/strings.xml
+++ b/DeviceLockController/res/values-am/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"ማናቸውም ከ<xliff:g id="CREDITOR_APP">%1$s</xliff:g> የሚመጡ የመቆለፍ ወይም የመክፈት ጥያቄዎች"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> መተግበሪያው የማይገኝ ከሆነ"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"የክፍት ምንጭ ፈቃዶች"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"ሌላው የአስተዳደር ችሎታዎች በ"<b>"ቅንብሮች &gt; ደህንነት &gt; የሚተዳደር የመሣሪያ መረጃ"</b>" በዚህ መሣሪያ ላይ አይተገበሩም"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"በደህንነት ቅንብሮች ፋይናንስ መሣሪያ ክፍል ውስጥ ያሉት የማስተዳደር ችሎታዎች በዚህ መሣሪያ ላይ አይተገበሩም።"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"ይህ መሣሪያ በ<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> የሚቀርብ ነው"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"የKiosk መተግበሪያ በራስ ሰር ይወርዳል እና ይጫናል"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"የKiosk መተግበሪያ ለዚህ ተጠቃሚ ይጫናል"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"ክፍያ ካለፈብዎት <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ይህን መሣሪያ ሊገድብ ይችላል"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"እርስዎ ክፍያ ካሳለፉ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> መሣሪያውን መገደብ ይችላሉ። ለዝርዝሮች <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>የአገልግሎት ውል<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> ይመልከቱ።"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"እርስዎ አስፈላጊዎቹን ክፍያዎች ካልፈጸሙ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ይህን መሣሪያ ሊገድብ ይችላል። ለዝርዝሮች <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>የአገልግሎት ውል<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> ይመልከቱ።"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"ባለቤቱ ክፍያዎችን ካልፈጸመ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ይህን መሣሪያ ሊገድብ ይችላል"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"እገዛ ለማግኘት፣ <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ን ያግኙ <xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>።"</string>
     <string name="previous" msgid="5241891780917802570">"ቀዳሚ"</string>
     <string name="next" msgid="8248291863254324326">"ቀጣይ"</string>
     <string name="start" msgid="2842214844667658537">"ጀምር"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"መረጃ"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"የአቅርቦት መረጃ"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"መሣሪያዎን ያስመዝግቡ"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"አሁን መሣሪያዎን በ<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> የፋይናንስ ፕሮግራም ውስጥ መመዝገብ ይችላሉ"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"አሁን መሣሪያዎን በ<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> የፋይናንስ ፕሮግራም ውስጥ ማስመዝገብ ይችላሉ"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"አሁን መሣሪያዎን በ<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> የድጎማ ፕሮግራም ውስጥ መመዝገብ ይችላሉ"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"የ<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> የድጋፍ ፕሮግራም ላይ ነዎት"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"የመሣሪያ ምዝገባ"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> በዚህ መሣሪያ ላይ ያሉ ቅንብሮችን መለወጥ ይችላሉ"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"የበለጠ ለመረዳት"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"የፋይናንስ ድጋፍ የተደረገለት መሣሪያ መረጃ"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"የእርስዎ ክሬዲት አቅራቢ ቅንብሮችን መለወጥ እና የkiosk መተግበሪያውን በመሣሪያው ላይ መጫን ይችላል።\n\nአግባብ ክፍያዎችን የማይፈጽሙ ወይም የ<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ሲምን መጠቀም የሚያቆሙ ከሆነ <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ይህን መሣሪያ ሊገድብ ይችላል።\n\nየበለጠ ለመረዳት <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>ን ያግኙ።"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ቅንብሮችን መለወጥ እና የkiosk መተግበሪያውን በመሣሪያው ላይ መጫን ይችላሉ።\n\nክፍያ ካመለጠዎት <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> መሣሪያዎን መገደብ ይችላሉ።\n\nየበለጠ ለመረዳት <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>ን ያነጋግሩ።"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ቅንብሮችን መለወጥ እና የkiosk መተግበሪያውን በመሣሪያው ላይ መጫን ይችላሉ።\n\nእንዲሁም ክፍያ ካመለጠዎት ወይም የ<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ሲምን መጠቀም ካቆሙ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ይህን መሣሪያ ሊገድቡ ይችላሉ።\n\nየበለጠ ለመረዳት <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>ን ያነጋግሩ።"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"ለመሣሪያዎ እስከከፈሉ ድረስ የሚከተለውን ማድረግ አይችሉም፦"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"መሣሪያዎን በሚያስተማምን ሁነታ ዳግም ያስነሱት"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"ቀን፣ ሰዓት እና የሰዓት ሰቆችን ይቀይሩ"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"የገንቢ አማራጮችን ይጠቀሙ"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"መሣሪያዎ ላይ ችግር ከተፈጠረ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> የሚከተሉትን ማድረግ ይችላል፦"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"የ<xliff:g id="KIOSK_APP">%1$s</xliff:g> መተግበሪያን ማራገፍ ይችላሉ"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"እገዛ ለማግኘት፦"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ን ያነጋግሩ<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"አቅርቦት"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{መሣሪያ በ1 ቀን ውስጥ ዳግም ይጀምራል}one{መሣሪያ በ# ቀን ውስጥ ዳግም ይጀምራል}other{መሣሪያ በ# ቀናት ውስጥ ዳግም ይጀምራል}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"መሣሪያ <xliff:g id="TIMER">%s</xliff:g> ውስጥ ዳግም ይጀምራል"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ሁሉም የመሣሪያ ውሂብ ይሰረዛል። መሣሪያዎን መመዝገብ ላይ እገዛ ለማግኘት <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ን ያግኙ"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"የመሣሪያውን ምዝገባ መላክ ለመቀጠል እባክዎ ከDeviceLock ማሳወቂያ ይፍቀዱ።"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"የፋይናንስ አቅርቦት አልተሳካም"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"የፋይናንስ አስተዳዳሪዎን የሚያገኙባቸውን መንገዶች ለማግኘት እባክዎ እዚህ ጠቅ ያድርጉ። <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>የበለጠ ለመረዳት<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"ውጣ"</string>
+    <string name="retry" msgid="7497287909193345356">"እንደገና ሞክር"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ar/strings.xml b/DeviceLockController/res/values-ar/strings.xml
index a963f35..88e92d9 100644
--- a/DeviceLockController/res/values-ar/strings.xml
+++ b/DeviceLockController/res/values-ar/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"أي طلبات لقفل الجهاز أو فتح قفله من تطبيق \"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>\""</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"إذا لم يكن تطبيق \"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>\" متاحًا"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"تراخيص البرامج المفتوحة المصدر"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"لا تسري على هذا الجهاز ميزات الإدارة الأخرى المُدرجة في "<b>"الإعدادات &gt; الأمان &gt; معلومات الجهاز المُدار"</b>"."</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"لا تسري على هذا الجهاز ميزات الإدارة المُدرجة في قسم الجهاز المموَّل ضمن إعدادات الأمان."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"يتم توفير هذا الجهاز من قِبل \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\""</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"سيتم تلقائيًا تنزيل تطبيق Kiosk وتثبيته."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"سيتم تثبيت تطبيق Kiosk على جهاز هذا المستخدِم."</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"بإمكان \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" فرض قيود على هذا الجهاز في حال عدم تسديد إحدى الدفعات."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"بإمكان \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" فرض قيود على الجهاز في حال عدم تسديد إحدى الدفعات. لمعرفة التفاصيل، يُرجى الاطّلاع على <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>الأحكام والشروط<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"بإمكان \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" فرض قيود على هذا الجهاز في حال عدم تسديد الدفعات المستحقّة. لمعرفة التفاصيل، يُرجى الاطّلاع على <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>الأحكام والشروط<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"بإمكان \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" فرض قيود على هذا الجهاز في حال عدم تسديد المالك للدفعات المستحقّة."</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"للحصول على المساعدة، <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>يمكنك التواصل مع \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"السابق"</string>
     <string name="next" msgid="8248291863254324326">"التالي"</string>
     <string name="start" msgid="2842214844667658537">"بدء"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"معلومات"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"معلومات حول التمويل"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"تسجيل الجهاز"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"يمكنك الآن تسجيل جهازك في برنامج التمويل المقدَّم من \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"يمكنك الآن تسجيل جهازك في برنامج التمويل المقدَّم من \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"يمكنك الآن تسجيل جهازك في برنامج الدعم المالي المقدَّم من \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"لقد انضممت إلى برنامج الدعم المالي من \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\""</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"تسجيل الجهاز"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"بإمكان \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" تغيير الإعدادات على هذا الجهاز."</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"مزيد من المعلومات"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"معلومات الجهاز المموَّل"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"يمكن لشركة بيع الأجهزة بالائتمان تغيير الإعدادات وتثبيت تطبيق Kiosk على هذا الجهاز.\n\nتجدر الإشارة إلى أنّه لدى \"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>\" الحق في فرض قيود على هذا الجهاز في حال عدم تسديد إحدى الدفعات المستحقّة أو التوقّف عن استخدام شريحة SIM التابعة لشركة \"<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>\".\n\nللحصول على مزيد من المعلومات، يُرجى التواصل مع \"<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\"."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"بإمكان \"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>\" تغيير الإعدادات وتثبيت تطبيق Kiosk على الجهاز.\n\nفي حال عدم تسديد إحدى الدفعات، بإمكان \"<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>\" فرض قيود على جهازك.\n\nيمكنك التواصل مع فريق \"<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\" لمعرفة مزيد من المعلومات."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"بإمكان \"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>\" تغيير الإعدادات وتثبيت تطبيق Kiosk على الجهاز.\n\nيمكن لشركة \"<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>\" أيضًا فرض قيود على جهازك في حال عدم تسديد إحدى الدفعات أو التوقّف عن استخدام شريحة SIM التابعة لـ \"<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\".\n\nيمكنك التواصل مع فريق \"<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>\" لمعرفة مزيد من المعلومات."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"إلى حين دفع الرسوم المستحقّة للجهاز، لن يكون بإمكانك:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"إعادة تشغيل الجهاز باستخدام ميزة \"الوضع الآمن\""</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"تغيير التاريخ والوقت والمناطق الزمنية"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"استخدام ميزة \"خيارات المطوّرين\""</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"إذا حدث خطأ في جهازك، سيكون بإمكان \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\":"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"يمكنك إلغاء تثبيت تطبيق \"<xliff:g id="KIOSK_APP">%1$s</xliff:g>\"."</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"للحصول على مساعدة:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>التواصل مع \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"التمويل"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{ستتم إعادة ضبط الجهاز بعد يوم واحد.}zero{ستتم إعادة ضبط الجهاز بعد # يوم.}two{ستتم إعادة ضبط الجهاز بعد يومَين.}few{ستتم إعادة ضبط الجهاز بعد # أيام.}many{ستتم إعادة ضبط الجهاز بعد # يومًا.}other{ستتم إعادة ضبط الجهاز بعد # يوم.}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"ستتم إعادة ضبط الجهاز بعد ‎<xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"سيتم حذف جميع البيانات على الجهاز. للحصول على المساعدة في تسجيل جهازك، يُرجى التواصل مع \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"يُرجى السماح بإشعارات DeviceLock لمواصلة تأجيل عملية تسجيل الجهاز."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"تعذَّر توفير التمويل"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"يُرجى النقر هنا لمعرفة طُرق التواصل مع جهة التمويل الخاصة بك. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>مزيد من المعلومات<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"خروج"</string>
+    <string name="retry" msgid="7497287909193345356">"إعادة المحاولة"</string>
 </resources>
diff --git a/DeviceLockController/res/values-as/strings.xml b/DeviceLockController/res/values-as/strings.xml
index dff37c6..dca77e5 100644
--- a/DeviceLockController/res/values-as/strings.xml
+++ b/DeviceLockController/res/values-as/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>ৰ পৰা অহা কোনো লক অথবা আনলক কৰাৰ অনুৰোধ"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"যদি <xliff:g id="CREDITOR_APP">%1$s</xliff:g> এপ্‌টো উপলব্ধ নহয়"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"মুক্ত উৎসৰ অনুজ্ঞাপত্ৰ"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"ছেটিং &gt; সুৰক্ষা &gt; পৰিচালিত ডিভাইচৰ তথ্য"</b>"ত থকা অন্য পৰিচালনাৰ সক্ষমতাসমূহ এই ডিভাইচটোত প্ৰযোজ্য নহয়"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"সুৰক্ষা সম্পৰ্কীয় ছেটিঙৰ বিত্তীয় সহায় পোৱা ডিভাইচৰ শাখাটোত থকা পৰিচালনাৰ সক্ষমতা এই ডিভাইচটোত প্ৰযোজ্য নহয়।"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"এই ডিভাইচটো <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>এ প্ৰদান কৰিছে"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk এপ্‌টো স্বয়ংক্ৰিয়ভাৱে ডাউনল’ড কৰি ইনষ্টল কৰা হ’ব"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"এই ব্যৱহাৰকাৰীগৰাকীৰ বাবে Kiosk এপ্‌টো ইনষ্টল কৰা হ’ব"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"আপুনি এবাৰ পৰিশোধ নকৰিলে <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>এ এই ডিভাইচটো সীমাবদ্ধ কৰিব পাৰে"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"আপুনি পৰিশোধ নকৰিলে <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>এ এই ডিভাইচটো সীমাবদ্ধ কৰিব পাৰে। সবিশেষৰ বাবে, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>নিয়ম আৰু চৰ্তাৱলী<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> চাওক।"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"যদি আপুনি আৱশ্যকীয় পৰিশোধসমূহ নকৰে <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>এ এই ডিভাইচটো সীমাবদ্ধ কৰিব পাৰে। সবিশেষৰ বাবে, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>নিয়ম আৰু চৰ্তাৱলী<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> চাওক।"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"গৰাকীয়ে পৰিশোধ নকৰিলে <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>এ এই ডিভাইচটো সীমাবদ্ধ কৰিব পাৰে"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"সহায়ৰ বাবে, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ৰ সৈতে সহযোগ কৰক<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>।"</string>
     <string name="previous" msgid="5241891780917802570">"পূৰ্বৱৰ্তী"</string>
     <string name="next" msgid="8248291863254324326">"পৰৱৰ্তী"</string>
     <string name="start" msgid="2842214844667658537">"আৰম্ভ কৰক"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"তথ্য"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"প্ৰ’ভিজনৰ তথ্য"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"আপোনাৰ ডিভাইচটো পঞ্জীয়ন কৰক"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"আপুনি এতিয়া নিজৰ ডিভাইচটো <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ৰ বিত্তীয় সহায় প্ৰদান কৰা প্ৰ’গ্ৰামত পঞ্জীয়ন কৰিব পাৰে"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"আপুনি এতিয়া নিজৰ ডিভাইচটো <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ৰ বিত্তীয় সহায় প্ৰদান কৰা প্ৰ’গ্ৰামত পঞ্জীয়ন কৰিব পাৰে"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"আপুনি এতিয়া নিজৰ ডিভাইচটো <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ৰ ৰাজসাহায্য প্ৰ’গ্ৰামত পঞ্জীয়ন কৰিব পাৰে"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ৰ ৰাজসাহায্য প্ৰ’গ্ৰামত আছে"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ডিভাইচৰ পঞ্জীয়ন"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>এ এই ডিভাইচটোত ছেটিং সলনি কৰিব পাৰে"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"অধিক জানক"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"বিত্তীয় সহায় প্ৰাপ্ত ডিভাইচৰ তথ্য"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"আপোনাৰ ক্ৰেডিট প্ৰদানকাৰীয়ে ছেটিং সলনি কৰিব আৰু ডিভাইচটোত Kiosk এপ্‌টো ইনষ্টল কৰিব পাৰে।\n\nআপুনি আৱশ্যকীয় পৰিশোধসমূহ নকৰিলে অথবা <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>ৰ ছিমখন ব্যৱহাৰ কৰাটো বন্ধ নকৰিলে <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>এ এই ডিভাইচটো সীমাবদ্ধ কৰিব পাৰে।\n\nঅধিক জানিবলৈ, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>ৰ সৈতে সীমাবদ্ধ কৰক।"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>এ ছেটিং সলনি কৰিব আৰু ডিভাইচটোত Kiosk এপ্‌টো ইনষ্টল কৰিব পাৰে।\n\nআপুনি যদি কোনোবাটো পৰিশোধ নকৰে, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>এ আপোনাৰ ডিভাইচটো প্ৰতিবন্ধিত কৰিব পাৰে।\n\nঅধিক জানিবলৈ, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>ৰ সৈতে যোগাযোগ কৰক।"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>এ ছেটিং সলনি কৰিব আৰু ডিভাইচটোত Kiosk এপ্‌টো ইনষ্টল কৰিব পাৰে।\n\nআপুনি যদি কোনোবাটো পৰিশোধ নকৰে অথবা <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>ৰ ছিম ব্যৱহাৰ কৰা বন্ধ কৰে, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>এ এই ডিভাইচটো প্ৰতিবন্ধিতও কৰিব পাৰে।\n\nঅধিক জানিবলৈ, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>ৰ সৈতে যোগাযোগ কৰক।"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"আপুনি আপোনাৰ ডিভাইচটোৰ বাবে পৰিশোধ নকৰালৈকে, এই কামসমূহ কৰিব নোৱাৰে:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"সুৰক্ষিত ম’ডত আপোনাৰ ডিভাইচটো ৰিবুট কৰা"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"তাৰিখ, সময় আৰু সময় মণ্ডল সলনি কৰিব পাৰে"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"বিকাশকৰ্তাৰ বিকল্পসমূহ ব্যৱহাৰ কৰিব পাৰে"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"যদি কোনোবাই আপোনাৰ ডিভাইচটো অপব্যৱহাৰ কৰে, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>এ:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"আপুনি <xliff:g id="KIOSK_APP">%1$s</xliff:g> এপ্‌টো আনইনষ্টল কৰিব পাৰে"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"সহায় পাবলৈ:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>ৰ সৈতে যোগাযোগ কৰক"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"প্ৰ’ভিজন"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{১ দিনত ডিভাইচটো ৰিছেট হ’ব}one{# দিনত ডিভাইচটো ৰিছেট হ’ব}other{# দিনত ডিভাইচটো ৰিছেট হ’ব}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"<xliff:g id="TIMER">%s</xliff:g>ত ডিভাইচটো ৰিছেট হ’ব"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ডিভাইচৰ আটাইবোৰ ডেটা মচা হ’ব। আপোনাৰ ডিভাইচ পঞ্জীয়ন কৰাত সহায় পাবলৈ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ৰ সৈতে যোগাযোগ কৰক"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"ডিভাইচটোৰ পঞ্জীয়ন পিছুৱাই দিয়াটো অব্যাহত ৰাখিবলৈ  অনুগ্ৰহ কৰি DeviceLockৰ জাননীক অনুমতি দিয়ক।"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"বিত্তীয় সহায় প্ৰদান কৰাৰ প্ৰ’ভিজনিং বিফল হৈছে"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"আপোনাৰ বিত্তৰ যোগান ধৰোঁতাৰ সৈতে যোগাযোগ কৰাৰ উপায়সমূহ জানিবলৈ অনুগ্ৰহ কৰি ইয়াত ক্লিক কৰক। <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>অধিক জানক<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"বাহিৰ ওলাওক"</string>
+    <string name="retry" msgid="7497287909193345356">"পুনৰ চেষ্টা কৰক"</string>
 </resources>
diff --git a/DeviceLockController/res/values-az/strings.xml b/DeviceLockController/res/values-az/strings.xml
index a6347fd..c568006 100644
--- a/DeviceLockController/res/values-az/strings.xml
+++ b/DeviceLockController/res/values-az/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> tətbiqinin kilidləmə və ya kilidaçma sorğuları"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> tətbiqi əlçatan olmadıqda"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Açıq mənbə lisenziyaları"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"Ayarlar &gt; Təhlükəsizlik &gt; İdarə edilən cihaz məlumatı"</b>" bölməsindəki digər idarəetmə imkanları bu cihaza tətbiq edilmir"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Təhlükəsizlik ayarlarının maliyyələşdirilən cihaz bölməsindəki idarəetmə imkanları bu cihaza tətbiq edilmir."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Bu cihaz <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> tərəfindən təmin edilib"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Köşk tətbiqi avtomatik endiriləcək və quraşdırılacaq"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Bu istifadəçi üçün Köşk tətbiqi quraşdırılacaq"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Ödəniş etməsəniz, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu cihazı məhdudlaşdıra bilər"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Ödəniş etməsəniz, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> cihazı məhdudlaşdıra bilər. Detallar üçün <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Şərt və Müddəalara<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> baxın."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Zəruri ödənişləri etməsəniz, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu cihazı məhdudlaşdıra bilər. Detallar üçün <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Şərt və Müddəalara<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> baxın."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Sahib ödəniş etməsə, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu cihazı məhdudlaşdıra bilər"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Kömək üçün <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ilə əlaqə saxlayın<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Əvvəlki"</string>
     <string name="next" msgid="8248291863254324326">"Növbəti"</string>
     <string name="start" msgid="2842214844667658537">"Başlayın"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Məlumat"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Təminat məlumatı"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Cihazı qeydiyyatdan keçirin"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> maliyyə proqramında cihazı qeydiyyatdan keçirə bilərsiniz"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> maliyyə proqramında cihazı qeydiyyatdan keçirə bilərsiniz"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> subsidiya proqramında cihazı qeydiyyatdan keçirə bilərsiniz"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> subsidiya proqramındasınız"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Cihaz qeydiyyatı"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu cihazda ayarları dəyişə bilər"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Ətraflı məlumat"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Maliyyələşdirilən cihaz məlumatı"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Kredit təminatçısı cihazda ayarları dəyişə və Köşk tətbiqini quraşdıra bilər.\n\nZəruri ödənişləri etməsəniz, yaxud <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIM-dən istifadəni dayandırsanız, <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> bu cihazı məhdudlaşdıra bilər.\n\nƏtraflı məlumat üçün <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ilə əlaqə saxlayın."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ayarları dəyişə və cihazda Köşk tətbiqini quraşdıra bilər.\n\nÖdəniş etməsəniz, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> cihazı məhdudlaşdıra bilər.\n\nƏtraflı məlumat üçün <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ilə əlaqə saxlayın."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ayarları dəyişə və cihazda Köşk tətbiqini quraşdıra bilər.\n\nÖdəniş etməsəniz, yaxud <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM-dən istifadəni dayandırsanız, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> bu cihazı məhdudlaşdıra bilər.\n\nƏtraflı məlumat üçün <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> ilə əlaqə saxlayın."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Cihaz ödənişini etməsəniz, aşağıdakıları edə bilməzsiniz:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Cihazı güvənli rejimdə yenidən yükləmək"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Tarix, vaxt və saat qurşağını dəyişmək"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Developer seçimlərindən istifadə"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Cihazda xəta olarsa, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bunları edə bilər:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> tətbiqini sistemdən silə bilərsiniz"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Kömək üçün:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ilə əlaqə saxlayın<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Təminat"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Cihaz 1 gündən sonra sıfırlanacaq}other{Cihaz # gündən sonra sıfırlanacaq}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Cihaz <xliff:g id="TIMER">%s</xliff:g> sonra sıfırlanacaq"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Bütün cihaz datası silinəcək. Cihaz qeydiyyatı üzrə kömək üçün <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ilə əlaqə saxlayın"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Cihaz qeydiyyatını təxirə salmaq üçün DeviceLock bildirişinə icazə verin."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Maliyyə təminatı alınmadı"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Maliyyəçi ilə əlaqə üsulları üçün bura klikləyin. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Ətraflı məlumat<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Çıxın"</string>
+    <string name="retry" msgid="7497287909193345356">"Təkrar sınayın"</string>
 </resources>
diff --git a/DeviceLockController/res/values-b+sr+Latn/strings.xml b/DeviceLockController/res/values-b+sr+Latn/strings.xml
index ec930d3..c737da3 100644
--- a/DeviceLockController/res/values-b+sr+Latn/strings.xml
+++ b/DeviceLockController/res/values-b+sr+Latn/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Svi zahtevi za zaključavanje i otključavanje koje šalje <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Ako aplikacija <xliff:g id="CREDITOR_APP">%1$s</xliff:g> nije dostupna"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licence otvorenog koda"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Ostale mogućnosti upravljanja u odeljku "<b>"Podešavanja &gt; Bezbednost &gt; Informacije o uređaju kojim se upravlja"</b>" nisu primenjive na ovaj uređaj"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Mogućnosti upravljanja u odeljku finansiranog uređaja u podešavanjima bezbednosti ne primenjuju se na ovaj uređaj."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Ovaj uređaj pruža <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk aplikacija će se automatski preuzeti i instalirati"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kiosk aplikacija će biti instalirana za ovog korisnika"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može da ograniči ovaj uređaj ako propustite plaćanje"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može da postavi ograničenje za uređaj ako propustite plaćanje. Detalje potražite u <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>uslovima i odredbama<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može da ograniči ovaj uređaj ako ne izvršite neophodna plaćanja. Detalje potražite u <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>uslovima i odredbama<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može da ograniči ovaj uređaj ako vlasnik ne izvrši plaćanja"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Obratite se operateru <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g> da biste dobili pomoć."</string>
     <string name="previous" msgid="5241891780917802570">"Prethodno"</string>
     <string name="next" msgid="8248291863254324326">"Dalje"</string>
     <string name="start" msgid="2842214844667658537">"Pokreni"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informacije"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Dodeljivanje"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Registrujte uređaj"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Sada možete da registrujete uređaj za <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> finansijski program"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Sada možete da registrujete uređaj za <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> finansijski program"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Sada možete da registrujete uređaj za <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> program subvencija"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Uključeni ste u <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> program subvencija"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Registracija uređaja"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može da menja podešavanja na ovom uređaju"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Saznajte više"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informacije o finansiranom uređaju"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Dobavljač kredita može da promeni podešavanja i instalira kiosk aplikaciju na uređaju.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> može da ograniči uređaj ako ne izvršite neophodna plaćanja ili prestanete da koristite <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIM.\n\nDa biste saznali više, obratite se: <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> može da promeni podešavanja i instalira kiosk aplikaciju na uređaju.\n\nAko propustite plaćanje, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> može da ograniči vaš uređaj.\n\nDa biste saznali više, obratite se dobavljaču usluge <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> može da promeni podešavanja i instalira kiosk aplikaciju na uređaju.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> može da ograniči ovaj uređaj propustite plaćanje ili prestanete da koristite <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM.\n\nDa biste saznali više, obratite se dobavljaču usluge <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Dok ne platite za uređaj, ne možete:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Restartujte uređaj u bezbednom režimu"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Promenite datum, vreme i vremenske zone"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Koristite opcije za programere"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Ako nešto nije u redu s uređajem, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Možete da deinstalirate aplikaciju <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Za pomoć:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Obratite se operateru <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Dodeljivanje"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Uređaj će se resetovati za 1 dan}one{Uređaj će se resetovati za # dan}few{Uređaj će se resetovati za # dana}other{Uređaj će se resetovati za # dana}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Uređaj će se resetovati za <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Svi podaci sa uređaja će biti izbrisani. Za pomoć pri registrovanju uređaja, obratite se: <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Dozvolite obaveštenja Zaključavanja uređaja da biste nastavili sa odlaganjem registracije uređaja."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Dodeljivanje finansiranja nije uspelo"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Kliknite ovde da biste videli načine za stupanje u kontakt sa finansijerom. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Saznajte više<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Izađi"</string>
+    <string name="retry" msgid="7497287909193345356">"Probaj ponovo"</string>
 </resources>
diff --git a/DeviceLockController/res/values-be/strings.xml b/DeviceLockController/res/values-be/strings.xml
index 058e1b7..1d78f50 100644
--- a/DeviceLockController/res/values-be/strings.xml
+++ b/DeviceLockController/res/values-be/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Любыя запыты блакіроўкі і разблакіроўкі ад праграмы \"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>\""</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Калі праграма \"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>\" недаступная"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Ліцэнзіі на ПЗ з адкрытым зыходным кодам"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Іншыя функцыі кіравання, пералічаныя ў раздзеле "<b>"Налады &gt; Бяспека &gt; Інфармацыя пра прыладу пад кіраваннем"</b>", не працуюць на гэтай прыладзе"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"На гэтай прыладзе не працуюць функцыі кіравання, пералічаныя ў раздзеле налад бяспекі для прылады, купленай у крэдыт."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Гэта прылада належыць кампаніі \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\""</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Праграма-кіёск будзе спампавана і ўсталявана аўтаматычна"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Для гэтага карыстальніка будзе ўсталявана праграма-кіёск"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Калі вы прапусціце плацеж, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> можа абмежаваць працу прылады"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Калі вы прапусціце плацеж, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> можа абмежаваць работу прылады. Каб даведацца больш, глядзіце <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Умовы выкарыстання<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Калі вы не будзеце рабіць неабходныя плацяжы, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> можа абмежаваць працу прылады. Падрабязныя звесткі можна знайсці ва <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Умовах выкарыстання<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Калі ўладальнік не будзе рабіць плацяжы, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> можа абмежаваць працу прылады"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Калі вам патрабуецца дапамога, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>звярніцеся да пастаўшчыка (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>)<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Назад"</string>
     <string name="next" msgid="8248291863254324326">"Далей"</string>
     <string name="start" msgid="2842214844667658537">"Пачаць"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Інфармацыя"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Аб падрыхтоўцы"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Зарэгіструйце прыладу"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Цяпер вы можаце зарэгістраваць сваю прыладу ў праграме фінансавання кампаніі \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\""</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Цяпер вы можаце зарэгістраваць сваю прыладу ў праграме фінансавання кампаніі \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\""</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Цяпер вы можаце зарэгістраваць прыладу ў праграме субсідзіравання кампаніі \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\""</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> дае вам субсідзіраванне"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Рэгістрацыя прылады"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> можа змяняць налады на гэтай прыладзе"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Даведацца больш"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Інфарм. аб прыладзе, купленай у крэдыт"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Кампанія-крэдытор можа змяняць налады і ўсталяваць на прыладзе праграму-кіёск.\n\nКалі вы не будзеце рабіць неабходныя плацяжы або перастанеце выкарыстоўваць SIM-карту кампаніі \"<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>\", \"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>\" можа абмежаваць працу прылады.\n\nКаб даведацца больш, звярніцеся ў кампанію \"<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\"."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"Кампанія \"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>\" можа змяняць налады і ўсталяваць на прыладзе праграму-кіёск.\n\nКалі вы прапусціце плацеж, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> можа абмежаваць работу прылады.\n\nКаб даведацца больш, звяжыцеся з кампаніяй \"<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\"."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"Кампанія \"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>\" можа змяняць налады і ўсталяваць на прыладзе праграму-кіёск.\n\nКампанія \"<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>\" можа таксама абмежаваць работу прылады, калі вы прапусціце плацеж або перастанеце выкарыстоўваць SIM-карту кампаніі \"<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\".\n\nКаб даведацца больш, звяжыцеся з кампаніяй \"<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>\"."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Да выплаты доўгу вы не можаце:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Перазагружаць прыладу з мэтай пераходу ў бяспечны рэжым"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Змяняць дату, час і часавы пояс"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Выкарыстоўваць параметры распрацоўшчыка"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"У выпадку праблем з прыладай <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> можа:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Вы можаце выдаліць праграму \"<xliff:g id="KIOSK_APP">%1$s</xliff:g>\""</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Каб атрымаць дапамогу:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Звязацца з пастаўшчыком (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>)<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Падрыхтоўка"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Прылада будзе скінута праз адзін дзень}one{Прылада будзе скінута праз # дзень}few{Прылада будзе скінута праз # дні}many{Прылада будзе скінута праз # дзён}other{Прылада будзе скінута праз # дня}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Прылада будзе скінута праз <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Усе даныя прылады будуць выдалены. Па дапамогу з рэгістрацыяй звяртайцеся ў кампанію \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Каб адкласці рэгістрацыю прылады, дазвольце DeviceLock прысылаць вам апавяшчэнні."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Не ўдалося падрыхтаваць прыладу да праграмы фінансавання"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Вы можаце звязацца з фінансавым спецыялістам: націсніце <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>тут<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>, каб даведацца больш"</string>
+    <string name="exit" msgid="645084771882733921">"Выйсці"</string>
+    <string name="retry" msgid="7497287909193345356">"Паўтарыць спробу"</string>
 </resources>
diff --git a/DeviceLockController/res/values-bg/strings.xml b/DeviceLockController/res/values-bg/strings.xml
index 442e347..028e83c 100644
--- a/DeviceLockController/res/values-bg/strings.xml
+++ b/DeviceLockController/res/values-bg/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Всички заявки за заключване или отключване от <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Ако приложението <xliff:g id="CREDITOR_APP">%1$s</xliff:g> не е налице"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Лицензи за отворен код"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Другите възможности за управление в "<b>"Настройки &gt; Сигурност &gt; Информация за управляваното устройство"</b>" не важат за това устройство"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Възможностите за управление в секцията за финансирано устройство, която се намира в настройките за сигурност, не са приложими за това устройство."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Това устройство е предоставено от <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Павилионното приложение ще бъде изтеглено и инсталирано автоматично"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Павилионното приложение ще бъде инсталирано за този потребител"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да ограничи това устройство, ако пропуснете плащане"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да ограничи устройството, ако пропуснете плащане. За подробности вижте <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>общите условия<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да ограничи това устройство, ако не извършите необходимите плащания. За подробности вижте <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>общите условия<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да ограничи това устройство, ако собственикът не извършва плащания"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"За помощ <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>се обърнете към <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Назад"</string>
     <string name="next" msgid="8248291863254324326">"Напред"</string>
     <string name="start" msgid="2842214844667658537">"Стартиране"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Информация"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Инф. за обезпечаване"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Регистрирайте устройството си"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Вече можете да регистрирате устройството си във финансовата програма на <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Вече можете да регистрирате устройството си във финансовата програма на <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Вече можете да регистрирате устройството си в програмата на <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> за субсидии"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Участвате в програмата на <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> за субсидии"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Регистриране на устройството"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да променя настройките на това устройство"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Научете повече"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Информация за финансираното устройство"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Кредитодателят ви може да променя настройкитe и да инсталира павилионното приложение на устройството.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може да ограничи това устройство, ако не извършите необходимите плащания или спрете да използвате SIM картата на <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nЗа да научите повече, обърнете се към <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може да променя настройките и да инсталира павилионното приложение на устройството.\n\nАко пропуснете плащане, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> може да ограничи устройството ви.\n\nЗа да научите повече, обърнете се към <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може да променя настройките и да инсталира павилионното приложение на устройството.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> може също да ограничи това устройство, ако пропуснете плащане или спрете да използвате SIM картата на <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nЗа да научите повече, обърнете се към <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Докато не сте изплатили устройството си, не можете да:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Рестартиране на устройството ви в безопасен режим"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Промяна на датата, часа и часовите зони"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Използване на опциите за програмисти"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"При проблем с устройството <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Можете да деинсталирате приложението <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"За да получите помощ:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Обърнете се към <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Обезпечаване"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Устройството ще бъде нулирано след 1 ден}other{Устройството ще бъде нулирано след # дни}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Устройството ще бъде нулирано след <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Всички данни на устройството ще бъдат изтрити. За помощ относно регистрирането му се свържете с(ъс) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Моля, разрешете известие от DeviceLock, за да продължите отлагането на регистрирането на устройството."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Обезпечаването за финансиране не бе успешно"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Моля, кликнете тук за начини да се свържете с финансиста си. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Научете повече<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Изход"</string>
+    <string name="retry" msgid="7497287909193345356">"Нов опит"</string>
 </resources>
diff --git a/DeviceLockController/res/values-bn/strings.xml b/DeviceLockController/res/values-bn/strings.xml
index 1252dc3..730cc0d 100644
--- a/DeviceLockController/res/values-bn/strings.xml
+++ b/DeviceLockController/res/values-bn/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>-এর করা যেকোনও লক বা আনলকের অনুরোধ"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> অ্যাপ উপলভ্য না থাকলে"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ওপেন-সোর্স লাইসেন্স"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"সেটিংস &gt; সুরক্ষা &gt; ম্যানেজ করা ডিভাইস তথ্য"</b>" বিভাগের অন্যান্য ম্যানেজমেন্ট সুবিধা এই ডিভাইসের ক্ষেত্রে প্রযোজ্য নয়"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"\'সুরক্ষা\' সেটিংসের \'ফাইন্যান্স করা ডিভাইস\' বিভাগের ম্যানেজমেন্ট সংক্রান্ত সুবিধা এই ডিভাইসের ক্ষেত্রে প্রযোজ্য নয়।"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"এই ডিভাইস <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> দিয়েছে"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk অ্যাপ অটোমেটিক ডাউনলোড ও ইনস্টল হবে"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"এই ব্যবহারকারীর জন্য Kiosk app ইনস্টল করা হবে"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"আপনি পেমেন্ট মিস করলে, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> এই ডিভাইসের ব্যবহার সীমিত করে দিতে পারে"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"আপনি পেমেন্ট না করলে, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ডিভাইসের ব্যবহার সীমিত করতে পারবে। আরও তথ্যের জন্য <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>নিয়ম ও শর্তাবলী দেখুন<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>।"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"আপনি প্রয়োজনীয় পেমেন্ট না করলে, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> এই ডিভাইসটির ব্যবহার সীমিত করতে পারে। আরও তথ্য জানার জন্য <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>নিয়ম ও শর্তাবলী দেখুন<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>।"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"ডিভাইসের মালিক পেমেন্ট না করলে, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> এই ডিভাইসের ব্যবহার সীমিত করে দিতে পারে"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"সাহায্যের জন্য <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>-এর সাথে যোগাযোগ করুন।"</string>
     <string name="previous" msgid="5241891780917802570">"পূর্ববর্তী"</string>
     <string name="next" msgid="8248291863254324326">"পরবর্তী"</string>
     <string name="start" msgid="2842214844667658537">"শুরু করুন"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"তথ্য"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"প্রভিশন তথ্য"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"আপনার ডিভাইস এনরোল করুন"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"আপনি এখন <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-এর ফাইন্যান্সিং প্রোগ্রামে এনরোল করতে পারবেন"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"আপনি এখন <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-এর ফাইন্যান্স প্রোগ্রামে নিজের ডিভাইস এনরোল করতে পারবেন"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"আপনি এখন <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-এর সাবসিডি প্রোগ্রামে এনরোল করতে পারবেন"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"আপনি <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-এর সাবসিডি প্রোগ্রামে রয়েছেন"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ডিভাইস এনরোলমেন্ট"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> এই ডিভাইসের সেটিংস পরিবর্তন করতে পারবে"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"আরও জানুন"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ফাইন্যান্স করা ডিভাইস সম্পর্কিত তথ্য"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"আপনার ক্রেডিট প্রদানকারী, ডিভাইসের সেটিংস পরিবর্তন ও Kiosk অ্যাপ ইনস্টল করতে পারবে।\n\nআপনি প্রয়োজনীয় পেমেন্ট না করলে বা <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>-এর সিম ব্যবহার করা বন্ধ করে দিলে, <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> এই ডিভাইসের ব্যবহার সীমিত করে দিতে পারে।\n\nআরও জানতে, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-এর সাথে যোগাযোগ করুন।"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>, ডিভাইসের সেটিংস পরিবর্তন ও Kiosk অ্যাপ ইনস্টল করতে পারবে।\n\nআপনার পেমেন্ট করা বাদ পড়লে, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> আপনার ডিভাইসের ব্যবহার সীমিত করে দিতে পারে।\n\nআরও জানতে, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-এর সাথে যোগাযোগ করুন।"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>, ডিভাইসের সেটিংস পরিবর্তন ও Kiosk অ্যাপ ইনস্টল করতে পারবে।\n\nআপনার পেমেন্ট করা বাদ পড়লে বা আপনি <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-এর সিম ব্যবহার করা বন্ধ করলে <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> আপনার ডিভাইসের ব্যবহার সীমিত করে দিতে পারে।\n\nআরও জানতে, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>-এর সাথে যোগাযোগ করুন।"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"ডিভাইসের জন্য পেমেন্ট না করা পর্যন্ত, এগুলি করতে পারবেন না:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"\'নিরাপদ মোড\' ব্যবহার করে ডিভাইস রিবুট করুন"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"তারিখ, সময় ও টাইম জোন পরিবর্তন করুন"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ডেভেলপার বিকল্প ব্যবহার করুন"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"ডিভাইসের কোনও সমস্যা হলে, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> যা করতে পারে:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"আপনি <xliff:g id="KIOSK_APP">%1$s</xliff:g> অ্যাপ আনইনস্টল করতে পারবেন"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"সহায়তা পেতে এটি করুন:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-এর সাথে যোগাযোগ করুন<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"প্রভিশন"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{১ দিনের মধ্যে ডিভাইস রিসেট হবে}one{# দিনের মধ্যে ডিভাইস রিসেট হবে}other{# দিনের মধ্যে ডিভাইস রিসেট হবে}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"<xliff:g id="TIMER">%s</xliff:g>-এর মধ্যে ডিভাইস রিসেট হবে"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ডিভাইসের সব ডেটা মুছে ফেলা হবে। আপনার ডিভাইস এনরোল করার জন্য <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-এর সাথে যোগাযোগ করুন"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"ডিভাইস এনরোলমেন্টের প্রক্রিয়া বন্ধ রাখতে, DeviceLock থেকে বিজ্ঞপ্তি পাঠানোর অনুমতি দিন।"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ফাইন্যান্সিং প্রভিশন করা যায়নি"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"আপনার অর্থদাতার সাথে কীভাবে যোগাযোগ করবেন তা জানতে, এখানে ক্লিক করুন। <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>আরও জানুন<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"বেরিয়ে আসুন"</string>
+    <string name="retry" msgid="7497287909193345356">"আবার চেষ্টা করুন"</string>
 </resources>
diff --git a/DeviceLockController/res/values-bs/strings.xml b/DeviceLockController/res/values-bs/strings.xml
index 8ecd10e..beed6da 100644
--- a/DeviceLockController/res/values-bs/strings.xml
+++ b/DeviceLockController/res/values-bs/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Svi zahtjevi aplikacije <xliff:g id="CREDITOR_APP">%1$s</xliff:g> za zaključavanje ili otključavanje"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Ako aplikacija <xliff:g id="CREDITOR_APP">%1$s</xliff:g> nije dostupna"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licence otvorenog koda"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Druge mogućnosti upravljanja u odjeljku "<b>"Postavke &gt; Sigurnost &gt; Informacije o uređaju kojim se upravlja"</b>" se ne primjenjuju na ovaj uređaj"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Mogućnosti upravljanja u odjeljku finansiranog uređaja u postavkama sigurnosti se ne primjenjuju na ovaj uređaj."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Ovaj uređaj pruža <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Automatski će se preuzeti i instalirati aplikacija Kiosk"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Aplikacija Kiosk će se instalirati za ovog korisnika"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može ograničiti ovaj uređaj ako propustite plaćanje"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može ograničiti uređaj ako propustite plaćanje. Za detalje pregledajte <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Uslove i odredbe<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može ograničiti ovaj uređaj ako ne izvršite potrebna plaćanja. Za detalje pogledajte <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Uslove i odredbe<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može ograničiti ovaj uređaj ako vlasnik ne izvrši plaćanja"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Za pomoć <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>kontaktirajte pružaoca <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Nazad"</string>
     <string name="next" msgid="8248291863254324326">"Naprijed"</string>
     <string name="start" msgid="2842214844667658537">"Započnite"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informacije"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Inf. o pružanju usluge"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Registrirajte uređaj"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Sada možete prijaviti uređaj u program finansiranja koji pruža <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Sada možete registrirati uređaj za program finansiranja koji pruža <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Sada možete registrirati uređaj za program subvencija koji pruža <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"U programu ste subvencija koji pruža <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Prijava uređaja"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može promijeniti postavke na ovom uređaju"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Saznajte više"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informacije o finansiranom uređaju"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Vaš dobavljač uređaja na kredit može promijeniti postavke i instalirati aplikaciju Kiosk na uređaju.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> može ograničiti ovaj uređaj ako ne izvršite potrebna plaćanja ili prestanete koristiti SIM operatera <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nDa saznate više, kontaktirajte operatera <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"Dobavljač uređaja <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> može promijeniti postavke i instalirati aplikaciju Kiosk na uređaju.\n\nAko ne izvršite plaćanje, dobavljač <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> može ograničiti vaš uređaj.\n\nDa saznate više, kontaktirajte dobavljača <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"Dobavljač uređaja na kredit <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> može promijeniti postavke i instalirati aplikaciju Kiosk na uređaju.\n\nDobavljač <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> također može ograničiti ovaj uređaj ako ne izvršite plaćanje ili prestanete koristiti SIM dobavljača <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nDa saznate više, kontaktirajte dobavljača <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Dok ne platite za uređaj, ne možete:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"ponovo pokrenuti uređaj u sigurnom načinu rada"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"promijeniti datum, vrijeme i vremenske zone"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"koristiti opcije za programere"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Ako nešto ne bude uredu s uređajem, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Možete deinstalirati aplikaciju <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Da dobijete pomoć:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontaktirajte dobavljača <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Pružanje usluge"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Uređaj će se vratiti na zadano za 1 dan}one{Uređaj će se vratiti na zadano za # dan}few{Uređaj će se vratiti na zadano za # dana}other{Uređaj će se vratiti na zadano za # dana}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Uređaj će se vratiti na zadano za <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Izbrisat će se svi podaci s uređaja. Za pomoć prilikom prijave uređaja kontaktirajte <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Dozvolite obavještenja od DeviceLocka da nastavite s odgodom prijave uređaja."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Pružanje usluge finansiranja nije uspjelo"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Kliknite ovdje da vidite kako možete kontaktirati finansijera. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Saznajte više<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Izađi"</string>
+    <string name="retry" msgid="7497287909193345356">"Pokušaj ponovo"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ca/strings.xml b/DeviceLockController/res/values-ca/strings.xml
index 75e4419..14efcb9 100644
--- a/DeviceLockController/res/values-ca/strings.xml
+++ b/DeviceLockController/res/values-ca/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Qualsevol sol·licitud de bloqueig o desbloqueig de l\'aplicació <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Si l\'aplicació <xliff:g id="CREDITOR_APP">%1$s</xliff:g> no està disponible"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Llicències de codi obert"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Les altres funcions de gestió a "<b>"Configuració &gt; Seguretat &gt; Informació del dispositiu gestionat"</b>" no s\'apliquen en aquest dispositiu"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Les funcions de gestió que hi ha a la secció del dispositiu finançat de la configuració de seguretat no s\'apliquen en aquest dispositiu."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> proporciona aquest dispositiu"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"L\'aplicació de quiosc es baixarà i s\'instal·larà automàticament."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"L\'aplicació de quiosc s\'instal·larà per a aquest usuari"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pot restringir aquest dispositiu si et falta algun pagament."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pot restringir el dispositiu si falta un pagament. Per obtenir informació, consulta els <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>termes i condicions<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pot restringir aquest dispositiu si no fas els pagaments necessaris. Per obtenir informació, consulta els <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>termes i condicions<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pot restringir aquest dispositiu si el propietari no efectua els pagaments"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Per obtenir ajuda, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>contacta <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Anterior"</string>
     <string name="next" msgid="8248291863254324326">"Següent"</string>
     <string name="start" msgid="2842214844667658537">"Inicia"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informació"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Dades de proveïment"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Inscriu el dispositiu"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Ja pots inscriure el dispositiu en el programa de finançament de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Ja pots inscriure el dispositiu en el programa de finançament de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Ja pots inscriure el dispositiu en el programa de subsidis de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Formes part del programa de subsidis de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Inscripció de dispositius"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pot canviar la configuració d\'aquest dispositiu"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Més informació"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informació del dispositiu finançat"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"La teva entitat de crèdit pot canviar la configuració i instal·lar l\'aplicació de quiosc al dispositiu.\n\nÉs possible que <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> restringeixi aquest dispositiu si no fas els pagaments necessaris o si deixes d\'utilitzar la SIM de <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPer obtenir més informació, contacta amb <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pot canviar la configuració i instal·lar l\'aplicació de quiosc al dispositiu.\n\nSi falta un pagament, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> pot restringir el dispositiu.\n\nPer obtenir més informació, contacta amb <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pot canviar la configuració i instal·lar l\'aplicació de quiosc al dispositiu.\n\nÉs possible que <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> també restringeixi aquest dispositiu si falta un pagament o si deixes d\'utilitzar la SIM de <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPer obtenir més informació, contacta amb <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Fins que no hagis pagat el dispositiu, no pots:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reiniciar el dispositiu en mode segur"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Canviar la data, l\'hora i la zona horària"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Utilitzar opcions per a desenvolupadors"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Si hi ha cap error amb el dispositiu, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pot:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Pots desinstal·lar l\'aplicació <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Per obtenir ajuda:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contacta amb <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Proveïment"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{El dispositiu es restablirà d\'aquí a 1 dia}other{El dispositiu es restablirà d\'aquí a # dies}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"El dispositiu es restablirà d\'aquí a <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Totes les dades del dispositiu se suprimiran. Per obtenir ajuda amb la inscripció del dispositiu, contacta amb <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Permet les notificacions de DeviceLock per continuar diferint la inscripció del dispositiu."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"S\'ha produït un error amb el proveïment del finançament"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Fes clic aquí per consultar com pots contactar amb el teu financer. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Més informació<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Surt"</string>
+    <string name="retry" msgid="7497287909193345356">"Torna-ho a provar"</string>
 </resources>
diff --git a/DeviceLockController/res/values-cs/strings.xml b/DeviceLockController/res/values-cs/strings.xml
index 82c7643..59bd914 100644
--- a/DeviceLockController/res/values-cs/strings.xml
+++ b/DeviceLockController/res/values-cs/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Všechny žádosti o uzamčení nebo odemčení z aplikace <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Pokud aplikace <xliff:g id="CREDITOR_APP">%1$s</xliff:g> není k dispozici"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licence open source"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Ostatní funkce správy v sekci "<b>"Nastavení &gt; Zabezpečení &gt; Informace o spravovaném zařízení"</b>" se na toto zařízení nevztahují"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Funkce správy v sekci s informacemi o financovaném zařízení v nastavení zabezpečení se na toto zařízení nevztahují."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Toto zařízení poskytuje <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Terminálová aplikace bude automaticky stažena a nainstalována"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Tomuto uživateli bude nainstalována terminálová aplikace"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Pokud zmeškáte platbu, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> může k tomuto zařízení omezit přístup"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Pokud zmeškáte platbu, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> může k zařízení omezit přístup. Podrobnosti najdete ve <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>smluvních podmínkách<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Pokud neuhradíte požadované platby, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> může k tomuto zařízení omezit přístup. Podrobnosti najdete ve <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>smluvních podmínkách<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Pokud vlastník neuhradí platby, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> může k tomuto zařízení omezit přístup"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Nápovědu vám poskytne <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Předchozí"</string>
     <string name="next" msgid="8248291863254324326">"Další"</string>
     <string name="start" msgid="2842214844667658537">"Začít"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informace"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Informace o zajištění"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Zaregistrujte své zařízení"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Nyní můžete zařízení zaregistrovat do programu financování <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Teď můžete zařízení zaregistrovat do programu financování <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Nyní můžete zařízení zaregistrovat do podpůrného programu <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Využíváte podpůrný program <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Registrace zařízení"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> může měnit nastavení tohoto zařízení"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Další informace"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informace o financovaném zařízení"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Poskytovatel úvěru může v tomto zařízení měnit nastavení a nainstalovat do něj terminálovou aplikaci.\n\nPokud neuhradíte požadované platby nebo přestanete používat SIM kartu <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>, společnost <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> může k tomuto zařízení omezit přístup.\n\nDalší informace vám sdělí <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"Poskytovatel <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> může v tomto zařízení měnit nastavení a nainstalovat do něj terminálovou aplikaci.\n\nV případě neuhrazení splátky může poskytovatel <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> zařízení omezit.\n\nDalší informace vám sdělí <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"Poskytovatel <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> může v tomto zařízení měnit nastavení a nainstalovat do něj terminálovou aplikaci.\n\nPokud zmeškáte platbu nebo přestanete používat SIM kartu od poskytovatele <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> může k tomuto zařízení omezit přístup.\n\nDalší informace vám sdělí <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Dokud za zařízení nezaplatíte, nebudete moci:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Restartovat zařízení do nouzového režimu"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Změnit datum, čas a časová pásma"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Používat nastavení pro vývojáře"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Pokud v zařízení dojde k problému, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> může:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Můžete odinstalovat aplikaci <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Jak získat nápovědu:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontaktovat banku <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Zajištění"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Zařízení bude resetováno za 1 den}few{Zařízení bude resetováno za # dny}many{Zařízení bude resetováno za # dne}other{Zařízení bude resetováno za # dnů}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Zařízení bude resetováno za <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Veškerá data budou ze zařízení vymazána. Pokud potřebujete pomoc s registrací zařízení, obraťte se na společnost <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Povolte oznámení z aplikace DeviceLock, abyste mohli dál odkládat registraci zařízení."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Zajištění financování se nezdařilo"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Kliknutím sem zobrazíte možnosti kontaktování společnosti poskytující financování. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Další informace<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Ukončit"</string>
+    <string name="retry" msgid="7497287909193345356">"Zkusit znovu"</string>
 </resources>
diff --git a/DeviceLockController/res/values-da/strings.xml b/DeviceLockController/res/values-da/strings.xml
index b769594..a25dac3 100644
--- a/DeviceLockController/res/values-da/strings.xml
+++ b/DeviceLockController/res/values-da/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Anmodninger om låsning og oplåsning fra <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Hvis <xliff:g id="CREDITOR_APP">%1$s</xliff:g>-appen ikke er tilgængelig"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Open source-licenser"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"De øvrige funktioner til administration under "<b>"Indstillinger &gt; Sikkerhed &gt; Oplysninger om administrerede enheder"</b>" gælder ikke for denne enhed"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Funktionerne til administration i sektionen om finansierede enheder i sikkerhedsindstillingerne gælder ikke for denne enhed."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Denne enhed er leveret af <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Terminalappen downloades og installeres automatisk"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Terminalappen installeres for denne bruger"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begrænse denne enhed, hvis du ikke foretager en betaling"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begrænse enheden, hvis du ikke foretager en betaling. Du kan få flere oplysninger ved at gå til <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Vilkår og betingelser<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begrænse denne enhed, hvis du ikke foretager de nødvendige betalinger. Du kan få flere oplysninger ved at gå til <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>vilkårene og betingelserne<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begrænse denne enhed, hvis ejeren ikke foretager en betaling"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontakt <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g> for at få hjælp."</string>
     <string name="previous" msgid="5241891780917802570">"Forrige"</string>
     <string name="next" msgid="8248291863254324326">"Næste"</string>
     <string name="start" msgid="2842214844667658537">"Start"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Oplysninger"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Provisioneringsinfo"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Tilmeld din enhed"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Du kan nu tilmelde din enhed finansieringsprogrammet fra <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Din enhed kan nu tilmeldes finansieringsprogrammet fra <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Du kan nu tilmelde din enhed tilskudsprogrammet fra <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Du deltager i tilskudsprogrammet fra <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Tilmelding af enhed"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan ændre indstillinger på denne enhed"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Få flere oplysninger"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Oplysninger om finansieret enhed"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Din kreditudbyder kan ændre indstillinger og installere terminalappen på enheden.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan begrænse denne enhed, hvis du ikke foretager de nødvendige betalinger eller holder op med at bruge SIM-kortet fra <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nFå flere oplysninger ved at kontakte <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan ændre indstillinger og installere terminalappen på denne enhed.\n\nHvis du ikke foretager de nødvendige betalinger, kan <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> begrænse din enhed.\n\nKontakt <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> for at få flere oplysninger."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan ændre indstillinger og installere terminalappen på denne enhed.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kan også begrænse enheden, hvis du ikke foretager de nødvendige betalinger, eller hvis du holder op med at bruge SIM-kortet fra <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nKontakt <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> for at få flere oplysninger."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Du kan ikke gøre følgende, før du har betalt for din enhed:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Genstarte din enhed i sikker tilstand"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Skifte dato, klokkeslæt og tidszoner"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Bruge Indstillinger for udviklere"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Hvis noget går galt med din enhed, kan <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Du kan afinstallere <xliff:g id="KIOSK_APP">%1$s</xliff:g>-appen"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Sådan kan du få hjælp:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontakt <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provisionering"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Enheden nulstilles om 1 dag}one{Enheden nulstilles om # dag}other{Enheden nulstilles om # dage}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Enheden nulstilles om <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Alle enhedsdata slettes. Kontakt <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> for at få hjælp til at tilmelde din enhed"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Tillad notifikation fra DeviceLock for at fortsætte med at udskyde tilmeldingen af enheden."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Provisionering af finansiering mislykkedes"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Klik her for at finde ud af, hvordan du kan kontakte din financier. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Få flere oplysninger<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Afslut"</string>
+    <string name="retry" msgid="7497287909193345356">"Prøv igen"</string>
 </resources>
diff --git a/DeviceLockController/res/values-de/strings.xml b/DeviceLockController/res/values-de/strings.xml
index 2db0b51..c1ca707 100644
--- a/DeviceLockController/res/values-de/strings.xml
+++ b/DeviceLockController/res/values-de/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Alle Sperren-/Entsperren-Anfragen von <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Wenn die <xliff:g id="CREDITOR_APP">%1$s</xliff:g> App nicht verfügbar ist"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Open-Source-Lizenzen"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Die anderen Verwaltungsfunktionen unter "<b>"Einstellungen &gt; Sicherheit &gt; Info zu verwalteten Geräten"</b>" gelten nicht für dieses Gerät"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Die Verwaltungsfunktionen im Abschnitt zu finanzierten Geräten in den Sicherheitseinstellungen gelten nicht für dieses Gerät."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Dieses Gerät wird von <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> zur Verfügung gestellt"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Die Kiosk-App wird automatisch heruntergeladen und installiert."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Die Kiosk-App wird für diesen Nutzer installiert"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kann die Nutzbarkeit dieses Geräts einschränken, wenn du eine Zahlung versäumst."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Wenn du eine Zahlung versäumst, kann <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> die Nutzbarkeit des Geräts einschränken. Ausführliche Informationen dazu findest du in den <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Nutzungsbedingungen<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kann die Nutzbarkeit dieses Geräts einschränken, wenn du deinen Zahlungsverpflichtungen nicht nachkommst. Ausführliche Informationen findest du in den <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Nutzungsbedingungen<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kann die Nutzbarkeit dieses Geräts einschränken, wenn der Besitzer seinen Zahlungsverpflichtungen nicht nachkommt"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Wenn du Hilfe benötigst, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>wende dich an <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Zurück"</string>
     <string name="next" msgid="8248291863254324326">"Weiter"</string>
     <string name="start" msgid="2842214844667658537">"Starten"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Info"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Bereitstellungsinfos"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Gerät registrieren"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Du kannst dein Gerät jetzt im Finanzierungsprogramm von <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> registrieren"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Du kannst dein Gerät jetzt im Finanzierungsprogramm von <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> registrieren"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Du kannst dein Gerät jetzt im Förderprogramm von <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> registrieren"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Du nimmst am Förderprogramm von <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> teil"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Geräteregistrierung"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kann Einstellungen auf diesem Gerät ändern"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Weitere Infos"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informationen zum finanzierten Gerät"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Dein Kreditinstitut kann auf diesem Gerät Einstellungen ändern und die Kiosk-App installieren.\n\nWenn du deinen Zahlungsverpflichtungen nicht nachkommst oder nicht mehr die SIM von <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> verwendest, kann <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> die Nutzbarkeit dieses Geräts einschränken.\n\nWenn du weitere Informationen benötigst, wende dich an <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kann auf diesem Gerät Einstellungen ändern und die Kiosk-App installieren.\n\nWenn du deinen Zahlungsverpflichtungen nicht nachkommst, kann <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> die Nutzbarkeit dieses Geräts einschränken.\n\nWenn du weitere Informationen benötigst, wende dich an <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kann auf diesem Gerät Einstellungen ändern und die Kiosk-App installieren.\n\nAußerdem kann <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> die Nutzbarkeit dieses Geräts einschränken, wenn du deinen Zahlungsverpflichtungen nicht nachkommst oder nicht mehr die SIM von <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> verwendest.\n\nWenn du weitere Informationen benötigst, wende dich an <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Bis du deine Raten bezahlt hast, kannst du Folgendes nicht:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Dein Gerät im abgesicherten Modus neu starten"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Datum, Uhrzeit und Zeitzonen ändern"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Entwickleroptionen verwenden"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Bei Problemen mit dem Gerät darf <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Die kannst die <xliff:g id="KIOSK_APP">%1$s</xliff:g> App deinstallieren"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Falls du Hilfe benötigst:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kontaktieren<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Bereitstellung"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Gerät wird in einem Tag zurückgesetzt}other{Gerät wird in # Tagen zurückgesetzt}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Das Gerät wird in <xliff:g id="TIMER">%s</xliff:g> zurückgesetzt"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Alle Gerätedaten werden gelöscht. Wenn du Hilfe bei der Registrierung deines Geräts benötigst, wende dich an <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Bitte lass Benachrichtigungen von DeviceLock zu, um die Registrierung des Geräts weiter aufzuschieben."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Finanzierungsbereitstellung fehlgeschlagen"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Wenn du wissen möchtest, wie du deinen Finanzierungsanbieter kontaktieren kannst, klicke hier. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Weitere Informationen<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Beenden"</string>
+    <string name="retry" msgid="7497287909193345356">"Noch mal versuchen"</string>
 </resources>
diff --git a/DeviceLockController/res/values-el/strings.xml b/DeviceLockController/res/values-el/strings.xml
index 5b627e8..fec9524 100644
--- a/DeviceLockController/res/values-el/strings.xml
+++ b/DeviceLockController/res/values-el/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Τυχόν αιτήματα για κλείδωμα και ξεκλείδωμα από την εφαρμογή <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Εάν η εφαρμογή <xliff:g id="CREDITOR_APP">%1$s</xliff:g> δεν είναι διαθέσιμη"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Άδειες λογισμικού ανοικτού κώδικα"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Οι άλλες δυνατότητες διαχείρισης στις "<b>"Ρυθμίσεις &gt; Ασφάλεια &gt; Πληροφορίες διαχειριζόμενης συσκευής"</b>" δεν ισχύουν για αυτήν τη συσκευή."</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Οι δυνατότητες διαχείρισης στην ενότητα χρηματοδοτούμενης συσκευής δεν ισχύουν για αυτήν τη συσκευή."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Αυτή η συσκευή παρέχεται από <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Θα γίνει αυτόματα λήψη και εγκατάσταση της εφαρμογής kiosk"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Η εφαρμογή kiosk θα εγκατασταθεί για αυτόν τον χρήστη"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Αν δεν καταβάλετε μια πληρωμή, ο πάροχος <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> μπορεί να εφαρμόσει περιορισμούς σε αυτήν τη συσκευή"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Αν δεν καταβάλετε μια πληρωμή, ο πάροχος <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> μπορεί να εφαρμόσει περιορισμούς στη συσκευή. Για λεπτομέρειες, ανατρέξτε στην ενότητα <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Όροι και Προϋποθέσεις<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Ο πάροχος <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> μπορεί να εφαρμόσει περιορισμούς σε αυτήν τη συσκευή αν δεν καταβάλετε τις απαραίτητες πληρωμές. Για λεπτομέρειες, ανατρέξτε στην ενότητα <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Όροι και Προϋποθέσεις<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Αν ο κάτοχος δεν καταβάλει πληρωμές, ο πάροχος <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> μπορεί να εφαρμόσει περιορισμούς σε αυτήν τη συσκευή"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Για βοήθεια, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>επικοινωνήστε με την εταιρεία <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Προηγούμενο"</string>
     <string name="next" msgid="8248291863254324326">"Επόμενο"</string>
     <string name="start" msgid="2842214844667658537">"Έναρξη"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Πληροφορίες"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Πληροφορίες παροχής"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Εγγραφή της συσκευής σας"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Μπορείτε τώρα να εγγράψετε τη συσκευή σας στο πρόγραμμα χρηματοδότησης του <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Μπορείτε τώρα να εγγράψετε τη συσκευή σας στο οικονομικό πρόγραμμα του παρόχου <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Μπορείτε τώρα να εγγράψετε τη συσκευή σας στο επιδοτούμενο πρόγραμμα του <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Είστε σε επιδοτούμενο πρόγραμμα <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Εγγραφή συσκευής"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"Ο πάροχος <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> μπορεί να αλλάξει ρυθμίσεις σε αυτήν τη συσκευή"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Μάθετε περισσότερα"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Πληροφορίες χρηματοδοτούμενης συσκευής"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Ο πωλητής συσκευών με πίστωση μπορεί να αλλάξει τις ρυθμίσεις και να εγκαταστήσει την εφαρμογή kiosk στη συσκευή.\n\nΟ πάροχος <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> μπορεί να εφαρμόσει περιορισμούς σε αυτήν τη συσκευή, σε περίπτωση που δεν καταβάλετε τις απαραίτητες πληρωμές ή σταματήσετε να χρησιμοποιείτε τη SIM του παρόχου <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nΓια να μάθετε περισσότερα, επικοινωνήστε με τον πάροχο <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"Ο πάροχος <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> μπορεί να αλλάξει τις ρυθμίσεις και να εγκαταστήσει την εφαρμογή kiosk στη συσκευή.\n\nΑν δεν καταβάλετε μια πληρωμή, ο πάροχος <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> μπορεί να εφαρμόσει περιορισμούς στη συσκευή.\n\nΓια να μάθετε περισσότερα, επικοινωνήστε με τον πάροχο <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"Ο πάροχος <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> μπορεί να αλλάξει τις ρυθμίσεις και να εγκαταστήσει την εφαρμογή kiosk στη συσκευή.\n\nΟ πάροχος <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> μπορεί επίσης να εφαρμόσει περιορισμούς σε αυτήν τη συσκευή, αν δεν καταβάλετε μια πληρωμή ή σταματήσετε να χρησιμοποιείτε τη SIM του παρόχου <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nΓια να μάθετε περισσότερα, επικοινωνήστε με τον πάροχο <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Μέχρι να πληρώσετε για τη συσκευή, δεν μπορείτε:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Επανεκκίνηση της συσκευής σας σε ασφαλή λειτουργία"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Αλλαγή ημερομηνίας, ώρας και ζωνών ώρας"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Χρήση επιλογών για προγραμματιστές"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Για προβλ. συσκευής, ο πάροχος <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> μπορεί:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Μπορείτε να απεγκαταστήσετε την εφαρμογή <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Για λήψη βοήθειας:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Επικοινωνήστε με τον πάροχο <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Παροχή"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Θα γίνει επαναφορά της συσκευής σε 1 ημέρα}other{Θα γίνει επαναφορά της συσκευής σε # ημέρες}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Θα γίνει επαναφορά της συσκευής σε <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Θα διαγραφούν όλα τα δεδομένα της συσκευής. Για βοήθεια με την εγγραφή της συσκευής, επικοινωνήστε με τον πάροχο <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Επιτρέψτε την ειδοποίηση από το DeviceLock για συνέχιση της αναβολής της εγγραφής συσκευής."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Η χρηματοοικονομική παροχή απέτυχε"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Κάντε κλικ εδώ για τρόπους επικοινωνίας με τον χρηματοοικονομικό σας σύμβουλο. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Μάθετε περισσότερα<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Έξοδος"</string>
+    <string name="retry" msgid="7497287909193345356">"Επανάληψη"</string>
 </resources>
diff --git a/DeviceLockController/res/values-en-rAU/strings.xml b/DeviceLockController/res/values-en-rAU/strings.xml
index 55adb7a..1ff3762 100644
--- a/DeviceLockController/res/values-en-rAU/strings.xml
+++ b/DeviceLockController/res/values-en-rAU/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Any lock or unlock requests from <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"If the <xliff:g id="CREDITOR_APP">%1$s</xliff:g> app isn\'t available"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Open-source licences"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"The other management capabilities in "<b>"Settings &gt; Security &gt; Managed device info"</b>" don\'t apply to this device"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"The management capabilities in the financed device section of security settings don\'t apply to this device."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"This device is provided by <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"The kiosk app will be downloaded and installed automatically"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"The kiosk app will be installed for this user"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can restrict this device if you miss a payment"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can restrict the device if you miss a payment. For details, view the <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Terms &amp; Conditions<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<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">&lt;a href=%2$s&gt;</xliff:g>Terms and Conditions<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can restrict this device if the owner doesn\'t make payments"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"For help, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>contact <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Previous"</string>
     <string name="next" msgid="8248291863254324326">"Next"</string>
     <string name="start" msgid="2842214844667658537">"Start"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Info"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Provision info"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Enrol your device"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"You can now enrol your device in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s financing programme"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"You can now enrol your device in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s finance programme"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"You can now enrol your device in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s subsidy programme"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"You\'re on <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s subsidy programme"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Device enrolment"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can change settings on this device"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Learn more"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Financed device info"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Your credit provider can change settings and install the kiosk app on the device.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> may restrict this device if you don’t make the necessary payments or stop using <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>’s SIM.\n\nTo learn more, contact <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> can change settings and install the kiosk app on the device.\n\nIf you miss a payment, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> can restrict your device.\n\nTo find out more, contact <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> can change settings and install the kiosk app on the device.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> may also restrict this device if you miss a payment or stop using <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>’s SIM.\n\nTo find out more, contact <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Until you’ve paid for your device, you can’t:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reboot your device into safe mode"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Change date, time and time zones"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Use developer options"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"If something goes wrong with your device, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"You can uninstall the <xliff:g id="KIOSK_APP">%1$s</xliff:g> app"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"To get help:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contact <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provision"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Device will reset in 1 day}other{Device will reset in # days}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Device will reset in <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"All device data will be deleted. For help enrolling your device, contact <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Please allow notification from DeviceLock to continue deferring the enrolment of the device."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Financing provisioning has failed"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Please click here for ways to contact your financier. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Learn more<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Exit"</string>
+    <string name="retry" msgid="7497287909193345356">"Retry"</string>
 </resources>
diff --git a/DeviceLockController/res/values-en-rGB/strings.xml b/DeviceLockController/res/values-en-rGB/strings.xml
index 55adb7a..1ff3762 100644
--- a/DeviceLockController/res/values-en-rGB/strings.xml
+++ b/DeviceLockController/res/values-en-rGB/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Any lock or unlock requests from <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"If the <xliff:g id="CREDITOR_APP">%1$s</xliff:g> app isn\'t available"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Open-source licences"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"The other management capabilities in "<b>"Settings &gt; Security &gt; Managed device info"</b>" don\'t apply to this device"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"The management capabilities in the financed device section of security settings don\'t apply to this device."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"This device is provided by <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"The kiosk app will be downloaded and installed automatically"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"The kiosk app will be installed for this user"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can restrict this device if you miss a payment"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can restrict the device if you miss a payment. For details, view the <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Terms &amp; Conditions<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<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">&lt;a href=%2$s&gt;</xliff:g>Terms and Conditions<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can restrict this device if the owner doesn\'t make payments"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"For help, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>contact <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Previous"</string>
     <string name="next" msgid="8248291863254324326">"Next"</string>
     <string name="start" msgid="2842214844667658537">"Start"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Info"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Provision info"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Enrol your device"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"You can now enrol your device in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s financing programme"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"You can now enrol your device in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s finance programme"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"You can now enrol your device in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s subsidy programme"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"You\'re on <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s subsidy programme"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Device enrolment"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can change settings on this device"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Learn more"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Financed device info"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Your credit provider can change settings and install the kiosk app on the device.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> may restrict this device if you don’t make the necessary payments or stop using <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>’s SIM.\n\nTo learn more, contact <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> can change settings and install the kiosk app on the device.\n\nIf you miss a payment, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> can restrict your device.\n\nTo find out more, contact <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> can change settings and install the kiosk app on the device.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> may also restrict this device if you miss a payment or stop using <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>’s SIM.\n\nTo find out more, contact <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Until you’ve paid for your device, you can’t:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reboot your device into safe mode"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Change date, time and time zones"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Use developer options"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"If something goes wrong with your device, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"You can uninstall the <xliff:g id="KIOSK_APP">%1$s</xliff:g> app"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"To get help:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contact <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provision"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Device will reset in 1 day}other{Device will reset in # days}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Device will reset in <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"All device data will be deleted. For help enrolling your device, contact <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Please allow notification from DeviceLock to continue deferring the enrolment of the device."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Financing provisioning has failed"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Please click here for ways to contact your financier. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Learn more<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Exit"</string>
+    <string name="retry" msgid="7497287909193345356">"Retry"</string>
 </resources>
diff --git a/DeviceLockController/res/values-en-rIN/strings.xml b/DeviceLockController/res/values-en-rIN/strings.xml
index 55adb7a..1ff3762 100644
--- a/DeviceLockController/res/values-en-rIN/strings.xml
+++ b/DeviceLockController/res/values-en-rIN/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Any lock or unlock requests from <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"If the <xliff:g id="CREDITOR_APP">%1$s</xliff:g> app isn\'t available"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Open-source licences"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"The other management capabilities in "<b>"Settings &gt; Security &gt; Managed device info"</b>" don\'t apply to this device"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"The management capabilities in the financed device section of security settings don\'t apply to this device."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"This device is provided by <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"The kiosk app will be downloaded and installed automatically"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"The kiosk app will be installed for this user"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can restrict this device if you miss a payment"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can restrict the device if you miss a payment. For details, view the <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Terms &amp; Conditions<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<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">&lt;a href=%2$s&gt;</xliff:g>Terms and Conditions<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can restrict this device if the owner doesn\'t make payments"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"For help, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>contact <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Previous"</string>
     <string name="next" msgid="8248291863254324326">"Next"</string>
     <string name="start" msgid="2842214844667658537">"Start"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Info"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Provision info"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Enrol your device"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"You can now enrol your device in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s financing programme"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"You can now enrol your device in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s finance programme"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"You can now enrol your device in <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s subsidy programme"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"You\'re on <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\'s subsidy programme"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Device enrolment"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can change settings on this device"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Learn more"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Financed device info"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Your credit provider can change settings and install the kiosk app on the device.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> may restrict this device if you don’t make the necessary payments or stop using <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>’s SIM.\n\nTo learn more, contact <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> can change settings and install the kiosk app on the device.\n\nIf you miss a payment, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> can restrict your device.\n\nTo find out more, contact <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> can change settings and install the kiosk app on the device.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> may also restrict this device if you miss a payment or stop using <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>’s SIM.\n\nTo find out more, contact <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Until you’ve paid for your device, you can’t:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reboot your device into safe mode"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Change date, time and time zones"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Use developer options"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"If something goes wrong with your device, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> can:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"You can uninstall the <xliff:g id="KIOSK_APP">%1$s</xliff:g> app"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"To get help:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contact <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provision"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Device will reset in 1 day}other{Device will reset in # days}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Device will reset in <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"All device data will be deleted. For help enrolling your device, contact <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Please allow notification from DeviceLock to continue deferring the enrolment of the device."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Financing provisioning has failed"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Please click here for ways to contact your financier. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Learn more<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Exit"</string>
+    <string name="retry" msgid="7497287909193345356">"Retry"</string>
 </resources>
diff --git a/DeviceLockController/res/values-en-rXC/strings.xml b/DeviceLockController/res/values-en-rXC/strings.xml
index 36991ae..3f4a431 100644
--- a/DeviceLockController/res/values-en-rXC/strings.xml
+++ b/DeviceLockController/res/values-en-rXC/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎‎‎‏‏‎Any lock or unlock requests from ‎‏‎‎‏‏‎<xliff:g id="CREDITOR_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎If the ‎‏‎‎‏‏‎<xliff:g id="CREDITOR_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ app isn\'t available‎‏‎‎‏‎"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎Open-source licenses‎‏‎‎‏‎"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎The other management capabilities in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎Settings &gt; Security &gt; Managed device info‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ don\'t apply to this device‎‏‎‎‏‎"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‎‎The management capabilities in the financed device section of Security settings don\'t apply to this device.‎‏‎‎‏‎"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎This device is provided by ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎The Kiosk app will be downloaded and installed automatically‎‏‎‎‏‎"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎The Kiosk app will be installed for this user‎‏‎‎‏‎"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ can restrict this device if you miss a payment‎‏‎‎‏‎"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ can restrict the device if you miss a payment. For details, view the ‎‏‎‎‏‏‎<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>‎‏‎‎‏‏‏‎Terms &amp; Conditions‎‏‎‎‏‏‎<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎<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">&lt;a href=%2$s&gt;</xliff:g>‎‏‎‎‏‏‏‎Terms &amp; Conditions‎‏‎‎‏‏‎<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ can restrict this device if the owner doesn\'t make payments‎‏‎‎‏‎"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‎For help, ‎‏‎‎‏‏‎<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>‎‏‎‎‏‏‏‎contact ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="previous" msgid="5241891780917802570">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎Previous‎‏‎‎‏‎"</string>
     <string name="next" msgid="8248291863254324326">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎Next‎‏‎‎‏‎"</string>
     <string name="start" msgid="2842214844667658537">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‎‎‏‎Start‎‏‎‎‏‎"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎Info‎‏‎‎‏‎"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‎‏‏‎Provision info‎‏‎‎‏‎"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎Enroll your device‎‏‎‎‏‎"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎You can now enroll your device in ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎\'s financing program‎‏‎‎‏‎"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎You can now enroll your device in ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎\'s finance program‎‏‎‎‏‎"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎You can now enroll your device in ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎\'s subsidy program‎‏‎‎‏‎"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‎You\'re on ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎\'s subsidy program‎‏‎‎‏‎"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‎Device enrollment‎‏‎‎‏‎"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‏‎‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ can change settings on this device‎‏‎‎‏‎"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‎Learn more‎‏‎‎‏‎"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‎Financed device info‎‏‎‎‏‎"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎Your credit provider can change settings and install the Kiosk app on the device.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ may restrict this device if you don’t make the necessary payments or stop using ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎’s SIM.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎To learn more, contact ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ can change settings and install the Kiosk app on the device.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎If you miss a payment, ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ can restrict your device.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎To learn more, contact ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ can change settings and install the Kiosk app on the device.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ may also restrict this device if you miss a payment or stop using ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>‎‏‎‎‏‏‏‎’s SIM.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎To learn more, contact ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‎‏‎‏‏‎‎‏‎‎settings_intro_preference_key‎‏‎‎‏‎"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‎‏‎Until you’ve paid for your device, you can’t:‎‏‎‎‏‎"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎‎settings_restrictions_category_preference_key‎‏‎‎‏‎"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎settings_install_apps_preference_key‎‏‎‎‏‎"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎Reboot your device into safe mode‎‏‎‎‏‎"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‎‎settings_safe_mode_preference_key‎‏‎‎‏‎"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‎‎Change date, time, and time zones‎‏‎‎‏‎"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎settings_config_date_time_preference_key‎‏‎‎‏‎"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎Use developer options‎‏‎‎‏‎"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎settings_developer_options_preference_key‎‏‎‎‏‎"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎If something goes wrong with your device, ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ can:‎‏‎‎‏‎"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‏‎settings_restrictions_removed_preference_key‎‏‎‎‏‎"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎You can uninstall the ‎‏‎‎‏‏‎<xliff:g id="KIOSK_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ app‎‏‎‎‏‎"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎settings_uninstall_kiosk_app_preference_key‎‏‎‎‏‎"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎To get help:‎‏‎‎‏‎"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎settings_support_category_preference_key‎‏‎‎‏‎"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>‎‏‎‎‏‏‏‎Contact ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎settings_contact_provider_preference_key‎‏‎‎‏‎"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‎Provision‎‏‎‎‏‎"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎Device will reset in 1 day‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎Device will reset in # days‎‏‎‎‏‎}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎Device will reset in ‎‏‎‎‏‏‎<xliff:g id="TIMER">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎All device data will be deleted. For help enrolling your device, contact ‎‏‎‎‏‏‎<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‎Please allow notification from DeviceLock to continue deferring the enrollment of the device.‎‏‎‎‏‎"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‎Financing provisioning has failed‎‏‎‎‏‎"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‎Please click here for ways to contact your financier. ‎‏‎‎‏‏‎<xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>‎‏‎‎‏‏‏‎Learn more‎‏‎‎‏‏‎<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="exit" msgid="645084771882733921">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎Exit‎‏‎‎‏‎"</string>
+    <string name="retry" msgid="7497287909193345356">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‏‎‎‎Retry‎‏‎‎‏‎"</string>
 </resources>
diff --git a/DeviceLockController/res/values-es-rUS/strings.xml b/DeviceLockController/res/values-es-rUS/strings.xml
index 5e86534..2152636 100644
--- a/DeviceLockController/res/values-es-rUS/strings.xml
+++ b/DeviceLockController/res/values-es-rUS/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Cualquier solicitud de bloqueo o desbloqueo de <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Si la app de <xliff:g id="CREDITOR_APP">%1$s</xliff:g> no está disponible"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licencias de código abierto"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Las otras funciones de administración de "<b>"Configuración &gt; Seguridad &gt; Información del dispositivo administrado"</b>" no se aplican a este dispositivo"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Las funciones de administración de la sección de la Configuración de seguridad del dispositivo financiado no se aplican a este dispositivo."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> proporciona este dispositivo"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Se descargará e instalará la aplicación de Kiosco automáticamente."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Se instalará la aplicación de Kiosco para este usuario"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede restringir este dispositivo si omites un pago."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede restringir el dispositivo si no realizas un pago. Para obtener más información, consulta los <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Términos y Condiciones<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede restringir este dispositivo si no realizas los pagos necesarios. Para obtener más información, consulta los <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Términos y Condiciones<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede restringir este dispositivo si el propietario no realiza los pagos"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Para recibir ayuda, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>comunícate con <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Anterior"</string>
     <string name="next" msgid="8248291863254324326">"Siguiente"</string>
     <string name="start" msgid="2842214844667658537">"Iniciar"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Información"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Datos de provisión"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Inscribe tu dispositivo"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Ya puedes inscribir tu dispositivo en el programa de financiación de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Ya puedes inscribir tu dispositivo en el programa de financiación de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Ya puedes inscribir tu dispositivo en el programa de subsidios de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Eres parte del programa de subsidios de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Inscripción del dispositivo"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede cambiar la configuración de este dispositivo"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Más información"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Información del dispositivo financiado"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Tu proveedor de crédito puede cambiar los parámetros de configuración e instalar la aplicación de Kiosco en el dispositivo.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> puede restringir este dispositivo si no realizas los pagos necesarios o si dejas de usar la SIM de <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPara obtener más información, comunícate con <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> puede cambiar los parámetros de configuración e instalar la aplicación de kiosco en el dispositivo.\n\nSi no realizas un pago, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> puede restringir el dispositivo.\n\nPara obtener más información, comunícate con <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> puede cambiar los parámetros de configuración e instalar la aplicación de kiosco en el dispositivo.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> también podría restringir este dispositivo si no realizas los pagos o si dejas de usar la SIM de <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPara obtener más información, comunícate con <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Hasta que pagues el dispositivo, no podrás hacer esto:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reiniciar el dispositivo de modo seguro"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Cambiar las zonas horarias, la fecha y la hora"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Usar opciones para desarrolladores"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Si tu dispositivo no funciona, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Puedes desinstalar la app de <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Para obtener ayuda:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Comunícate con <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provisión"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Se restablecerá el dispositivo en 1 día}other{Se restablecerá el dispositivo en # días}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Se restablecerá el dispositivo en <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Se borrarán todos los datos del dispositivo. Si necesitas ayuda para inscribir tu dispositivo, comunícate con <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Permite las notificaciones de DeviceLock para continuar difiriendo la inscripción del dispositivo."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"No se pudo provisionar la financiación"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Haz clic aquí para descubrir cómo puedes ponerte en contacto con tu financista. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Más información<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Salir"</string>
+    <string name="retry" msgid="7497287909193345356">"Reintentar"</string>
 </resources>
diff --git a/DeviceLockController/res/values-es/strings.xml b/DeviceLockController/res/values-es/strings.xml
index 35ff354..d84df7a 100644
--- a/DeviceLockController/res/values-es/strings.xml
+++ b/DeviceLockController/res/values-es/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Las solicitudes de bloqueo o desbloqueo de <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Si la aplicación <xliff:g id="CREDITOR_APP">%1$s</xliff:g> no está disponible"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licencias de software libre"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Las otras funciones de gestión que se indican en "<b>"Ajustes &gt; Seguridad &gt; Información sobre el dispositivo administrado"</b>" no se aplican a este dispositivo"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Las funciones de gestión que aparecen en la sección del dispositivo financiado de los ajustes de Seguridad no se aplican a este dispositivo."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Este dispositivo lo proporciona <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"La aplicación de kiosko se descargará e instalará automáticamente."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"La aplicación de kiosko se instalará para este usuario"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede restringir este dispositivo si no cumples con un pago."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede restringir este dispositivo si no cumples con un pago. Para ver más detalles, consulta los <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>términos y condiciones<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede restringir este dispositivo si no realizas los pagos necesarios. Para ver más detalles, consulta los <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Términos y Condiciones<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede restringir este dispositivo si el propietario no realiza los pagos"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Para obtener ayuda, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>contacta con <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Anterior"</string>
     <string name="next" msgid="8248291863254324326">"Siguiente"</string>
     <string name="start" msgid="2842214844667658537">"Iniciar"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Información"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Información de aprovisionamiento"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Registra el dispositivo"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Ahora puedes registrar tu dispositivo en el programa de financiación de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Ahora puedes registrar tu dispositivo en el programa de financiación de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Ahora puedes registrar tu dispositivo en el programa de compensación de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Estás en el programa de compensación de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Registro del dispositivo"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede cambiar los ajustes de este dispositivo"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Más información"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Información del dispositivo financiado"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Tu entidad de crédito puede cambiar ajustes e instalar la aplicación de kiosko en el dispositivo.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> puede restringir este dispositivo si no realizas los pagos necesarios o dejas de usar la SIM de <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPara obtener más información, contacta con <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> puede cambiar ajustes e instalar la aplicación de kiosko en el dispositivo.\n\nSi no cumples con un pago, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> puede restringir tu dispositivo.\n\nPara obtener más información, contacta con <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> puede cambiar ajustes e instalar la aplicación de kiosko en el dispositivo.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> también puede restringir este dispositivo si no cumples con un pago o dejas de usar la SIM de <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPara obtener más información, contacta con <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Hasta que hayas pagado tu dispositivo, no podrás:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reiniciar tu dispositivo en modo Seguro"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Cambiar la fecha, la hora y la zona horaria"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Usar opciones para desarrolladores"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Si surge algún problema con tu dispositivo, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> puede:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Puedes desinstalar la aplicación <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Para obtener ayuda, sigue estos pasos:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Ponte en contacto con <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Aprovisionamiento"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{El dispositivo se restablecerá en 1 día}other{El dispositivo se restablecerá en # días}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"El dispositivo se restablecerá en <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Se eliminarán todos los datos del dispositivo. Para obtener ayuda con el registro de tu dispositivo, contacta con <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Habilita las notificaciones de Bloqueo del dispositivo para seguir aplazando el registro del dispositivo."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"No se ha podido aprovisionar la financiación"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Haz clic aquí para consultar cómo contactar con tu asesor financiero. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Más información<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Salir"</string>
+    <string name="retry" msgid="7497287909193345356">"Reintentar"</string>
 </resources>
diff --git a/DeviceLockController/res/values-et/strings.xml b/DeviceLockController/res/values-et/strings.xml
index 382181a..33ac97b 100644
--- a/DeviceLockController/res/values-et/strings.xml
+++ b/DeviceLockController/res/values-et/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Kõik lukustamise või avamise taotlused rakenduselt <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Kui rakendus <xliff:g id="CREDITOR_APP">%1$s</xliff:g> pole saadaval"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Avatud lähtekoodi litsentsid"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Muud haldusfunktsioonid menüüs "<b>"Seaded &gt; Turvalisus &gt; Teave hallatud seadme kohta"</b>" selle seadme puhul ei kehti"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Haldusfunktsioonid turvaseadete jaotises „Teave seadme finantsandmete kohta“ selle seadme puhul ei kehti."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Selle seadme on andnud <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kioskirakendus laaditakse alla ja installitakse automaatselt"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kioskirakendus installitakse sellele kasutajale"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> saab selle seadme kasutust piirata, kui jätate makse vahele"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> saab seadme kasutust piirata, kui jätate makse vahele. Lisateavet leiate lehelt <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Nõuded ja tingimused<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> saab selle seadme kasutust piirata, kui te ei tee vajalikke makseid. Lisateavet leiate lehelt <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Nõuded ja tingimused<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> saab selle seadme kasutust piirata, kui omanik ei tee makseid"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Abi saamiseks <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>võtke ühendust teenusepakkujaga <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Eelmine"</string>
     <string name="next" msgid="8248291863254324326">"Edasi"</string>
     <string name="start" msgid="2842214844667658537">"Alusta"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Teave"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Pakkumise teave"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Registreerige seade"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Saate nüüd registreerida oma seadme teenusepakkuja <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> järelmaksuprogrammi"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Saate nüüd registreerida oma seadme teenusepakkuja <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> järelmaksuprogrammi"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Saate nüüd registreerida oma seadme teenusepakkuja <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> toetusprogrammi"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Olete teenusepakkuja <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> toetusprogrammis"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Seadme registreerimine"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> saab selle seadme seadeid muuta"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Lisateave"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Järelmaksuga seadme teave"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Teie krediidipakkuja saab muuta seadme seadeid ja installida kioskirakenduse.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> võib selle seadme kasutust piirata, kui te ei tee vajalikke makseid või lõpetate pakkuja <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIM-kaardi kasutamise.\n\nLisateabe saamiseks võtke ühendust pakkujaga <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> saab seadmes seadeid muuta ja kioskirakenduse installida.\n\nKui makse jääb tegemata, võib <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> teie seadme kasutust piirata.\n\nLisateabe saamiseks võtke ühendust teenusepakkujaga <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> saab seadmes seadeid muuta ja kioskirakenduse installida.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> võib selle seadme kasutust piirata ka siis, kui makse jääb tegemata või lõpetate teenusepakkuja <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM-i kasutamise.\n\nLisateabe saamiseks võtke ühendust teenusepakkujaga <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Enne seadme eest tasumist ei saa te teha järgmist."</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Seadme taaskäivitamine turvarežiimis"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Kuupäeva, kellaaja ja ajavööndi muutmine"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"kasutada arendaja valikuid"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Kui seadmega midagi juhtub, saab <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Saate rakenduse <xliff:g id="KIOSK_APP">%1$s</xliff:g> desinstallida"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Abi hankimiseks tehke järgmist:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Võtke ühendust teenusepakkujaga <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Pakkumine"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Seade lähtestatakse 1 päeva pärast}other{Seade lähtestatakse # päeva pärast}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Seade lähtestatakse <xliff:g id="TIMER">%s</xliff:g> pärast"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Kõik seadme andmed kustutatakse. Seadme registreerimisel abi saamiseks võtke ühendust pakkujaga <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Seadme registreerimise edasilükkamise jätkamiseks lubage märguanded rakenduselt DeviceLock."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Järelmaksu pakkumine ebaõnnestus"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Klõpsake siin, et näha, kuidas oma järelmaksu pakkujaga ühendust võtta. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Lisateave<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Välju"</string>
+    <string name="retry" msgid="7497287909193345356">"Proovi uuesti"</string>
 </resources>
diff --git a/DeviceLockController/res/values-eu/strings.xml b/DeviceLockController/res/values-eu/strings.xml
index 3d949e2..bf106ba 100644
--- a/DeviceLockController/res/values-eu/strings.xml
+++ b/DeviceLockController/res/values-eu/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> aplikazioak blokeatzeko edo desblokeatzeko eskaerarik egin duen."</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> aplikazioa erabilgarri dagoen ala ez."</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Kode irekiko lizentziak"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"Ezarpenak &gt; Segurtasuna &gt; Kudeatutako gailuari buruzko informazioa"</b>" ataleko gainerako kudeaketa-gaitasunak ez dira gailu honetan aplikagarriak"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Segurtasun-ezarpenetako gailu finantzatuaren ataleko kudeaketa-gaitasunak ez dira gailu honetan aplikagarriak."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzaileak eman du gailu hau"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosko-aplikazioa automatikoki deskargatu eta instalatuko da."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Erabiltzaile horri kiosko-aplikazioa instalatuko zaio"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Ordainketaren bat egiten ez baduzu, baliteke <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzaileak gailua murriztea."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Ordainketaren bat egiten ez baduzu, baliteke <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzaileak gailua murriztea. Xehetasunak lortzeko, ikusi <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Zehaztapenak eta baldintzak<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Beharrezko ordainketak egiten ez badituzu, baliteke <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzaileak gailua murriztea. Xehetasunak lortzeko, ikusi <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Zehaztapenak eta baldintzak<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Jabeak ordainketak egiten ez baditu, baliteke <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzaileak gailua murriztea"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Laguntza lortzeko, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>jarri <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzailearekin harremanetan<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Aurrekoa"</string>
     <string name="next" msgid="8248291863254324326">"Hurrengoa"</string>
     <string name="start" msgid="2842214844667658537">"Hasi"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informazioa"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Hornikuntza-informazioa"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Erregistratu gailua"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Orain, gailua <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzailearen finantzaketa-programan erregistra dezakezu"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Orain, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzailearen dirulaguntza-programan erregistra dezakezu gailua"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Orain, gailua <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzailearen dirulaguntza-programan erregistra dezakezu"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzailearen dirulaguntza-programan zaude"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Gailuaren erregistroa"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzaileak gailuaren ezarpenak alda ditzake"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Informazio gehiago"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Gailu finantzatuari buruzko informazioa"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Kreditu bidezko gailu-hornitzaileak, ezarpenak aldatu, eta gailuan kiosko-aplikazioa instala dezake.\n\nBaliteke <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> hornitzaileak gailua murriztea beharrezko ordainketak egiten ez badituzu edo <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> hornitzailearen SIMa erabiltzeari uzten badiozu.\n\nInformazio gehiago lortzeko, jarri <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> hornitzailearekin harremanetan."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> hornitzaileak, ezarpenak aldatu, eta gailuan kiosko-aplikazioa instala dezake.\n\nOrdainketaren bat egiten ez baduzu, baliteke <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> hornitzaileak gailua murriztea.\n\nInformazio gehiago lortzeko, jarri <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> hornitzailearekin harremanetan."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> hornitzaileak, ezarpenak aldatu, eta gailuan kiosko-aplikazioa instala dezake.\n\nHalaber, baliteke <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> hornitzaileak gailua murriztea ordainketaren bat egiten ez baduzu edo <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> hornitzailearen SIMa erabiltzeari uzten badiozu.\n\nInformazio gehiago lortzeko, jarri <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> hornitzailearekin harremanetan."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Gailua guztiz ordaindu arte, ezingo dituzu egin hauek:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Gailua modu seguruan berrabiarazi."</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Data, ordua eta ordu-zonak aldatu."</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Garatzaileentzako aukerak erabili."</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Gailuarekin arazoren bat badago, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzaileak hauek egin ditzake:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> aplikazioa desinstala dezakezu"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Laguntza lortzeko:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Jarri <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzailearekin harremanetan<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Hornikuntza"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Bihar berrezarriko da gailua}other{# egun barru berrezarriko da gailua}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"<xliff:g id="TIMER">%s</xliff:g> barru berrezarriko da gailua"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Gailuko datu guztiak ezabatuko dira. Gailua erregistratzearen inguruko laguntza jasotzeko, jarri <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> hornitzailearekin harremanetan"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Eman gailuaren erregistroa atzeratzen jarraitzeko baimena DeviceLock-en jakinarazpenari."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Finantzaketaren hornikuntzak huts egin du"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Sakatu hau zure finantzariarekin harremanetan jartzeko zer modu dituzun ikusteko. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Lortu informazio gehiago<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Irten"</string>
+    <string name="retry" msgid="7497287909193345356">"Saiatu berriro"</string>
 </resources>
diff --git a/DeviceLockController/res/values-fa/strings.xml b/DeviceLockController/res/values-fa/strings.xml
index c9c092b..49f821a 100644
--- a/DeviceLockController/res/values-fa/strings.xml
+++ b/DeviceLockController/res/values-fa/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"همه درخواست‌های قفل کردن یا باز کردن قفل ازطرف <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"اگر برنامه <xliff:g id="CREDITOR_APP">%1$s</xliff:g> دردسترس نباشد"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"پروانه‌های متن‌باز"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"دیگر قابلیت‌های مدیریتی موجود در "<b>"«تنظیمات &gt; امنیت &gt; اطلاعات دستگاه مدیریت‌شده»"</b>" شامل این دستگاه نمی‌شود"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"قابلیت‌های مدیریتی موجود در بخش دستگاه دارای پشتیبانی مالی از «تنظیمات ایمنی» شامل این دستگاه نمی‌شود."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"این دستگاه را <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ارائه کرده است"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"برنامه «کیوسک» به‌طور خودکار بارگیری و نصب خواهد شد"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"برنامه «کیوسک» برای این کاربر نصب خواهد شد"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"اگر پرداختی را انجام ندهید، <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> می‌تواند این دستگاه را محدود کند"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"اگر پرداختی را انجام ندهید، <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> می‌تواند دستگاه را محدود کند. برای جزئیات، <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>شرایط خدمات<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> را مشاهده کنید."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"اگر پرداخت‌های ضروری را انجام ندهید، <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> می‌تواند این دستگاه را محدود کند. برای جزئیات، <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>شرایط خدمات<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> را مشاهده کنید."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"اگر مالک پرداخت‌ها را انجام ندهد، <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> می‌تواند این دستگاه را محدود کند"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"برای راهنمایی، <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>با <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> تماس بگیرید<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"قبلی"</string>
     <string name="next" msgid="8248291863254324326">"بعدی"</string>
     <string name="start" msgid="2842214844667658537">"شروع"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"اطلاعات"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"اطلاعات تأمین"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"ثبت‌نام دستگاه"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"اکنون می‌توانید دستگاهتان را در برنامه تأمین مالی <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ثبت‌نام کنید"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"اکنون می‌توانید دستگاهتان را در برنامه مالی <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ثبت‌نام کنید"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"اکنون می‌توانید دستگاهتان را در برنامه یارانه <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ثبت‌نام کنید"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"در برنامه یارانه <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> هستید"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ثبت‌نام دستگاه"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> می‌تواند تنظیمات این دستگاه را تغییر دهد"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"بیشتر بدانید"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"اطلاعات دستگاه دارای پشتیبانی مالی"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"ارائه‌دهنده اعتبار می‌تواند تنظیمات را تغییر دهد و برنامه «کیوسک» را در دستگاه نصب کند.\n\nاگر پرداخت‌های ضروری را انجام ندهید یا استفاده از سیم‌کارت <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> را متوقف کنید، <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> می‌تواند این دستگاه را محدود کند.\n\nبرای کسب اطلاعات بیشتر، با <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> تماس بگیرید."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> می‌تواند تنظیمات را تغییر دهد و برنامه «کیوسکی» را در دستگاه نصب کند.\n\nاگر صورت‌حسابی را پرداخت نکنید، <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> می‌تواند دستگاهتان را محدود کند.\n\nبرای کسب اطلاعات بیشتر، با <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> تماس بگیرید."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> می‌تواند تنظیمات را تغییر دهد و برنامه «کیوسکی» را در دستگاه نصب کند.\n\nاگر صورت‌حسابی را پرداخت نکنید یا دیگر از سیم‌کارت <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> استفاده نکنید، <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ممکن است این دستگاه را محدود کند.\n\nبرای کسب اطلاعات بیشتر، با <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> تماس بگیرید."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"تا زمانی‌که هزینه دستگاه را پرداخت نکنید، نمی‌توانید:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"بازراه‌اندازی دستگاه در حالت ایمن"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"تغییر تاریخ، ساعت، و منطقه زمانی"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"استفاده از گزینه‌های توسعه‌دهندگان"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"اگر مشکلی در دستگاه رخ دهد، <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> می‌تواند:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"می‌توانید برنامه <xliff:g id="KIOSK_APP">%1$s</xliff:g> را حذف نصب کنید"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"برای دریافت راهنمایی:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>تماس با <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"تأمین"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{دستگاه یک روز دیگر بازنشانی خواهد شد}one{دستگاه # روز دیگر بازنشانی خواهد شد}other{دستگاه # روز دیگر بازنشانی خواهد شد}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"دستگاه <xliff:g id="TIMER">%s</xliff:g> دیگر بازنشانی خواهد شد"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"همه داده‌های دستگاه حذف خواهد شد. برای دریافت راهنمایی درخصوص ثبت‌نام دستگاه، با <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> تماس بگیرید"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"برای ادامه یافتن به‌تأخیر انداختن ثبت‌نام این دستگاه، لطفاً به اعلان‌های DeviceLock اجازه دهید."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"تأمین مالی انجام نشد"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"برای اطلاع از روش‌های تماس با تأمین‌کننده مالی، لطفاً اینجا کلیک کنید. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>بیشتر بدانید<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"خارج شدن"</string>
+    <string name="retry" msgid="7497287909193345356">"امتحان مجدد"</string>
 </resources>
diff --git a/DeviceLockController/res/values-fi/strings.xml b/DeviceLockController/res/values-fi/strings.xml
index dca7ee4..1b2bd16 100644
--- a/DeviceLockController/res/values-fi/strings.xml
+++ b/DeviceLockController/res/values-fi/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Lukitus- ja avauspyynnöt, joiden lähde on <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Jos <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ei ole käytettävissä"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Avoimen lähdekoodin lisenssit"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Muut hallinnointiominaisuudet kohdassa "<b>"Asetukset &gt; Suojaus &gt; Hallinnoidun laitteen tiedot"</b>" eivät koske tätä laitetta"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Suojausasetusten Rahoitettu laite ‑kohdassa olevat hallinnointiominaisuudet eivät koske tätä laitetta."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Tämän laitteen tarjoaa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk-sovellus ladataan ja asennetaan automaattisesti"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kiosk-sovellus asennetaan tälle käyttäjälle"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> voi rajoittaa laitetta, jos sinulta jää maksu välistä"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> voi rajoittaa laitetta, jos sinulta jää maksu välistä. Katso lisätietoa <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>käyttöehdoista<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> voi rajoittaa laitetta, jos et suorita pakollisia maksuja. Katso lisätietoa <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>käyttöehdoista<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> voi rajoittaa laitetta, jos omistaja ei suorita maksuja"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Jos tarvitset apua, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>laitevalmistajaan: <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Edellinen"</string>
     <string name="next" msgid="8248291863254324326">"Seuraava"</string>
     <string name="start" msgid="2842214844667658537">"Aloita"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Tiedot"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Tiedot tarjoamisesta"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Rekisteröi laite"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Voit nyt rekisteröidä laitteen rahoitusohjelmaan (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>)"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Voit nyt rekisteröidä laitteen rahoitusohjelmaan (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>)"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Voit nyt rekisteröidä laitteen tukiohjelmaan (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>)"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Olet liittynyt tukiohjelmaan (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>)"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Laitteen rekisteröinti"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> voi muuttaa laitteen asetuksia"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Lue lisää"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Rahoitetun laitteen tiedot"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Luoton myöntäjä voi muuttaa asetuksia ja asentaa Kiosk-sovelluksen laitteelle.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> voi rajoittaa laitetta, jos et suorita pakollisia maksuja tai lopetat SIM-kortin (<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>) käytön.\n\nJos haluat lisätietoa, ota yhteyttä: <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> voi muuttaa asetuksia ja asentaa Kiosk-sovelluksen laitteelle.\n\nJos sinulta jää maksu välistä, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> voi rajoittaa laitettasi.\n\nJos haluat lisätietoa, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> voi auttaa."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> voi muuttaa asetuksia ja asentaa Kiosk-sovelluksen laitteelle.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> voi myös rajoittaa laitetta, jos sinulta jää maksu välistä tai lopetat SIM-kortin (<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>) käytön.\n\nJos haluat lisätietoa, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> voi auttaa."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Et voi tehdä näitä, ennen kuin olet maksanut laitteesta:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Käynnistää laitteen uudelleen vikasietotilassa"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Muuttaa päivämäärää, aikaa ja aikavyöhykkeitä"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Käyttää kehittäjäasetuksia"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Jos jotain menee laitteella, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> voi tehdä näitä:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Voit poistaa sovelluksen: <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Jos tarvitset apua:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Ota yhteyttä: <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Tarjous"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Laite nollataan 1 päivän kuluttua}other{Laite nollataan # päivän kuluttua}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Laite nollataan, kun <xliff:g id="TIMER">%s</xliff:g> on kulunut"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Kaikki laitteen data poistetaan. Jos tarvitset apua laitteen rekisteröintiin, ota yhteyttä palveluntarjoajaan: <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Salli DeviceLockin ilmoitus, niin voit jatkaa laitteen rekisteröinnin lykkäämistä."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Rahoituksen tarjoaminen epäonnistui"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Klikkaa tästä, niin näet tapoja ottaa yhteyttä rahoittajaan. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Lue lisää<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Sulje"</string>
+    <string name="retry" msgid="7497287909193345356">"Yritä uudelleen"</string>
 </resources>
diff --git a/DeviceLockController/res/values-fr-rCA/strings.xml b/DeviceLockController/res/values-fr-rCA/strings.xml
index 32532cb..42bacfb 100644
--- a/DeviceLockController/res/values-fr-rCA/strings.xml
+++ b/DeviceLockController/res/values-fr-rCA/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Toute demande de verrouillage ou de déverrouillage de <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Si l\'application <xliff:g id="CREDITOR_APP">%1$s</xliff:g> n\'est pas accessible"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licences de logiciels libres"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Les autres fonctionnalités de gestion sous "<b>"Paramètres &gt; Sécurité &gt; Renseignements sur l\'appareil géré"</b>" ne s\'appliquent pas à cet appareil"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Les capacités de gestion indiquées dans la section relative aux appareils financés dans les paramètres de sécurité ne s\'appliquent pas à cet appareil."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Cet appareil est fourni par <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"L\'application kiosque sera téléchargée et installée automatiquement"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"L\'application Kiosque sera installée pour cet utilisateur"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut restreindre cet appareil si vous manquez un paiement"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut restreindre l\'accès à l\'appareil si vous manquez un paiement. Pour en savoir plus, consultez les <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>conditions d\'utilisation<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut restreindre cet appareil si vous n\'effectuez pas les paiements nécessaires. Pour en savoir plus, consultez les <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>conditions d\'utilisation<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut restreindre cet appareil si le propriétaire n\'effectue pas les paiements"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Pour obtenir de l\'aide, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>communiquez avec <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Précédent"</string>
     <string name="next" msgid="8248291863254324326">"Suivant"</string>
     <string name="start" msgid="2842214844667658537">"Commencer"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Info"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Infos sur provision"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Inscrire l\'appareil"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Vous pouvez désormais inscrire votre appareil au programme de financement de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Vous pouvez désormais inscrire votre appareil au programme de financement de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Vous pouvez désormais inscrire votre appareil au programme de subvention de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Vous bénéficiez d\'une subvention de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Inscription de l\'appareil"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut modifier les paramètres de cet appareil"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"En savoir plus"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Renseignements sur l\'appareil financé"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Votre fournisseur de crédit peut modifier les paramètres de l\'appareil et y installer l\'application Kiosk.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> peut restreindre cet appareil si vous n\'effectuez pas les paiements nécessaires ou si vous cessez d\'utiliser la carte SIM de <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPour en savoir plus, communiquez avec <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> peut modifier les paramètres de l\'appareil et y installer l\'application Kiosque.\n\nSi vous manquez un paiement, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> peut restreindre votre appareil.\n\nPour en savoir plus, communiquez avec <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> peut modifier les paramètres de l\'appareil et y installer l\'application Kiosque.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> peut également restreindre cet appareil si vous manquez un paiement ou si vous cessez d\'utiliser la carte SIM de <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPour en savoir plus, communiquez avec <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Tant que l\'appareil n\'est pas payé, vous ne pouvez pas :"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Redémarrer votre appareil en mode sans échec"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Modifier la date, l\'heure et les fuseaux horaires"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Utiliser les options pour développeurs"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"En cas de problème d\'appareil, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut :"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Vous pouvez désinstaller l\'application <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Pour obtenir de l\'aide :"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Communiquer avec <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provision"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{L\'appareil sera réinitialisé dans 1 jour}one{L\'appareil sera réinitialisé dans # jour}other{L\'appareil sera réinitialisé dans # jours}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"L\'appareil sera réinitialisé dans <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Toutes les données de l\'appareil seront supprimées. Pour obtenir de l\'aide concernant l\'inscription de votre appareil, communiquez avec <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Veuillez autoriser les notifications de DeviceLock pour continuer à différer l\'inscription de l\'appareil."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Le provisionnement du financement a échoué"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Veuillez cliquer ici pour connaître les moyens de communiquer avec votre financeur. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>En savoir plus<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Quitter"</string>
+    <string name="retry" msgid="7497287909193345356">"Réessayer"</string>
 </resources>
diff --git a/DeviceLockController/res/values-fr/strings.xml b/DeviceLockController/res/values-fr/strings.xml
index cafa481..e294b41 100644
--- a/DeviceLockController/res/values-fr/strings.xml
+++ b/DeviceLockController/res/values-fr/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Les demandes de verrouillage ou de déverrouillage de <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Si l\'appli <xliff:g id="CREDITOR_APP">%1$s</xliff:g> n\'est pas disponible"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licences Open Source"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Les autres fonctionnalités de gestion sous "<b>"Paramètres &gt; Sécurité &gt; Infos sur l\'appareil géré"</b>" ne s\'appliquent pas à cet appareil"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Les fonctionnalités de gestion situées dans la section sur l\'appareil financé des paramètres de sécurité ne s\'appliquent pas à cet appareil."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Cet appareil est fourni par <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"L\'application kiosque sera téléchargée et installée automatiquement."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"L\'application kiosque sera installée pour cet utilisateur"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut limiter l\'utilisation de cet appareil en cas de manquement de paiement."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut limiter l\'utilisation de l\'appareil en cas de manquement de paiement. Pour plus d\'informations, consultez les <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Conditions d\'utilisation<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut limiter l\'utilisation de cet appareil si vous n\'effectuez pas les paiements nécessaires. Pour plus d\'informations, consultez les <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Conditions d\'utilisation<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut limiter l\'utilisation de cet appareil si le propriétaire n\'effectue pas de paiement"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Pour obtenir de l\'aide, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>contactez <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Précédent"</string>
     <string name="next" msgid="8248291863254324326">"Suivant"</string>
     <string name="start" msgid="2842214844667658537">"Commencer"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Infos"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Infos de provision"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Enregistrer votre appareil"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Vous pouvez enregistrer votre appareil dans le programme de financement de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Vous pouvez enregistrer votre appareil dans le programme de financement de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Vous pouvez à présent enregistrer votre appareil dans le programme de subvention de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Programme de subvention de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> activé"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Enregistrement des appareils"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut modifier les paramètres de cet appareil"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"En savoir plus"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informations sur l\'appareil financé"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Votre société de crédit peut modifier les paramètres et installer l\'application kiosque sur l\'appareil.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> peut limiter l\'utilisation de cet appareil si vous n\'effectuez pas les paiements nécessaires ou si vous cessez d\'utiliser la carte SIM de <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPour en savoir plus, contactez <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> peut modifier les paramètres et installer l\'application kiosque sur l\'appareil.\n\nEn cas de manquement de paiement, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> peut limiter l\'utilisation de votre appareil.\n\nPour en savoir plus, contactez <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> peut modifier les paramètres et installer l\'application kiosque sur l\'appareil.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> peut également limiter l\'utilisation de cet appareil en cas de manquement de paiement ou si vous cessez d\'utiliser la carte SIM de <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPour en savoir plus, contactez <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"En attendant le paiement de l\'appareil, vous ne pouvez pas :"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Redémarrer votre appareil en mode sans échec"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Modifier la date, l\'heure et les fuseaux horaires"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Utiliser les options pour développeurs"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"En cas de problème, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> peut :"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Vous pouvez désinstaller l\'application <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Pour obtenir de l\'aide :"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contacter <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provision"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Réinitialisation de l\'appareil dans 1 j}one{Réinitialisation de l\'appareil dans # j}other{Réinitialisation de l\'appareil dans # j}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Réinitialisation de l\'appareil dans <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Toute les données de l\'appareil seront supprimées. Pour obtenir de l\'aide lors de l\'enregistrement de votre appareil, contactez <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Veuillez autoriser les notifications de DeviceLock pour continuer à reporter l\'inscription de l\'appareil."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Le provisionnement du financement a échoué"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Pour contacter votre financier, cliquez ici. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>En savoir plus<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Quitter"</string>
+    <string name="retry" msgid="7497287909193345356">"Réessayer"</string>
 </resources>
diff --git a/DeviceLockController/res/values-gl/strings.xml b/DeviceLockController/res/values-gl/strings.xml
index 3916507..f665cf7 100644
--- a/DeviceLockController/res/values-gl/strings.xml
+++ b/DeviceLockController/res/values-gl/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"As solicitudes de bloqueo e desbloqueo de <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Se a aplicación <xliff:g id="CREDITOR_APP">%1$s</xliff:g> non está dispoñible"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licenzas de código aberto"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"As outras funcións de xestión dispoñibles en "<b>"Configuración &gt; Seguranza &gt; Información sobre o dispositivo xestionado"</b>" non se aplican a este dispositivo"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Non se aplican a este dispositivo as funcións de xestión dispoñibles na sección do dispositivo financiado da opción de configuración Seguranza."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> proporciona este dispositivo."</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"A aplicación de quiosco descargarase e instalarase de xeito automático"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"A aplicación de quiosco instalarase para este usuario"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restrinxir o uso deste dispositivo se che falta algún pago"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restrinxir o uso do dispositivo se che falta algún pago por facer. Tes máis información nos <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termos e condicións<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restrinxir o uso deste dispositivo se non fas os pagos necesarios. Consulta máis información nos <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termos e condicións<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restrinxir o uso deste dispositivo se a persoa propietaria non fai pagos"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Para recibir axuda, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ponte en contacto con <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Anterior"</string>
     <string name="next" msgid="8248291863254324326">"Seguinte"</string>
     <string name="start" msgid="2842214844667658537">"Iniciar"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Información"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Info de provisión"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Inscribe o teu dispositivo"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Xa podes inscribir o dispositivo no programa de finanzas de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Xa podes inscribir o dispositivo no programa de financiamento de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Xa podes inscribir o dispositivo no programa de bonificación de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Estás no programa de bonificación de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Inscrición do dispositivo"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode modificar a configuración deste dispositivo"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Máis información"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Info sobre o dispositivo financiado"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"A túa entidade de crédito pode modificar a configuración do dispositivo e instalar nel a aplicación de quiosco.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pode restrinxir o uso deste dispositivo se non fas os pagos necesarios ou se deixas de usar a SIM de <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPara obter máis información, ponte en contacto con <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pode modificar a configuración e instalar a aplicación de quiosco no dispositivo.\n\nSe non realizas algún pago, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> pode restrinxir o uso do teu dispositivo.\n\nPara obter máis información, ponte en contacto con <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pode modificar a configuración e instalar a aplicación de quiosco no dispositivo.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> tamén pode restrinxir o uso deste dispositivo se non realizas algún pago ou se deixas de usar SIM de <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPara obter máis información, ponte en contacto con <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Mentres non pagues o dispositivo, non podes:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reiniciar o dispositivo no modo seguro"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Cambiar a data, a hora e os fusos horarios"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Usar as opcións de programador"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"En caso de problema co dispositivo, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Podes desinstalar a aplicación <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Para recibir axuda:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contactar con <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provisión"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{O dispositivo restablecerase dentro de 1 día}other{O dispositivo restablecerase dentro de # días}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"O dispositivo restablecerase dentro de <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Eliminaranse todos os datos do dispositivo. Se precisas axuda para inscribilo, ponte en contacto con <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Permite as notificacións de DeviceLock para continuar pospoñendo a inscrición do dispositivo."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Produciuse un erro durante o aprovisionamento financeiro"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Fai clic aquí para poñerte en contacto co teu financeiro. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Máis información<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Saír"</string>
+    <string name="retry" msgid="7497287909193345356">"Tentar de novo"</string>
 </resources>
diff --git a/DeviceLockController/res/values-gu/strings.xml b/DeviceLockController/res/values-gu/strings.xml
index a0a0102..5bc95de 100644
--- a/DeviceLockController/res/values-gu/strings.xml
+++ b/DeviceLockController/res/values-gu/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>ની કોઈપણ લૉક કે અનલૉક કરવાની વિનંતીઓ"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"જો <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ઍપ ઉપલબ્ધ ન હોય, તો"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ઓપન સૉર્સ લાઇસન્સ"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"મેનેજમેન્ટની "<b>"સેટિંગ &gt; સુરક્ષા &gt; મેનેજ કરવામાં આવતા ડિવાઇસની માહિતી"</b>"માંની અન્ય ક્ષમતાઓ આ ડિવાઇસ પર લાગુ થતી નથી"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"સુરક્ષા સેટિંગના ફાઇનાન્સ ડિવાઇસ વિભાગમાં મેનેજમેન્ટની ક્ષમતાઓ આ ડિવાઇસ પર લાગુ થતી નથી."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"આ ડિવાઇસ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> દ્વારા પ્રદાન કરવામાં આવેલું છે"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"કિઓસ્ક ઍપ ઑટોમૅટિક રીતે ડાઉનલોડ અને ઇન્સ્ટૉલ થશે"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"આ વપરાશકર્તા માટે Kiosk ઍપ ઇન્સ્ટૉલ કરવામાં આવશે"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"જો તમે કોઈ ચુકવણી ચૂકો, તો <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> આ ડિવાઇસને પ્રતિબંધિત કરી શકે છે"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"જો તમે કોઈ ચુકવણી ચૂકો, તો <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ડિવાઇસને પ્રતિબંધિત કરી શકે છે. વિગતો માટે, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>નિયમો અને શરતો<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> જુઓ."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"જો તમે જરૂરી ચુકવણીઓ ન કરો, તો <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> આ ડિવાઇસને પ્રતિબંધિત કરી શકે છે. વિગતો માટે, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>નિયમો અને શરતો<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> જુઓ."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"જો માલિક ચુકવણીઓ ન કરે, તો <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> આ ડિવાઇસને પ્રતિબંધિત કરી શકે છે"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"સહાય માટે, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>નો સંપર્ક કરો<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"પાછળ"</string>
     <string name="next" msgid="8248291863254324326">"આગળ"</string>
     <string name="start" msgid="2842214844667658537">"શરૂ કરો"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"માહિતી"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"જોગવાઈની માહિતી"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"તમારા ડિવાઇસની નોંધણી કરો"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"તમે હવે તમારા ડિવાઇસની નોંધણી <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ના ફાઇનાન્સ પ્રોગ્રામમાં કરી શકશો"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"તમે હવે તમારા ડિવાઇસની નોંધણી <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ના ફાઇનાન્સ પ્રોગ્રામમાં કરી શકશો"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"તમે હવે તમારા ડિવાઇસની નોંધણી <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ના સબસિડી પ્રોગ્રામમાં કરી શકશો"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"તમે <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ના સબસિડી પ્રોગ્રામનો ભાગ છો"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ડિવાઇસની નોંધણી"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>, આ ડિવાઇસના સેટિંગમાં ફેરફાર કરી શકશે"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"વધુ જાણો"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"લોન પર લીધેલા ડિવાઇસની માહિતી"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"ક્રેડિટ પર તમને વેચાણ કરનારા આ ડિવાઇસ પર સેટિંગમાં ફેરફાર કરી શકશે તેમજ Kiosk ઍપ ઇન્સ્ટૉલ કરી શકશે.\n\nજો તમે જરૂરી ચુકવણીઓ ન કરો અથવા <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>નો સિમ કાર્ડનો ઉપયોગ બંધ કરી દો, તો <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> આ ડિવાઇસને પ્રતિબંધિત કરી શકશે.\n\nવધુ જાણવા માટે, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>નો સંપર્ક કરો."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> આ ડિવાઇસના સેટિંગમાં ફેરફાર કરી શકે છે તેમજ કિઓસ્ક ઍપ ઇન્સ્ટૉલ કરી શકે છે.\n\nજો તમે કોઈ ચુકવણી ચૂકી જાઓ, તો <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> તમારા ડિવાઇસને પ્રતિબંધિત કરી શકે છે.\n\nવધુ જાણવા માટે, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>નો સંપર્ક કરો."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> આ ડિવાઇસના સેટિંગમાં ફેરફાર કરી શકે છે તેમજ કિઓસ્ક ઍપ ઇન્સ્ટૉલ કરી શકે છે.\n\nજો તમે કોઈ ચુકવણી ચૂકી જાઓ અથવા <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>ના સિમ કાર્ડનો ઉપયોગ કરવાનું બંધ કરો, તો <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> આ ડિવાઇસને પ્રતિબંધિત કરી શકે છે.\n\nવધુ જાણવા માટે, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>નો સંપર્ક કરો."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"જ્યાં સુધી ડિવાઇસની પૂર્ણ ચુકવણી કરો નહીં, ત્યાં સુધી તમે:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"તમારા ડિવાઇસને સુરક્ષિત મોડમાં રીબૂટ કરી શકાશે"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"તારીખ, સમય અને સમય ઝોનમાં ફેરફાર કરી શકાશે"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ડેવલપરના વિકલ્પોનો ઉપયોગ કરી શકાશે"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"જો તમારા ડિવાઇસમાં કંઈક ખોટું થાય, તો <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> આમ કરી શકશે:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"તમે <xliff:g id="KIOSK_APP">%1$s</xliff:g> ઍપને અનઇન્સ્ટૉલ કરી શકશો"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"સહાય મેળવવા માટે:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>નો સંપર્ક કરો<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"જોગવાઈ"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{ડિવાઇસને 1 દિવસમાં રીસેટ કરવામાં આવશે}one{ડિવાઇસને # દિવસમાં રીસેટ કરવામાં આવશે}other{ડિવાઇસને # દિવસમાં રીસેટ કરવામાં આવશે}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"ડિવાઇસ રીસેટ થવાનો કાઉન્ટર <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ડિવાઇસનો તમામ ડેટા ડિલીટ કરવામાં આવશે. તમારા ડિવાઇસની નોંધણીમાં સહાય માટે, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>નો સંપર્ક કરો"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"આ ડિવાઇસની નોંધણી મુલતવી રાખવાનું ચાલુ રાખવા માટે, કૃપા કરીને DeviceLockના નોટિફિકેશનને મંજૂરી આપો."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ફાઇનાન્સ સંબંધી જોગવાઈઓ નિષ્ફળ થઈ છે"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"તમારા ફાઇનાન્સરનો સંપર્ક કરવાની રીતો જાણવા માટે, કૃપા કરીને અહીં ક્લિક કરો. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>વધુ જાણો<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"બહાર નીકળો"</string>
+    <string name="retry" msgid="7497287909193345356">"ફરી પ્રયાસ કરો"</string>
 </resources>
diff --git a/DeviceLockController/res/values-hi/strings.xml b/DeviceLockController/res/values-hi/strings.xml
index 7966324..8b76442 100644
--- a/DeviceLockController/res/values-hi/strings.xml
+++ b/DeviceLockController/res/values-hi/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"लॉक या अनलॉक करने के लिए, <xliff:g id="CREDITOR_APP">%1$s</xliff:g> से किए गए अनुरोध"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"जब उपयोगकर्ता के डिवाइस में, <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ऐप्लिकेशन मौजूद न हो"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ओपन सोर्स लाइसेंस"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"सेटिंग &gt; सुरक्षा &gt; मैनेज किए जा रहे डिवाइस की जानकारी"</b>" में मौजूद मैनेज करने से जुड़ी दूसरी अनुमतियां, इस डिवाइस पर लागू नहीं होंगी"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"सुरक्षा सेटिंग के फ़ाइनेंस किए गए डिवाइस वाले सेक्शन में मौजूद, मैनेज करने से जुड़ी अनुमतियां, इस डिवाइस पर लागू नहीं होंगी."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"यह डिवाइस <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ने दिया है"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"कीऑस्क ऐप्लिकेशन, अपने-आप डाउनलोड और इंस्टॉल हो जाएगा"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"इस उपयोगकर्ता के लिए कीऑस्क ऐप्लिकेशन इंस्टॉल किया जाएगा"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"पेमेंट न करने पर, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> इस डिवाइस पर पाबंदी लगा सकता है"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"पेमेंट न करने पर, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> इस डिवाइस पर पाबंदी लगा सकता है. ज़्यादा जानकारी के लिए, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>नियम और शर्तें<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> देखें."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"ज़रूरी पेमेंट न करने पर, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> इस डिवाइस पर पाबंदी लगा सकता है. ज़्यादा जानकारी के लिए, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>नियम और शर्तें<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> देखें."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"मालिक के पेमेंट न करने पर, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> इस डिवाइस पर पाबंदी लगा सकता है"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"मदद के लिए, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g> से संपर्क करें."</string>
     <string name="previous" msgid="5241891780917802570">"पीछे जाएं"</string>
     <string name="next" msgid="8248291863254324326">"आगे बढ़ें"</string>
     <string name="start" msgid="2842214844667658537">"शुरू करें"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"जानकारी"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"प्रॉविज़निंग का डेटा"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"अपना डिवाइस रजिस्टर करें"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"अब आपका डिवाइस, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> के फ़ाइनेंस प्रोग्राम में रजिस्टर किया जा सकता है"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"अब आपका डिवाइस, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> के फ़ाइनेंस प्रोग्राम में रजिस्टर किया जा सकता है"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"अब आपका डिवाइस, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> के सब्सिडी प्रोग्राम में रजिस्टर किया जा सकता है"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"आप <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> के सब्सिडी प्रोग्राम में शामिल हैं"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"डिवाइस रजिस्टर करें"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>, इस डिवाइस की सेटिंग में बदलाव कर सकता है"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"ज़्यादा जानें"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"फ़ाइनेंस किए गए डिवाइस की जानकारी"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"क्रेडिट सेवा देने वाली कंपनी, डिवाइस की सेटिंग में बदलाव कर सकती है और उस पर कीऑस्क ऐप्लिकेशन इंस्टॉल कर सकती है.\n\nज़रूरी पेमेंट न करने पर या <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> का सिम इस्तेमाल बंद करने पर, <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> इस डिवाइस पर पाबंदी लगा सकता है.\n\nज़्यादा जानने के लिए, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> से संपर्क करें."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> के पास डिवाइस की सेटिंग में बदलाव करने और उस पर कीऑस्क ऐप्लिकेशन इंस्टॉल करने का विकल्प है.\n\nअगर आपसे कोई पेमेंट छूट जाता है, तो <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> के पास आपके डिवाइस पर पाबंदी लगाने का विकल्प होता है.\n\nइस बारे में ज़्यादा जानने के लिए, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> से संपर्क करें."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> के पास डिवाइस की सेटिंग में बदलाव करने और उस पर कीऑस्क ऐप्लिकेशन इंस्टॉल करने का विकल्प है.\n\nअगर आपसे कोई पेमेंट छूट गया है या आपने <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> के सिम का इस्तेमाल करना बंद कर दिया है, तो <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> के पास इस डिवाइस पर पाबंदी लगाने का विकल्प है.\n\nइस बारे में ज़्यादा जानने के लिए, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> से संपर्क करें."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"डिवाइस के लिए पैसे न चुकाए जाने तक ये काम नहीं किए जा सकते:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"अपने डिवाइस को सुरक्षित मोड में फिर से चालू करें"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"तारीख, समय, और टाइम ज़ोन में बदलाव करें"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"डेवलपर के लिए सेटिंग और टूल का यूज़ करें"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"डिवाइस में गड़बड़ी होने पर <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> यह कर सकता है:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> ऐप्लिकेशन को अनइंस्टॉल किया जा सकता है"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"सहायता के लिए यहां देखें:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> से संपर्क करें<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"प्रॉविज़न"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{डिवाइस 1 दिन में रीसेट हो जाएगा}one{डिवाइस # दिन में रीसेट हो जाएगा}other{डिवाइस # दिन में रीसेट हो जाएगा}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"डिवाइस <xliff:g id="TIMER">%s</xliff:g> में रीसेट हो जाएगा"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"डिवाइस का सारा डेटा मिटा दिया जाएगा. अपने डिवाइस को रजिस्टर करने में मदद पाने के लिए, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> से संपर्क करें"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"डिवाइस का रजिस्ट्रेशन करने की तारीख आगे बढ़ाते रहने के लिए, कृपया DeviceLock से सूचना पाने की सुविधा चालू करें."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"डिवाइस प्रॉविज़निंग को फ़ाइनेंस नहीं किया जा सका"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"कृपया, अपने फ़ाइनेंशियर से संपर्क करने के तरीके जानने के लिए यहां क्लिक करें. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>ज़्यादा जानें<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"बाहर निकलें"</string>
+    <string name="retry" msgid="7497287909193345356">"फिर से कोशिश करें"</string>
 </resources>
diff --git a/DeviceLockController/res/values-hr/strings.xml b/DeviceLockController/res/values-hr/strings.xml
index 0f26436..4b49240 100644
--- a/DeviceLockController/res/values-hr/strings.xml
+++ b/DeviceLockController/res/values-hr/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Svi zahtjevi aplikacije <xliff:g id="CREDITOR_APP">%1$s</xliff:g> za zaključavanje ili otključavanje"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Je li aplikacija <xliff:g id="CREDITOR_APP">%1$s</xliff:g> nedostupna"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licence otvorenog koda"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Druge mogućnosti upravljanja u odjeljku "<b>"Postavke &gt; Sigurnost &gt; Informacije o upravljanom uređaju"</b>" ne primjenjuju se na ovaj uređaj"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Mogućnosti upravljanja u odjeljku uređaja na pretplatu u sigurnosnim postavkama ne primjenjuju se na ovaj uređaj."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Ovaj uređaj pruža <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk aplikacija automatski će se preuzeti i instalirati"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kiosk aplikacija instalirat će se za ovog korisnika"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Davatelj usluge <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može ograničiti ovaj uređaj ako propustite plaćanje"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Davatelj usluge <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može ograničiti vašu upotrebu uređaja ako propustite plaćanje. Pojedinosti potražite u <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>uvjetima i odredbama<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Davatelj usluge <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može ograničiti ovaj uređaj ako ne izvršite potrebna plaćanja. Za pojedinosti pogledajte <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>uvjete i odredbe<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Davatelj usluge <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može ograničiti ovaj uređaj ako vlasnik ne izvrši plaćanje"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Za pomoć <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>se obratite davatelju usluga <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Prethodno"</string>
     <string name="next" msgid="8248291863254324326">"Dalje"</string>
     <string name="start" msgid="2842214844667658537">"Početak"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informacije"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Podaci o pristupu"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Prijavite svoj uređaj"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Odsad možete prijaviti svoj uređaj u financijski program davatelja usluge <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Svoj uređaj sada možete prijaviti u financijski program davatelja usluge <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Odsad možete prijaviti svoj uređaj u program subvencioniranja davatelja usluge <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Uključeni ste u program subvencioniranja davatelja usluge <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Prijava uređaja"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može promijeniti postavke na ovom uređaju"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Saznajte više"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informacije o uređaju na pretplatu"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Vaš operater može promijeniti postavke i instalirati kiosk aplikaciju na uređaju.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> može ograničiti ovaj uređaj ako ne izvršite potrebna plaćanja ili prestanete upotrebljavati SIM karticu davatelja usluge <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nDa biste saznali više, obratite se davatelju usluge <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> može promijeniti postavke i instalirati kiosk aplikaciju na uređaju.\n\nAko propustite plaćanje, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> može ograničiti vaš uređaj.\n\nDa biste saznali više, obratite se davatelju usluge <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> može promijeniti postavke i instalirati kiosk aplikaciju na uređaju.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> može i ograničiti ovaj uređaj ako propustite plaćanje ili prestanete upotrebljavati SIM davatelja usluge <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nDa biste saznali više, obratite se davatelju usluge <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Dok ne platite uređaj, ne možete:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"ponovno pokrenuti uređaj u sigurnom načinu rada"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"promjena datuma, vremena i vremenske zone"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"koristiti opcije za razvojne programere"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"U slučaju pogreške s uređajem <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> može:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Možete deinstalirati aplikaciju <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Ako trebate pomoć:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Obratite se davatelju <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Omogući pristup"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Uređaj će se ponovno pokrenuti za 1 dan}one{Uređaj će se ponovno pokrenuti za # dan}few{Uređaj će se ponovno pokrenuti za # dana}other{Uređaj će se ponovno pokrenuti za # dana}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Uređaj će se poništiti za <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Svi će se podaci o uređaju izbrisati. Za pomoć pri prijavi uređaja kontaktirajte davatelja usluga <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Omogućite obavijest od DeviceLocka da biste nastavili s odgodom prijave uređaja."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Financijski pristup nije uspio"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Kliknite ovdje da biste pronašli načine na koje možete kontaktirati svog financijera. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Saznajte više<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Izlaz"</string>
+    <string name="retry" msgid="7497287909193345356">"Pokušaj ponovo"</string>
 </resources>
diff --git a/DeviceLockController/res/values-hu/strings.xml b/DeviceLockController/res/values-hu/strings.xml
index 6bda733..b862e7e 100644
--- a/DeviceLockController/res/values-hu/strings.xml
+++ b/DeviceLockController/res/values-hu/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Minden zárolási és feloldási kérelem a következőtől: <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Ha a következő alkalmazás nem áll rendelkezésre: <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Nyílt forráskódú licencek"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"A "<b>"Beállítások &gt; Biztonság &gt; Felügyelt eszköz adatai"</b>" részben található további kezelési lehetőségek nem vonatkoznak erre az eszközre."</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"A Biztonsági beállítások Finanszírozott eszközök adatai részében található kezelési lehetőségek nem vonatkoznak erre az eszközre."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Ezt az eszközt a(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> biztosítja"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"A kioszkalkalmazás automatikusan letöltődik és települ"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"A kioszkalkalmazás telepítésre kerül ezen felhasználó számára"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"A(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> korlátozhatja ezt az eszközt, ha kihagy egy szükséges befizetést."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"A(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> korlátozhatja az eszközt, ha Ön elmulaszt egy befizetést. A részleteket az <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Általános Szerződési Feltételekben<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> találja."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"A(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> korlátozhatja ezt az eszközt, ha nem teljesíti a szükséges befizetéseket. A részleteket az <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Általános Szerződési Feltételekben<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> találja."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"A(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> korlátozhatja ezt az eszközt, ha a tulajdonos nem teljesíti a befizetéseket."</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Segítségért <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>forduljon a következőhöz: <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Előző"</string>
     <string name="next" msgid="8248291863254324326">"Következő"</string>
     <string name="start" msgid="2842214844667658537">"Kezdés"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Információ"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Kiépítési adatok"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Az eszköz regisztrálása"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Most már regisztrálhatja eszközét a(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> finanszírozási programjába"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Most már regisztrálhatja eszközét a(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> finanszírozási programjába"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Most már regisztrálhatja eszközét a(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> támogatási programjába"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Ön a(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> támogatási programjának részese"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Eszközregisztráció"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"A(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> megváltoztathatja a beállításokat ezen az eszközön"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"További információ"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Információk a finanszírozott eszközről"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"A hitelező módosíthatja az eszköz beállításait, és kioszkalkalmazást telepíthet rá.\n\nA(z) <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> korlátozhatja az eszközt, ha elmulasztja a szükséges befizetéseket, vagy nem a(z) <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIM-kártyáját használja.\n\nTovábbi információ: <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"A(z) <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> módosíthatja az eszköz beállításait, és kioszkalkalmazást telepíthet rá.\n\nHa elmulaszt egy befizetést, a(z) <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> korlátozhatja az eszközt.\n\nTovábbi információért forduljon a szolgáltatóhoz (<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>)."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"A(z) <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> módosíthatja az eszköz beállításait, és kioszkalkalmazást telepíthet rá.\n\nA(z) <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> korlátozhatja is az alkalmazást, ha Ön elmulaszt egy befizetést, vagy nem a(z) <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM-kártyáját használja.\n\nTovábbi információért forduljon a szolgáltatóhoz (<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>)."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Amíg nem fizet eszközéért, nem képes a következőkre:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Az eszköz újraindítása csökkentett módban"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Dátum, időpont és időzónák módosítása"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Fejlesztői beállítások használata"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Az eszköz problémái esetén a(z) <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> képes a következőkre:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Eltávolíthatja a(z) <xliff:g id="KIOSK_APP">%1$s</xliff:g> alkalmazást"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Ha segítségre van szüksége:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kapcsolatfelvétel: <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Kiépítés"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Az eszköz visszaállításra kerül 1 nap múlva}other{Az eszköz visszaállításra kerül # nap múlva}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"<xliff:g id="TIMER">%s</xliff:g> múlva az eszköz visszaállításra kerül"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Az eszközön lévő minden adat törlésre kerül. Ha segítségre van szüksége eszköze regisztrálásához, forduljon a következőhöz: <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Engedélyezze a DeviceLock értesítéseit, ha továbbra is halasztani szeretné az eszköz regisztrációját."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"A finanszírozási kiépítés sikertelen volt"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"A finanszíróval való kapcsolatfelvételi módokért kattintson ide. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>További információ<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>."</string>
+    <string name="exit" msgid="645084771882733921">"Kilépés"</string>
+    <string name="retry" msgid="7497287909193345356">"Újra"</string>
 </resources>
diff --git a/DeviceLockController/res/values-hy/strings.xml b/DeviceLockController/res/values-hy/strings.xml
index 1f2fa2d..d8dcf7e 100644
--- a/DeviceLockController/res/values-hy/strings.xml
+++ b/DeviceLockController/res/values-hy/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> հավելվածից ստացված կողպման և ապակողպման բոլոր հարցումները"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Եթե <xliff:g id="CREDITOR_APP">%1$s</xliff:g> հավելվածը հասանելի չէ"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Բաց կոդով ծրագրակազմի լիցենզիաներ"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"Կարգավորում &gt; Անվտանգություն &gt; Կառավարվող սարքի մասին"</b>" բաժնի մյուս գործառույթները չեն կիրառվում այս սարքում"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Այս սարքում չեն կիրառվում կառավարման գործառույթները, որոնք նշված են ֆինանսավորված սարքի անվտանգության կարգավորումների բաժնում։"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Այս սարքը տրամադրվել է <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ի կողմից"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Կրպակ-հավելվածն ավտոմատ կներբեռնվի և կտեղադրվի"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Այս օգտատիրոջ համար կտեղադրվի կրպակ-հավելվածը"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ծառայությունը կարող է սահմանափակել այս սարքը, եթե որևէ վճարում բաց թողնեք"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ծառայությունը կարող է սահմանափակել սարքը, եթե որևէ վճարում բաց թողնեք։ Մանրամասների համար ծանոթացեք <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Օգտագործման պայմաններին<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>։"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ծառայությունը կարող է սահմանափակել այս սարքը, եթե չկատարեք անհրաժեշտ վճարումները։ Մանրամասների համար ծանոթացեք <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Օգտագործման պայմաններին<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>։"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ծառայությունը կարող է սահմանափակել այս սարքը, եթե սարքի տերը չկատարի վճարումները"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Օգնության համար <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>դիմեք <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ին<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>։"</string>
     <string name="previous" msgid="5241891780917802570">"Նախորդը"</string>
     <string name="next" msgid="8248291863254324326">"Հաջորդը"</string>
     <string name="start" msgid="2842214844667658537">"Սկսել"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Տեղեկություններ"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Կարգավորման մասին"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Գրանցեք ձեր սարքը"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Դուք այժմ կարող եք գրանցել ձեր սարքը <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ի ֆինանսավորման ծրագրում"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Դուք այժմ կարող եք գրանցել ձեր սարքը <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ի ֆինանսավորման ծրագրում"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Դուք այժմ կարող եք գրանցել ձեր սարքը <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ի սուբսիդավորման ծրագրում"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Դուք <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ի սուբսիդավորման ծրագրի անդամ եք"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Սարքի գրանցում"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ծառայությունը կարող է կարգավորումներ փոխել այս սարքում"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Իմանալ ավելին"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Ֆինանսավորված սարքի մասին"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Ձեր վարկատուն կարող է այս սարքում փոխել կարգավորումները և տեղադրել կրպակ-հավելվածը։\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ծառայությունը կարող է սահմանափակել այս սարքը, եթե չկատարեք անհրաժեշտ վճարումները կամ դադարեք օգտագործել <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>-ի SIM քարտը։\n\nԱվելին իմանալու համար դիմեք <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-ին։"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>-ն այս սարքում կարող է փոխել կարգավորումները և տեղադրել կրպակ-հավելվածը։\n\nԵթե որևէ վճարում բաց թողնեք, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>-ն այս սարքի աշխատանքը կարող է սահմանափակել։\n\nԱվելին իմանալու համար դիմեք <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-ին։"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>-ն այս սարքում կարող է փոխել կարգավորումները և տեղադրել կրպակ-հավելվածը։\n\nԲացի այդ՝ եթե որևէ վճարում բաց թողնեք կամ դադարեք օգտագործել <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-ի SIM քարտը, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>-ն այս սարքի աշխատանքը կարող է սահմանափակել։\n\nԱվելին իմանալու համար դիմեք <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>-ին։"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Մինչև չվճարեք ձեր սարքի համար, չեք կարողանա՝"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Վերագործարկել սարքը անվտանգ ռեժիմում"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Փոխել սարքի ամսաթիվը, ժամը և ժամային գոտին"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Օգտագործել մշակողի ընտրանքները"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Խնդրի դեպքում <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ծառայությունը կարող է՝"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Դուք կարող եք ապատեղադրել <xliff:g id="KIOSK_APP">%1$s</xliff:g> հավելվածը"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Օգնության համար՝"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Կապվել <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ի հետ<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Կարգավորում"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Սարքը կվերակայվի 1 օրից}one{Սարքը կվերակայվի # օրից}other{Սարքը կվերակայվի # օրից}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Սարքը շուտով կվերակայվի՝ <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Սարքի բոլոր տվյալները կջնջվեն։ Սարքի գրանցման հետ կապված օգնություն ստանալու համար դիմեք <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ին"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Սարքի գրանցումը հետաձգելու համար թույլատրեք, որ DeviceLock-ը ձեզ ծանուցումներ ուղարկի։"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Ֆինանսավորման կարգավորումը ձախողվեց"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Սեղմեք այստեղ՝ իմանալու, թե ինչպես կարող եք դիմել ֆինանսական մասնագետին։ <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Իմանալ ավելին<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Դուրս գալ"</string>
+    <string name="retry" msgid="7497287909193345356">"Նորից փորձել"</string>
 </resources>
diff --git a/DeviceLockController/res/values-in/strings.xml b/DeviceLockController/res/values-in/strings.xml
index c11d57b..0c53185 100644
--- a/DeviceLockController/res/values-in/strings.xml
+++ b/DeviceLockController/res/values-in/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Permintaan kunci atau buka kunci apa pun dari <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Apakah aplikasi <xliff:g id="CREDITOR_APP">%1$s</xliff:g> tidak tersedia"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Lisensi open source"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Kemampuan pengelolaan lain di "<b>"Setelan &gt; Keamanan &gt; Info perangkat terkelola"</b>" tidak berlaku untuk perangkat ini"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Kemampuan pengelolaan di bagian perangkat yang dibiayai di setelan Keamanan tidak berlaku untuk perangkat ini."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Perangkat ini disediakan oleh <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Aplikasi Kios akan otomatis didownload dan diinstal"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Aplikasi Kios akan diinstal untuk pengguna ini"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> dapat membatasi perangkat ini jika Anda melalaikan pembayaran"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> dapat membatasi perangkat jika Anda melewatkan pembayaran. Untuk mengetahui detailnya, lihat <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Persyaratan &amp; Ketentuan<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> dapat membatasi perangkat ini jika Anda tidak melakukan pembayaran yang diperlukan. Untuk mengetahui detailnya, lihat <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Persyaratan &amp; Ketentuan<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> dapat membatasi perangkat ini jika pemilik tidak melakukan pembayaran"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Untuk mendapatkan bantuan, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>hubungi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Sebelumnya"</string>
     <string name="next" msgid="8248291863254324326">"Berikutnya"</string>
     <string name="start" msgid="2842214844667658537">"Mulai"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Info"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Info penyediaan"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Daftarkan perangkat Anda"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Anda kini dapat mendaftarkan perangkat Anda ke program keuangan <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Anda kini dapat mendaftarkan perangkat Anda ke program pembiayaan <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Anda kini dapat mendaftarkan perangkat Anda ke program subsidi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Anda bergabung dalam program subsidi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Pendaftaran perangkat"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> dapat mengubah setelan di perangkat ini"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Pelajari lebih lanjut"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Info perangkat yang dibiayai"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Penyedia kredit Anda dapat mengubah setelan dan menginstal aplikasi Kios pada perangkat.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> dapat membatasi perangkat ini jika Anda tidak melakukan pembayaran yang diperlukan atau berhenti menggunakan SIM <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nUntuk mempelajari lebih lanjut, hubungi <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> dapat mengubah setelan dan menginstal aplikasi Kios pada perangkat.\n\nJika Anda melewatkan pembayaran, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> dapat membatasi perangkat Anda.\n\nUntuk mempelajari lebih lanjut, hubungi <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> dapat mengubah setelan dan menginstal aplikasi Kios pada perangkat.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> juga dapat membatasi perangkat ini jika Anda melewatkan pembayaran atau berhenti menggunakan SIM <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nUntuk mempelajari lebih lanjut, hubungi <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Sebelum Anda melunasi perangkat, Anda tidak dapat:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Memulai ulang perangkat ke mode aman"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Mengubah tanggal, waktu, dan zona waktu"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Menggunakan opsi developer"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Jika terjadi masalah pada perangkat Anda, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> dapat:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Anda dapat menguninstal aplikasi <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Untuk mendapatkan bantuan:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Hubungi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Penyediaan"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Perangkat akan direset dalam 1 hari}other{Perangkat akan direset dalam # hari}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Perangkat akan direset dalam <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Semua data perangkat akan dihapus. Untuk mendapatkan bantuan dalam proses pendaftaran perangkat Anda, hubungi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Berikan izin notifikasi dari DeviceLock untuk melanjutkan proses penundaan pendaftaran perangkat."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Penyediaan keuangan gagal"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Klik di sini untuk mengetahui cara menghubungi penyedia dana Anda. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Pelajari lebih lanjut<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Keluar"</string>
+    <string name="retry" msgid="7497287909193345356">"Coba lagi"</string>
 </resources>
diff --git a/DeviceLockController/res/values-is/strings.xml b/DeviceLockController/res/values-is/strings.xml
index 5814eb5..fab94f7 100644
--- a/DeviceLockController/res/values-is/strings.xml
+++ b/DeviceLockController/res/values-is/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Allar beiðnir frá <xliff:g id="CREDITOR_APP">%1$s</xliff:g> um að læsa eða taka úr lás"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Ef <xliff:g id="CREDITOR_APP">%1$s</xliff:g>-forritið er ekki í boði"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Leyfi opins kóða"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Aðrir stjórnunareiginleikar í "<b>"Stillingar &gt; Öryggi &gt; Upplýsingar um stýrt tæki"</b>" gilda ekki um þetta tæki"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Stjórnunareiginleikar í öryggisstillingum varðandi fjármögnunarhluta tækisins eiga ekki við um þetta tæki."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Þetta tæki er frá <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Sjálfsalaforritið verður sótt og sett upp sjálfkrafa"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Sjálfsalaforritið verður sett upp fyrir þennan notanda"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> getur sett takmarkanir á þetta tæki ef þú missir úr greiðslu"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> getur sett takmarkanir á tækið ef þú missir úr greiðslu. Frekari upplýsingar má finna í <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>skilmálunum<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> getur sett takmarkanir á þetta tæki ef þú greiðir ekki áskildar greiðslur. Frekari upplýsingar má finna í <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>skilmálunum<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> getur sett takmarkanir á þetta tæki ef eigandinn greiðir ekki"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Hafðu samband við <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g> til að fá aðstoð."</string>
     <string name="previous" msgid="5241891780917802570">"Til baka"</string>
     <string name="next" msgid="8248291863254324326">"Áfram"</string>
     <string name="start" msgid="2842214844667658537">"Byrja"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Upplýsingar"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Úthlutunarupplýsingar"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Skráðu tækið þitt"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Nú geturðu skráð tækið þitt í fjármögnunarkerfi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Nú geturðu skráð tækið þitt í fjármögnunarkerfi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Nú geturðu skráð tækið þitt í niðurgreiðslukerfi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Þú ert í niðurgreiðslukerfi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Skráning tækis"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> getur breytt stillingum í þessu tæki"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Nánar"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Upplýsingar um fjármögnuð tæki"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Lánveitandi þinn getur breytt stillingum og sett upp sjálfsalaforritið í þessu tæki.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kann að setja takmarkanir á þetta tæki ef þú greiðir ekki áskildar greiðslur eða hættir að nota SIM frá <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nTil að fá frekari upplýsingar skaltu hafa samband við <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> getur breytt stillingum og sett upp sjálfsalaforritið í þessu tæki.\n\nEf þú missir úr greiðslu getur <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> sett takmarkanir á tækið þitt.\n\nTil að fá frekari upplýsingar skaltu hafa samband við <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> getur breytt stillingum og sett upp sjálfsalaforritið í þessu tæki.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kann einnig að setja takmarkanir á þetta tæki ef þú missir úr greiðslu eða hættir að nota SIM frá <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nTil að fá frekari upplýsingar skaltu hafa samband við <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Þar til þú greiðir fyrir tækið geturðu ekki:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Endurræstu tækið þitt í öruggri stillingu"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Breytt dagsetningu, tíma og tímabeltum"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Notað forritunarkosti"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Ef eitthvað fer úrskeiðis með tækið getur <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Þú getur fjarlægt <xliff:g id="KIOSK_APP">%1$s</xliff:g>-forritið"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Til að fá aðstoð:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Hafa samband við <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Úthluta"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Tæki verður endurstillt eftir 1 dag}one{Tæki verður endurstillt eftir # dag}other{Tæki verður endurstillt eftir # daga}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Tækið verður endurstillt eftir <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Öllum gögnum tækis verður eytt. Hafðu samband við <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> til að fá aðstoð við að skrá tækið"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Leyfðu tilkynningu frá DeviceLock til að halda áfram að fresta skráningu tækisins."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Fjármögnunarúthlutun mistókst"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Smelltu hér til að sjá leiðir til að ná sambandi við fjármögnunarþjónustuna. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Nánar<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Hætta"</string>
+    <string name="retry" msgid="7497287909193345356">"Reyna aftur"</string>
 </resources>
diff --git a/DeviceLockController/res/values-it/strings.xml b/DeviceLockController/res/values-it/strings.xml
index 0599194..d54164d 100644
--- a/DeviceLockController/res/values-it/strings.xml
+++ b/DeviceLockController/res/values-it/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Qualsiasi richiesta di blocco o sblocco da <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Se l\'app <xliff:g id="CREDITOR_APP">%1$s</xliff:g> non è disponibile"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licenze open source"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Le altre funzionalità di gestione in "<b>"Impostazioni &gt; Sicurezza &gt; Informazioni sul dispositivo gestito"</b>" non si applicano a questo dispositivo"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Le funzionalità di gestione nella sezione relativa al dispositivo finanziato delle impostazioni Sicurezza non si applicano a questo dispositivo."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Questo dispositivo è fornito da <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"L\'app kiosk verrà scaricata e installata automaticamente"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"L\'app kiosk verrà installata per questo utente"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> può limitare questo dispositivo se salti un pagamento"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> può limitare il dispositivo se salti un pagamento. Per informazioni dettagliate, visualizza i <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termini e condizioni<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> può limitare questo dispositivo se non effettui i pagamenti necessari. Per informazioni dettagliate, visualizza i <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termini e condizioni<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> può limitare questo dispositivo se il proprietario non effettua i pagamenti"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Per assistenza, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>contatta <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Precedente"</string>
     <string name="next" msgid="8248291863254324326">"Avanti"</string>
     <string name="start" msgid="2842214844667658537">"Inizia"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informazioni"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Info provisioning"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Registra il tuo dispositivo"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Ora puoi registrare il tuo dispositivo al programma di finanziamento di <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Ora puoi registrare il tuo dispositivo al programma di finanziamento di <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Ora puoi registrare il tuo dispositivo al programma di sovvenzione di <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Sei nel programma di sovvenzione di <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Registrazione del dispositivo"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> può cambiare le impostazioni su questo dispositivo"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Scopri di più"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informazioni sul dispositivo finanziato"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Il tuo fornitore di credito può modificare le impostazioni e installare l\'app kiosk sul dispositivo.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> potrebbe limitare questo dispositivo se non effettui i pagamenti necessari o non usi più la SIM di <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPer scoprire di più, contatta <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> può modificare le impostazioni e installare l\'app kiosk sul dispositivo.\n\nSe salti un pagamento, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> può limitare il tuo dispositivo.\n\nPer scoprire di più, contatta <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> può modificare le impostazioni e installare l\'app kiosk sul dispositivo.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> potrebbe anche limitare il dispositivo se salti un pagamento o se smetti di usare la SIM di <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPer scoprire di più, contatta <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Finché non avrai pagato il dispositivo non potrai:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Riavviare il tuo dispositivo in modalità provvisoria"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Cambiare data, ora e fusi orari"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Usare Opzioni sviluppatore"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"In caso di problemi col dispositivo <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> può:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Puoi disinstallare l\'app <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Per richiedere assistenza:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contatta <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provisioning"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Il dispositivo sarà resettato tra 1 g}other{Il dispositivo sarà resettato tra # g}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Il dispositivo verrà resettato tra <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Verranno eliminati tutti i dati del dispositivo. Per farti aiutare con la registrazione del dispositivo, contatta <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Consenti la notifica di DeviceLock per continuare a posticipare la registrazione del dispositivo."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Il finanziamento del provisioning non è andato a buon fine"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Fai clic qui per trovare le modalità di contatto di chi ti finanzia. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Scopri di più<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Esci"</string>
+    <string name="retry" msgid="7497287909193345356">"Riprova"</string>
 </resources>
diff --git a/DeviceLockController/res/values-iw/strings.xml b/DeviceLockController/res/values-iw/strings.xml
index 629a899..376e64b 100644
--- a/DeviceLockController/res/values-iw/strings.xml
+++ b/DeviceLockController/res/values-iw/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"כל הבקשות לנעילה או לביטול נעילה מהאפליקציה <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"אם האפליקציה <xliff:g id="CREDITOR_APP">%1$s</xliff:g> לא זמינה"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"רישיונות קוד פתוח"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"שאר יכולות הניהול שמופיעות ב"<b>"\'הגדרות\' &gt; \'אבטחה\' &gt; \'פרטי המכשיר המנוהל\'"</b>" לא חלות על המכשיר הזה"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"יכולות הניהול שמופיעות בקטע \'פרטי המכשיר הממומן\' בהגדרות האבטחה לא חלות על המכשיר הזה."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"המכשיר הזה סופק על ידי <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"יתבצעו הורדה והתקנה אוטומטיות של אפליקציית \"קיוסק\""</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"אפליקציית \"קיוסק\" תותקן עבור המשתמש הזה"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"יש ל-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> אפשרות להגביל את המכשיר הזה אם לא שילמת בזמן"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"לספק <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> יש אפשרות להגביל את המכשיר אם לא שילמת בזמן. לקבלת פרטים, אפשר לעיין <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>בתנאים ובהגבלות<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"יש ל-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> אפשרות להגביל את המכשיר הזה אם לא שילמת כנדרש. לפרטים, אפשר לעיין <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>בתנאים ובהגבלות<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"יש ל-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> אפשרות להגביל את המכשיר הזה אם הבעלים לא משלמים"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"לקבלת עזרה, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>עליך לפנות אל <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"הקודם"</string>
     <string name="next" msgid="8248291863254324326">"הבא"</string>
     <string name="start" msgid="2842214844667658537">"התחלה"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"מידע"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"מידע על ההקצאה"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"צירוף המכשיר לתוכנית"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"עכשיו אפשר לצרף את המכשיר לתוכנית המימון של <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"עכשיו אפשר לצרף את המכשיר לתוכנית המימון של <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"עכשיו אפשר לצרף את המכשיר לתוכנית הסובסידיה של <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"הצטרפת לתוכנית הסובסידיה של <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"צירוף מכשיר לתוכנית"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"יש ל-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> אפשרות לשנות את ההגדרות במכשיר הזה"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"מידע נוסף"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"פרטי המכשיר הממומן"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"החברה שמוכרת מכשירים באשראי יכולה לשנות הגדרות ולהתקין את אפליקציית \"קיוסק\" במכשיר.\n\nל-<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> יש אפשרות להגביל את המכשיר הזה אם לא מתבצעים התשלומים הדרושים או אם לא משתמשים יותר בכרטיס ה-SIM של <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nלמידע נוסף, אפשר לפנות אל <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"הספק <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> יכול לשנות הגדרות ולהתקין את אפליקציית \"קיוסק\" במכשיר.\n\nאם פספסת תשלום, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> יכול להגביל את המכשיר.\n\nלמידע נוסף אפשר לפנות אל <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"הספק <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> יכול לשנות הגדרות ולהתקין את אפליקציית \"קיוסק\" במכשיר.\n\nל-<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> יש גם אפשרות להגביל את המכשיר אם פספסת תשלום או הפסקת להשתמש בכרטיס ה-SIM של<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nלמידע נוסף, אפשר לפנות אל <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"לפני שמשלמים עבור המכשיר, לא ניתן:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"להפעיל את המכשיר מחדש במצב בטוח"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"שינוי התאריך, השעה ואזורי הזמן"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"להשתמש באפשרויות למפתחים"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"אם משהו משתבש במכשיר, ל-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> יש אפשרות:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"אפשר להסיר את אפליקציית <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"לקבלת עזרה:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>יצירת קשר עם <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"הקצאה"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{המכשיר יתאפס בעוד יום אחד}one{המכשיר יתאפס בעוד # ימים}two{המכשיר יתאפס בעוד יומיים (#)}other{המכשיר יתאפס בעוד # ימים}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"המכשיר יתאפס בעוד <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"כל הנתונים במכשיר יימחקו. כדי לקבל עזרה בצירוף המכשיר לתוכנית, יש ליצור קשר עם <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"יש לאפשר קבלת התראות מ-DeviceLock כדי להמשיך לדחות את הצירוף של המכשיר לתוכנית."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"הקצאת המימון נכשלה"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"אפשר ללחוץ כאן לקבלת דרכים ליצירת קשר עם נותני המימון. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>מידע נוסף<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"יציאה"</string>
+    <string name="retry" msgid="7497287909193345356">"ניסיון נוסף"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ja/strings.xml b/DeviceLockController/res/values-ja/strings.xml
index c15ce4e..fe38d2c 100644
--- a/DeviceLockController/res/values-ja/strings.xml
+++ b/DeviceLockController/res/values-ja/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> からのロック / ロック解除のリクエスト"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> アプリが利用できない場合"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"オープンソース ライセンス"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"[設定] &gt; [セキュリティ] &gt; [管理対象デバイスの情報]"</b>" のその他の管理機能は、このデバイスに適用されません"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"セキュリティ設定の [ローンで購入したデバイスの情報] に記載されている管理機能は、このデバイスには適用されません。"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"このデバイスは <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> から提供されています"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"キオスクアプリは自動的にダウンロード、インストールされます"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"このユーザーに対してキオスクアプリがインストールされます"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"支払いが行われなかった場合、<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> はこのデバイスを制限する可能性があります"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"支払いが行われなかった場合、<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> はこのデバイスを制限する可能性があります。詳しくは、<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>利用規約<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>をご覧ください。"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"必要な支払いを行わない場合、<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> はこのデバイスを制限する可能性があります。詳しくは、<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>利用規約<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>をご覧ください。"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"所有者が支払いを行わない場合、<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> はこのデバイスを制限する可能性があります"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"サポートが必要な場合は、<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> にお問い合わせ<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>ください。"</string>
     <string name="previous" msgid="5241891780917802570">"前へ"</string>
     <string name="next" msgid="8248291863254324326">"次へ"</string>
     <string name="start" msgid="2842214844667658537">"開始する"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"情報"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"プロビジョニング情報"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"デバイスを登録する"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> の融資プログラムにデバイスを登録できるようになりました"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> の融資プログラムにデバイスを登録できるようになりました"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> の補助金プログラムにデバイスを登録できるようになりました"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> の補助金プログラムに参加しています"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"デバイスの登録"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> はこのデバイスの設定を変更できます"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"詳細"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ローンで購入したデバイスの情報"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"クレジット プロバイダは、デバイスの設定を変更したり、デバイスにキオスクアプリをインストールしたりできます。\n\nユーザーが必要な支払いを行わない場合や、<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> の SIM の利用を停止した場合、<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> はこのデバイスを制限する可能性があります。\n\n詳しくは、<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> にお問い合わせください。"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> は、デバイスの設定を変更したり、デバイスにキオスクアプリをインストールしたりできます。\n\n支払いが行われなかった場合、<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> はデバイスを制限する可能性があります。\n\n詳細については、<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> にお問い合わせください。"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> は、デバイスの設定を変更したり、デバイスにキオスクアプリをインストールしたりできます。\n\n支払いが行われなかった場合や <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> の SIM が使用されなくなった場合、<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> はこのデバイスを制限する可能性があります。\n\n詳細については、<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> にお問い合わせください。"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"デバイスのお支払いが完了するまで、以下の操作は行えません。"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"デバイスをセーフモードで再起動する"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"日付、時刻、タイムゾーンを変更する"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"開発者向けオプションの使用"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"デバイスで問題が発生した場合、<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> は次のことができます。"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> アプリをアンインストールできます"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"ヘルプ:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> に問い合わせる<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"プロビジョニング"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{デバイスは 1 日以内にリセットされます}other{デバイスは # 日以内にリセットされます}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"デバイスは <xliff:g id="TIMER">%s</xliff:g> にリセットされます"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"デバイスのデータはすべて削除されます。デバイスの登録についてサポートが必要な場合は、<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> にお問い合わせください"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"デバイスの登録を引き続き延期するには、DeviceLock からの通知を許可してください。"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"融資のプロビジョニングに失敗しました"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"融資業者への連絡方法については、こちらをクリックしてください。<xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>詳細<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"終了"</string>
+    <string name="retry" msgid="7497287909193345356">"再試行"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ka/strings.xml b/DeviceLockController/res/values-ka/strings.xml
index 9688b69..4900d88 100644
--- a/DeviceLockController/res/values-ka/strings.xml
+++ b/DeviceLockController/res/values-ka/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"დაბლოკვის ან განბლოკვის ყველა მოთხოვნა <xliff:g id="CREDITOR_APP">%1$s</xliff:g>-ისგან"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"თუ <xliff:g id="CREDITOR_APP">%1$s</xliff:g> აპი არ არის ხელმისაწვდომი"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ღია კოდის ლიცენზიები"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"მართვის სხვა შესაძლებლობები განყოფილებიდან "<b>"პარამეტრები &gt; უსაფრთხოება &gt; ინფორმაცია მართული მოწყობილობის შესახებ"</b>" ამ მოწყობილობაზე არ ვრცელდება"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"უსაფრთხოების პარამეტრების დაფინანსებული მოწყობილობის განყოფილებაში მოცემული მართვის შესაძლებლობები ამ მოწყობილობაზე არ ვრცელდება."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"ამ მოწყობილობის მომწოდებელია <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk აპი ავტომატურად ჩამოიტვირთება და დაინსტალირდება"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kiosk აპი დაინსტალირდება ამ მომხმარებლისთვის"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ს შეუძლია შეზღუდოს ეს მოწყობილობა, თუ გადახდას გამოტოვებთ"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"თუ გადახდა გამოგრჩებათ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ს შეუძლია, შეზღუდოს მოწყობილობა. დეტალებისთვის იხილეთ <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>წესები და პირობები<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ს შეუძლია შეზღუდოს ეს მოწყობილობა, თუ არ განახორციელებთ საჭირო გადახდებს. დეტალებისთვის იხილეთ <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>მომსახურების პირობები<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ს შეუძლია შეზღუდოს ეს მოწყობილობა, თუ მფლობელი არ გადაიხდის"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"დახმარების მისაღებად <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>დაუკავშირდით <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ს<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"წინა"</string>
     <string name="next" msgid="8248291863254324326">"შემდეგ"</string>
     <string name="start" msgid="2842214844667658537">"დაწყება"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"ინფორმაცია"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"უზრუნველყოფის ინფო."</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"თქვენი მოწყობილობის რეგისტრაცია"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"ახლა შეგიძლიათ, დაარეგისტრიროთ თქვენი მოწყობილობა <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ის დაფინანსების პროგრამაში"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"ახლა შეგიძლიათ, დაარეგისტრიროთ თქვენი მოწყობილობა <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ის ფინანსურ პროგრამაში"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"ახლა თქვენ შეგიძლიათ დაარეგისტრიროთ თქვენი მოწყობილობა <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ის სუბსიდიის პროგრამაში"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"თქვენ ხართ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ის სუბსიდიის პროგრამაში"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"მოწყობილობის რეგისტრაცია"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ს შეუძლია შეცვალოს პარამეტრები ამ მოწყობილობაზე"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"შეიტყვეთ მეტი"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"დაფინანსებული მოწყობილობის ინფორმაცია"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"თქვენს კრედიტის პროვაიდერს შეუძლია, შეცვალოს პარამეტრები და დააინსტალიროს Kiosk აპი მოწყობილობაზე.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>-მა შეიძლება შეზღუდოს ეს მოწყობილობა, თუ არ განახორციელებთ აუცილებელ გადახდებს ან შეწყვეტთ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>-ის SIM-ის გამოყენებას.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-ს."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>-ს შეუძლია, შეცვალოს პარამეტრები და დააინსტალიროს kiosk აპი მოწყობილობაზე.\n\nთუ გადახდა გამოგრჩებათ, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> თქვენი მოწყობილობის შეზღუდვას შეძლებს.\n\nმეტის გასაგებად <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-ს დაუკავშირდით."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>-ს შეუძლია, შეცვალოს პარამეტრები და დააინსტალიროს kiosk აპი მოწყობილობაზე.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>-ს მოწყობილობის შეზღუდვაც შეუძლია, თუ გადახდა გამოგრჩებათ ან თუ შეწყვეტთ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-ის SIM-ის გამოყენებას.\n\nმეტის გასაგებად <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>-ს დაუკავშირდით."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"სანამ არ გადაიხდით მოწყობილობისას, თქვენ არ შეგიძლიათ:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"თქვენი მოწყობილობის გადატვირთვა უსაფრთხო რეჟიმში"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"თარიღის, დროისა და სასაათო სარტყლების შეცვლა"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"დეველოპერთა პარამეტრების გამოყენება"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"მოწყობ. პრობ. შემთხვევაში <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ს შეუძლია:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"შეგიძლიათ <xliff:g id="KIOSK_APP">%1$s</xliff:g> აპის დეინსტალაცია"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"დახმარების მისაღებად:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>დაუკავშირდით <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ს<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"უზრუნველყოფა"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{მოწყობილობა გადაყენდება 1 დღეში}other{მოწყობილობა გადაყენდება # დღეში}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"მოწყობილობა გადაყენდება <xliff:g id="TIMER">%s</xliff:g>-ში"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"მოწყობილობის ყველა მონაცემი წაიშლება. თქვენი მოწყობილობის რეგისტრაციასთან დაკავშირებით დახმარებისთვის დაუკავშირდით <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-ს"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"გთხოვთ, დაუშვათ შეტყობინება DeviceLock-იდან მოწყობილობის რეგისტრაციის გადადების გასაგრძელებლად."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"დაფინანსების უზრუნველყოფა ვერ მოხერხდა"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"დააწკაპუნეთ აქ თქვენს ფინანსისტთან დაკავშირების გზებისთვის. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>შეიტყვეთ მეტი<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"გასვლა"</string>
+    <string name="retry" msgid="7497287909193345356">"ხელახლა ცდა"</string>
 </resources>
diff --git a/DeviceLockController/res/values-kk/strings.xml b/DeviceLockController/res/values-kk/strings.xml
index 42ac264..3f33217 100644
--- a/DeviceLockController/res/values-kk/strings.xml
+++ b/DeviceLockController/res/values-kk/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> қолданбасының құлыптау және құлыпты ашу сұраулары"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> қолданбасы қолжетімді болмаса"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Ашық кодты бағдарлама лицензиялары"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Осы құрылғыға "<b>"Параметрлер &gt; Қауіпсіздік &gt; Басқарылатын құрылғы туралы ақпарат"</b>" бөлімінде көрсетілген басқа басқару мүмкіндіктері қолданылмайды."</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Осы құрылғыға қауіпсіздік параметрлеріндегі \"Қаржыландырылған құрылғы\" бөлімінде көрсетілген басқару мүмкіндіктері қолданылмайды."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Осы құрылғыны <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ұсынады."</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Киоск қолданбасы жүктеп алынып, автоматты түрде орнатылады."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Киоск қолданбасы осы пайдаланушы үшін орнатылады."</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Төлемді өткізіп алсаңыз, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> осы құрылғының пайдаланылуын шектей алады."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Төлемді өткізіп алсаңыз, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> құрылғының пайдаланылуын шектей алады. Толық ақпарат алу үшін <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Шарттар мен талаптарды<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> қараңыз."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Қажетті төлемдерді жасамасаңыз, кредитор (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>) осы құрылғының пайдаланылуын шектей алады. Толық ақпарат алу үшін <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Шарттар мен талаптарды<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> қараңыз."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Иесі төлем жасамаса, кредитор (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>) осы құрылғының пайдаланылуын шектей алады."</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Көмек керек болса, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> провайдеріне хабарласыңыз<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Алдыңғы"</string>
     <string name="next" msgid="8248291863254324326">"Келесі"</string>
     <string name="start" msgid="2842214844667658537">"Бастау"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Ақпарат"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Ұсыну ақпараты"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Құрылғыңызды тіркеңіз"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Енді құрылғыңызды кредитордың (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>) қаржыландыру бағдарламасына тіркей аласыз."</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Енді құрылғыңызды кредитордың (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>) субсидиялау бағдарламасына тіркей аласыз."</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Енді құрылғыңызды кредитордың (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>) субсидиялау бағдарламасына тіркей аласыз."</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> субсидиялау бағдарламасына қосылдыңыз"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Құрылғыны тіркеу"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"Кредитор (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>) осы құрылғыдағы параметрлерді өзгерте алады."</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Толық ақпарат"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Қаржыландырылатын құрылғы туралы ақпарат"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Кредиторыңыз параметрлерді өзгертіп, құрылғыға киоск қолданбасын орната алады.\n\nҚажетті төлемдерді жасамасаңыз не байланыс провайдерінің (<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>) SIM картасын қолдануды тоқтатсаңыз, <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> осы құрылғының пайдаланылуын шектеуі мүмкін.\n\nТолық ақпарат алу үшін <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> компаниясына хабарласыңыз."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> параметрлерді өзгертіп, құрылғыға киоск қолданбасын орната алады.\n\nТөлем уақытын өткізіп алсаңыз, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> құрылғыны пайдалану мүмкіндігін шектеуі мүмкін.\n\nТолық ақпарат алу үшін <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> компаниясына хабарласыңыз."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> параметрлерді өзгертіп, құрылғыға киоск қолданбасын орната алады.\n\nТөлем уақытын өткізіп алсаңыз немесе <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM картасын пайдаланбай қойсаңыз, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> құрылғыны пайдалану мүмкіндігін шектеуі мүмкін.\n\nТолық ақпарат алу үшін <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> компаниясына хабарласыңыз."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Құрылғы үшін ақы төлемесеңіз, мыналарды орындай алмайсыз:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Құрылғыны өшіріп қосып, қауіпсіз режимге өту"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Күнді, уақытты және уақыт белдеулерін өзгерту"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Әзірлеуші опцияларын пайдалану"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Ақау шықса, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> төмендегілерді орындай алады:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> қолданбасын жоюыңызға болады."</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Анықтама алу үшін:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> провайдеріне хабарласу<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Ұсыну"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Құрылғы 1 күннен кейін бастапқы күйге қайтарылады}other{Құрылғы # күннен кейін бастапқы күйге қайтарылады}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Құрылғы <xliff:g id="TIMER">%s</xliff:g> кейін бастапқы күйге қайтарылады"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Құрылғыдағы барлық дерек жойылады. Құрылғыны тіркеу бойынша көмек алу үшін кредиторға (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>) хабарласыңыз."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Құрылғыны тіркеуді кейінге қалдыра беру үшін DeviceLock-тың хабарландыру жіберуіне рұқсат етіңіз."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Қаржымен қамтамасыз ету мүмкін болмады"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Қаржыгермен қалай хабарласуға болатынын білу үшін осы жерді басыңыз. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Толық ақпарат<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Шығу"</string>
+    <string name="retry" msgid="7497287909193345356">"Қайталау"</string>
 </resources>
diff --git a/DeviceLockController/res/values-km/strings.xml b/DeviceLockController/res/values-km/strings.xml
index d6b4d07..c34c1d2 100644
--- a/DeviceLockController/res/values-km/strings.xml
+++ b/DeviceLockController/res/values-km/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"សំណើសុំចាក់សោ ឬដោះសោពី <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"ប្រសិនបើមិនអាចប្រើកម្មវិធី <xliff:g id="CREDITOR_APP">%1$s</xliff:g> បានទេ"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"អាជ្ញាបណ្ណ​កូដ​ចំហ"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"សមត្ថភាព​គ្រប់គ្រង​ផ្សេងទៀត​នៅក្នុង"<b>"ការកំណត់ &gt; សុវត្ថិភាព &gt; ព័ត៌មាន​អំពី​ឧបករណ៍​ដែលស្ថិតក្រោម​ការគ្រប់គ្រង"</b>"មិនអនុវត្ត​ចំពោះ​ឧបករណ៍នេះទេ"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"សមត្ថភាព​គ្រប់គ្រង​នៅក្នុងផ្នែក​ការកំណត់​សុវត្ថិភាព​របស់ឧបករណ៍​ដែលទទួលបាន​ហិរញ្ញប្បទាន​មិនអនុវត្ត​ចំពោះ​ឧបករណ៍នេះទេ។"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"ឧបករណ៍នេះត្រូវបានផ្ដល់ដោយ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"កម្មវិធីបញ្ជរនឹង​ត្រូវបានទាញយក និងដំឡើងដោយស្វ័យប្រវត្តិ"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"កម្មវិធីបញ្ជរនឹងត្រូវបានដំឡើងសម្រាប់អ្នកប្រើប្រាស់នេះ"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> អាចដាក់កំហិត​ឧបករណ៍នេះ ប្រសិនបើអ្នកខកខានការបង់ប្រាក់"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> អាចដាក់កំហិត​ឧបករណ៍នេះ ប្រសិនបើអ្នកខកខានការបង់ប្រាក់ណាមួយ។ សម្រាប់ព័ត៌មានលម្អិត សូមមើល<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>លក្ខខណ្ឌ<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>។"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> អាចដាក់កំហិត​ឧបករណ៍នេះ ប្រសិនបើអ្នកមិនធ្វើការបង់ប្រាក់​ដែលចាំបាច់។ សម្រាប់ព័ត៌មានលម្អិត សូមមើល<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>លក្ខខណ្ឌ<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>។"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> អាចដាក់កំហិត​ឧបករណ៍នេះ ប្រសិនបើម្ចាស់​មិនធ្វើការបង់ប្រាក់"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"ដើម្បីទទួលបានជំនួយ <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>សូមទាក់ទង <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>។"</string>
     <string name="previous" msgid="5241891780917802570">"មុន"</string>
     <string name="next" msgid="8248291863254324326">"បន្ទាប់"</string>
     <string name="start" msgid="2842214844667658537">"ចាប់ផ្ដើម"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"ព័ត៌មាន"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"ព័ត៌មានអំពីការផ្ដល់"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"ចុះឈ្មោះ​ឧបករណ៍​របស់អ្នក"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"ឥឡូវនេះ អ្នកអាចចុះឈ្មោះឧបករណ៍របស់អ្នកនៅក្នុងកម្មវិធីហិរញ្ញវត្ថុរបស់ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> បានហើយ"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"ឥឡូវនេះ អ្នកអាចចុះឈ្មោះឧបករណ៍របស់អ្នកនៅក្នុងកម្មវិធីហិរញ្ញប្បទានរបស់ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> បានហើយ"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"ឥឡូវនេះ អ្នកអាចចុះឈ្មោះឧបករណ៍របស់អ្នកនៅក្នុងកម្មវិធីឧបត្ថម្ភធនរបស់ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> បានហើយ"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"អ្នកកំពុងប្រើកម្មវិធីឧបត្ថម្ភធនរបស់ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ការចុះឈ្មោះឧបករណ៍"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> អាចប្ដូរការកំណត់នៅលើឧបករណ៍នេះ"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"ស្វែងយល់បន្ថែម"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ព័ត៌មានឧបករណ៍ដែលទទួលបានហិរញ្ញប្បទាន"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"ក្រុមហ៊ុនផ្ដល់សេវាឥណទានរបស់អ្នក​អាចផ្លាស់ប្ដូរការកំណត់ និងដំឡើងកម្មវិធីបញ្ជរ​នៅលើឧបករណ៍។\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> អាចដាក់កំហិត​ឧបករណ៍នេះ ប្រសិនបើអ្នក​មិនធ្វើការបង់ប្រាក់ដែលចាំបាច់ ឬឈប់ប្រើស៊ីមរបស់ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>។\n\nដើម្បីស្វែងយល់បន្ថែម សូមទាក់ទងទៅ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>។"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> អាចផ្លាស់ប្ដូរការកំណត់ និងដំឡើងកម្មវិធីបញ្ជរនៅលើឧបករណ៍។\n\nប្រសិនបើអ្នកខកខានមិនបានធ្វើការបង់ប្រាក់ណាមួយ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> អាចដាក់កំហិតលើឧបករណ៍របស់អ្នក។\n\nដើម្បីស្វែងយល់បន្ថែម សូមទាក់ទងទៅ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>។"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> អាចផ្លាស់ប្ដូរការកំណត់ និងដំឡើងកម្មវិធីបញ្ជរ​នៅលើឧបករណ៍។\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ក៏អាចដាក់កំហិតលើឧបករណ៍នេះផងដែរ ប្រសិនបើអ្នកខកខានមិនបានធ្វើការបង់ប្រាក់ណាមួយ ឬឈប់ប្រើស៊ីមរបស់ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>។\n\nដើម្បីស្វែងយល់បន្ថែម សូមទាក់ទងទៅ <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>។"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"ទាល់តែអ្នកបានបង់ប្រាក់​សម្រាប់ឧបករណ៍របស់អ្នក អ្នកមិនអាច៖"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"ចាប់ផ្ដើមឧបករណ៍របស់អ្នកឡើងវិញទៅក្នុងមុខងារសុវត្ថិភាព"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"ប្ដូរកាលបរិច្ឆេទ ម៉ោង និងល្វែងម៉ោង"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ប្រើ​ជម្រើសសម្រាប់អ្នកអភិវឌ្ឍន៍"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"ប្រសិនបើអ្វីមួយខុសប្រក្រតីពាក់ព័ន្ធនឹងឧបករណ៍របស់អ្នក <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> អាច៖"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"អ្នកអាចលុបកម្មវិធី <xliff:g id="KIOSK_APP">%1$s</xliff:g> បាន"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"ដើម្បីទទួលបានជំនួយ៖"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ទាក់ទងទៅ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"ការផ្ដល់"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{ឧបករណ៍នឹងកំណត់ឡើងវិញ​ក្នុងរយៈពេល 1 ថ្ងៃ}other{ឧបករណ៍នឹងកំណត់ឡើងវិញ​ក្នុងរយៈពេល # ថ្ងៃ}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"ឧបករណ៍នឹងកំណត់ឡើងវិញ​ក្នុងរយៈពេល <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ទិន្នន័យឧបករណ៍​ទាំងអស់នឹងត្រូវបានលុប។ សម្រាប់ជំនួយក្នុង​ការចុះឈ្មោះឧបករណ៍របស់អ្នក សូមទាក់ទងទៅ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"សូមអនុញ្ញាតការជូនដំណឹងពី DeviceLock ដើម្បីបន្តពន្យារពេលចុះឈ្មោះឧបករណ៍។"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ការផ្ដល់ហិរញ្ញវត្ថុមិនបានសម្រេច"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"សូមចុចត្រង់នេះ ដើម្បីរកមើលវិធី​ក្នុងការទាក់ទងទៅ​ហិរញ្ញធិការីរបស់អ្នក។ <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>ស្វែងយល់បន្ថែម<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"ចាកចេញ"</string>
+    <string name="retry" msgid="7497287909193345356">"ព្យាយាមម្ដងទៀត"</string>
 </resources>
diff --git a/DeviceLockController/res/values-kn/strings.xml b/DeviceLockController/res/values-kn/strings.xml
index 8aa9648..b518824 100644
--- a/DeviceLockController/res/values-kn/strings.xml
+++ b/DeviceLockController/res/values-kn/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ನಿಂದ ಎಲ್ಲಾ ಲಾಕ್ ಅಥವಾ ಅನ್‌ಲಾಕ್ ವಿನಂತಿಗಳು"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ಆ್ಯಪ್ ಲಭ್ಯವಿಲ್ಲದಿದ್ದರೆ"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ಓಪನ್ ಸೋರ್ಸ್ ಲೈಸೆನ್ಸ್‌ಗಳು"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"ಸೆಟ್ಟಿಂಗ್‌ಗಳು &gt; ಭದ್ರತೆ &gt; ನಿರ್ವಹಿತ ಸಾಧನ ಮಾಹಿತಿ"</b>" ಎಂಬುದರಲ್ಲಿರುವ ಇತರ ನಿರ್ವಹಣೆ ಸಾಮರ್ಥ್ಯಗಳು ಈ ಸಾಧನಕ್ಕೆ ಅನ್ವಯಿಸುವುದಿಲ್ಲ"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"ಈ ಸಾಧನಕ್ಕೆ ಸುರಕ್ಷತಾ ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಹಣಕಾಸು ಸಾಧನ ವಿಭಾಗದಲ್ಲಿರುವ ನಿರ್ವಹಣಾ ಸಾಮರ್ಥ್ಯಗಳು ಅನ್ವಯಿಸುವುದಿಲ್ಲ."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"ಈ ಸಾಧನವನ್ನು <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಒದಗಿಸಿದ್ದಾರೆ"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"kiosk ಆ್ಯಪ್ ಅನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಡೌನ್‌ಲೋಡ್ ಹಾಗೂ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗುತ್ತದೆ"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"ಈ ಬಳಕೆದಾರರಿಗಾಗಿ Kiosk ಆ್ಯಪ್ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗುತ್ತದೆ"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"ನೀವು ಪಾವತಿಯನ್ನು ಮಿಸ್ ಮಾಡಿಕೊಂಡರೆ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಈ ಸಾಧನವನ್ನು ನಿರ್ಬಂಧಿಸಬಹುದು"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"ನೀವು ಪಾವತಿಯನ್ನು ಮಿಸ್ ಮಾಡಿದರೆ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಸಾಧನವನ್ನು ನಿರ್ಬಂಧಿಸಬಹುದು. ವಿವರಗಳಿಗಾಗಿ, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ನಿಯಮಗಳು ಮತ್ತು ನಿಬಂಧನೆಗಳನ್ನು<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> ವೀಕ್ಷಿಸಿ."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"ನೀವು ಅಗತ್ಯವಿರುವ ಪಾವತಿಗಳನ್ನು ಮಾಡದಿದ್ದರೆ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಈ ಸಾಧನವನ್ನು ನಿರ್ಬಂಧಿಸಬಹುದು. ವಿವರಗಳಿಗಾಗಿ, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ನಿಯಮಗಳು ಮತ್ತು ಷರತ್ತುಗಳನ್ನು<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> ನೋಡಿ."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"ಮಾಲೀಕರು ಪಾವತಿಗಳನ್ನು ಮಾಡದಿದ್ದರೆ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಈ ಸಾಧನವನ್ನು ನಿರ್ಬಂಧಿಸಬಹುದು"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"ಸಹಾಯಕ್ಕಾಗಿ, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಅನ್ನು ಸಂಪರ್ಕಿಸಿ<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"ಹಿಂದಿನದು"</string>
     <string name="next" msgid="8248291863254324326">"ಮುಂದಿನದು"</string>
     <string name="start" msgid="2842214844667658537">"ಪ್ರಾರಂಭಿಸಿ"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"ಮಾಹಿತಿ"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"ಪೂರೈಕೆಯ ಮಾಹಿತಿ"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ನೋಂದಣಿ ಮಾಡಿ"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"ನೀವು ಈಗ ನಿಮ್ಮ ಸಾಧನವನ್ನು <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ನ ಹಣಕಾಸು ಪ್ರೋಗ್ರಾಂಗೆ ನೋಂದಣಿ ಮಾಡಬಹುದು"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"ನೀವು ಈಗ ನಿಮ್ಮ ಸಾಧನವನ್ನು <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ನ ಹಣಕಾಸು ಪ್ರೋಗ್ರಾಂಗೆ ನೋಂದಣಿ ಮಾಡಬಹುದು"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"ನೀವು ಈಗ ನಿಮ್ಮ ಸಾಧನವನ್ನು <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ನ ಸಬ್ಸಿಡಿ ಪ್ರೋಗ್ರಾಂನಲ್ಲಿ ನೋಂದಾಯಿಸಿಕೊಳ್ಳಬಹುದು"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"ನೀವು <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ನ ಸಬ್ಸಿಡಿ ಪ್ರೋಗ್ರಾಂನಲ್ಲಿದ್ದೀರಿ"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ಸಾಧನದ ನೋಂದಣಿ"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"ಈ ಸಾಧನದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಬದಲಾಯಿಸಬಹುದು"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ಸಾಲ ಪಡೆದು ಖರೀದಿಸಿದ ಸಾಧನದ ಮಾಹಿತಿ"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"ನಿಮ್ಮ ಕ್ರೆಡಿಟ್ ಒದಗಿಸುವವರು ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಬಹುದು ಮತ್ತು ಸಾಧನದಲ್ಲಿ Kiosk ಆ್ಯಪ್ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಬಹುದು.\n\nನೀವು ಅಗತ್ಯ ಪಾವತಿಗಳನ್ನು ಮಾಡದಿದ್ದರೆ ಅಥವಾ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ಸಿಮ್ ಬಳಸುವುದನ್ನು ನಿಲ್ಲಿಸಿದರೆ <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ಈ ಸಾಧನವನ್ನು ನಿರ್ಬಂಧಿಸಬಹುದು.\n\nಇನ್ನಷ್ಟು ತಿಳಿಯಲು, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ಅನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಬಹುದು ಮತ್ತು ಸಾಧನದಲ್ಲಿ Kiosk ಆ್ಯಪ್ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಬಹುದು.\n\nನೀವು ಪಾವತಿಯನ್ನು ಮಿಸ್ ಮಾಡಿಕೊಂಡರೆ, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ನಿಮ್ಮ ಸಾಧನವನ್ನು ನಿರ್ಬಂಧಿಸಬಹುದು.\n\nಇನ್ನಷ್ಟು ತಿಳಿಯಲು, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ಅನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಬಹುದು ಮತ್ತು ಸಾಧನದಲ್ಲಿ Kiosk ಆ್ಯಪ್ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಬಹುದು.\n\nನೀವು ಪಾವತಿಯನ್ನು ಮಿಸ್ ಮಾಡಿಕೊಂಡರೆ ಅಥವಾ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ನ SIM ಬಳಸುವುದನ್ನು ನಿಲ್ಲಿಸಿದರೆ, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ಈ ಸಾಧನವನ್ನು ನಿರ್ಬಂಧಿಸಬಹುದು.\n\nಇನ್ನಷ್ಟು ತಿಳಿಯಲು, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> ಅನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಪಾವತಿಸುವವರೆಗೆ, ನಿಮಗೆ ಇದನ್ನು ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಸುರಕ್ಷಿತ ಮೋಡ್‌ಗೆ ರೀಬೂಟ್ ಮಾಡಿ"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"ದಿನಾಂಕ, ಸಮಯ ಮತ್ತು ಸಮಯ ವಲಯಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳನ್ನು ಬಳಸಿ"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"ಸಾಧನದಲ್ಲಿ ಸಮಸ್ಯೆಯಾದರೆ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಹೀಗೆ ಮಾಡಬಹುದು:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"ನೀವು <xliff:g id="KIOSK_APP">%1$s</xliff:g> ಆ್ಯಪ್ ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಬಹುದು"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"ಸಹಾಯ ಪಡೆಯಲು:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಅನ್ನು ಸಂಪರ್ಕಿಸಿ<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"ಪೂರೈಕೆ"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{ಸಾಧನವನ್ನು 1 ದಿನದಲ್ಲಿ ರೀಸೆಟ್ ಮಾಡಲಾಗುತ್ತದೆ}one{ಸಾಧನವನ್ನು # ದಿನಗಳಲ್ಲಿ ರೀಸೆಟ್ ಮಾಡಲಾಗುತ್ತದೆ}other{ಸಾಧನವನ್ನು # ದಿನಗಳಲ್ಲಿ ರೀಸೆಟ್ ಮಾಡಲಾಗುತ್ತದೆ}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"ಸಾಧನವು <xliff:g id="TIMER">%s</xliff:g> ಗೆ ರೀಸೆಟ್ ಆಗಲಿದೆ"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ಎಲ್ಲಾ ಸಾಧನ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ. ನಿಮ್ಮ ಸಾಧನವನ್ನು ನೋಂದಾಯಿಸಲು ಸಹಾಯಕ್ಕಾಗಿ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ಅನ್ನು ಸಂಪರ್ಕಿಸಿ"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"ಸಾಧನ ನೋಂದಣಿಯನ್ನು ಮುಂದೂಡುವುದನ್ನು ಮುಂದುವರಿಸಲು DeviceLock ನಿಂದ ನೋಟಿಫಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸಿ."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ಹಣಕಾಸು ಒದಗಿಸುವಿಕೆ ವಿಫಲವಾಗಿದೆ"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"ನಿಮ್ಮ ಫೈನಾನ್ಷಿಯರ್ ಅನ್ನು ಸಂಪರ್ಕಿಸುವ ಮಾರ್ಗಗಳಿಗಾಗಿ ಇಲ್ಲಿ ಕ್ಲಿಕ್ ಮಾಡಿ. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"ನಿರ್ಗಮಿಸಿ"</string>
+    <string name="retry" msgid="7497287909193345356">"ಮರುಪ್ರಯತ್ನಿಸಿ"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ko/strings.xml b/DeviceLockController/res/values-ko/strings.xml
index ed74d3f..5029b15 100644
--- a/DeviceLockController/res/values-ko/strings.xml
+++ b/DeviceLockController/res/values-ko/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>의 잠금 또는 잠금 해제 요청"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> 앱을 사용할 수 없는 경우"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"오픈소스 라이선스"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"설정 &gt; 보안 &gt; 관리 기기 정보"</b>"의 기타 관리 기능은 이 기기에 적용되지 않습니다."</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"보안 설정의 할부 기기 정보 섹션에 있는 관리 기능은 이 기기에 적용되지 않습니다."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에서 제공하는 기기"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"키오스크 앱이 자동으로 다운로드 및 설치됩니다."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"키오스크 앱이 이 사용자를 위해 설치됩니다."</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"결제를 하지 않으면 <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에서 이 기기 사용을 제한할 수 있습니다."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"결제를 하지 않으면 <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에서 기기 사용을 제한할 수 있습니다. 자세한 내용은 <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>이용약관<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>에서 확인하세요."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"필수 결제를 진행하지 않으면 <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에서 이 기기 사용을 제한할 수 있습니다. 자세한 내용은 <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>이용약관<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>에서 확인하세요."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"기기 소유자가 결제를 하지 않으면 <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에서 이 기기 사용을 제한할 수 있습니다."</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"도움이 필요하면 <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에 문의<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>하세요."</string>
     <string name="previous" msgid="5241891780917802570">"이전"</string>
     <string name="next" msgid="8248291863254324326">"다음"</string>
     <string name="start" msgid="2842214844667658537">"시작"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"정보"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"프로비저닝 정보"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"기기 등록"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"이제 기기를 <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>의 파이낸싱 프로그램에 등록할 수 있습니다."</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"이제 기기를 <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>의 재정 지원 프로그램에 등록할 수 있습니다"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"이제 기기를 <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>의 보조금 프로그램에 등록할 수 있습니다."</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>의 보조금 프로그램 사용 중"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"기기 등록"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에서 이 기기의 설정을 변경할 수 있습니다."</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"자세히 알아보기"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"할부 기기 정보"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"신용 상품 제공업체는 이 기기의 설정을 변경하고 키오스크 앱을 설치할 수 있습니다.\n\n필수 결제를 놓치거나 <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>의 SIM 사용을 중지하면 <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>에서 기기를 잠그고 기기 설정을 변경할 수 있습니다.\n\n자세한 내용은 <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>에 문의하세요."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>은(는) 이 기기의 설정을 변경하고 키오스크 앱을 설치할 수 있습니다.\n\n결제를 놓치면 <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>에서 기기를 제한할 수 있습니다.\n\n자세한 내용은 <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>에 문의하세요."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>은(는) 이 기기의 설정을 변경하고 키오스크 앱을 설치할 수 있습니다.\n\n결제를 놓치거나 <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>의 SIM 사용을 중지하면 <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>에서 이 기기를 제한할 수도 있습니다.\n\n자세한 내용은 <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>에 문의하세요."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"기기 대금을 결제하지 않으면 다음 작업을 할 수 없습니다."</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"기기를 안전 모드로 재부팅"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"날짜, 시간 및 시간대 변경"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"개발자 옵션 사용"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"기기에 문제가 생기면 <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에서 다음 조치를 취할 수 있습니다."</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> 앱을 제거할 수 있음"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"지원 받는 방법:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에 문의하기<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"사용 설정"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{1일 후 기기 초기화}other{#일 후 기기 초기화}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"<xliff:g id="TIMER">%s</xliff:g> 후 기기 초기화"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"기기의 모든 데이터가 삭제됩니다. 기기 등록과 관련해 도움이 필요하면 <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>에 문의하세요."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"기기 등록을 계속 미루려면 DeviceLock의 알림을 허용해 주세요."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"파이낸싱 프로비저닝 실패함"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"여기를 클릭하여 금융 기관에 문의하는 방법을 확인하세요. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>자세히 알아보기<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"종료"</string>
+    <string name="retry" msgid="7497287909193345356">"다시 시도"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ky/strings.xml b/DeviceLockController/res/values-ky/strings.xml
index 3208a64..97d60fa 100644
--- a/DeviceLockController/res/values-ky/strings.xml
+++ b/DeviceLockController/res/values-ky/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> жөнөткөн бардык кулпулоо же кулпуну ачуу сурамдарын"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> колдонмосунун түзмөктө жеткиликсиз экенин"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Ачык программа уруксаттамалары"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"Параметрлер &gt; Коопсуздук &gt; Башкарылган түзмөк жөнүндө маалымат"</b>" бөлүмүндөгү башка башкаруу мүмкүнчүлүктөрү бул түзмөктө колдонулбайт"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Коопсуздук параметрлеринин каржыланган түзмөк бөлүмүндөгү башкаруу мүмкүнчүлүктөрү бул түзмөккө карата колдонулбайт."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Бул түзмөктү <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> камсыздады"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Киоск колдонмосу автоматтык түрдө жүктөлүп алынып, орнотулат"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Киоск колдонмосу бул колдонуучу үчүн орнотулат"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Эгер төлөмдү өткөрүп жиберсеңиз, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> бул түзмөктү чектеши мүмкүн"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Эгер төлөмдү өткөрүп жиберсеңиз, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> түзмөктү чектеп коюшу мүмкүн. Толук маалымат алуу үчүн <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Жоболорду жана шарттарды<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> караңыз."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Талап кылынган нерселердин акысын төлөбөсөңүз, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> бул түзмөктүн иштешин чектеши мүмкүн. Толук маалымат алуу үчүн <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Жоболорду жана шарттарды<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> караңыз."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Эгер ээси төлөмдөрдү аткарбаса, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> бул түзмөктү чектеши мүмкүн"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Жардам алуу үчүн <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> менен байланышыңыз<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Мурунку"</string>
     <string name="next" msgid="8248291863254324326">"Кийинки"</string>
     <string name="start" msgid="2842214844667658537">"Баштоо"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Маалымат"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Камсыздоо маалыматы"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Түзмөгүңүздү каттаңыз"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Эми түзмөгүңүздү <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> каржы программасына каттай аласыз"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Эми түзмөгүңүздү <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> каржы программасына каттай аласыз"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Эми түзмөгүңүздү <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> субсидия программасына каттай аласыз"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> cубсидия программасына кошулдуңуз"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Түзмөктү каттоо"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> бул түзмөктө параметрлерди өзгөртүшү мүмкүн"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Кеңири маалымат"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Насыяга алынган түзмөк тууралуу"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Насыя берүүчү параметрлерди өзгөртүп, түзмөккө Киоск колдонмосун орнотушу мүмкүн.\n\nКеректүү төлөмдү аткарбасаңыз же <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIM картасын колдонбой калсаңыз, <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> бул түзмөктү чектеп коюшу мүмкүн.\n\nКеңири маалымат алуу үчүн <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> менен байланышыңыз."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> параметрлерди өзгөртүп, түзмөккө Киоск колдонмосун орнотушу мүмкүн.\n\nЭгер төлөмдү өткөрүп жиберсеңиз, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> түзмөгүңүздү чектеп коюшу мүмкүн.\n\nКеңири маалымат алуу үчүн <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> менен байланышыңыз."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> параметрлерди өзгөртүп, түзмөккө Киоск колдонмосун орнотушу мүмкүн.\n\nТөлөмдү өткөрүп жиберсеңиз же <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM картасын колдонбой калсаңыз, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> бул түзмөктү чектеп коюшу мүмкүн.\n\nКеңири маалымат алуу үчүн <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> менен байланышыңыз."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Түзмөгүңүз үчүн төлөбөсөңүз, төмөнкүлөрдү аткара албайсыз:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Коопсуз режимге өтүү үчүн түзмөктү өчүрүп-күйгүзүү"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Күндү, убакытты жана убакыт алкактарын өзгөртүү"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Иштеп чыгуучyнун параметрлерин колдонуу"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Эгер түзмөгүңүздө ката кетсе, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> төмөнкүлөрдү аткара алат:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> колдонмосун чыгарып салсаңыз болот"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Жардам алуу үчүн:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> менен байланышыңыз<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Камсыздоо"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Түзмөк 1 күндөн кийин баштапкы абалга келтирилет}other{Түзмөк # күндөн кийин баштапкы абалга келтирилет}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Түзмөк <xliff:g id="TIMER">%s</xliff:g> кийин баштапкы абалга келтирилет"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Түзмөктөгү бардык нерселер жок кылынат. Түзмөктү каттоо боюнча жардам алуу үчүн <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> менен байланышыңыз"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Түзмөктү каттоону кечиктирүү үчүн DeviceLock билдирмесине уруксат бериңиз."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Каржы берилген жок"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Финансист менен байланышуу жолдорун көрүү үчүн бул жерди чыкылдатыңыз. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Кеңири маалымат<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Чыгуу"</string>
+    <string name="retry" msgid="7497287909193345356">"Кайталоо"</string>
 </resources>
diff --git a/DeviceLockController/res/values-lo/strings.xml b/DeviceLockController/res/values-lo/strings.xml
index 6060806..4a1d7fa 100644
--- a/DeviceLockController/res/values-lo/strings.xml
+++ b/DeviceLockController/res/values-lo/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"ຄຳຮ້ອງຂໍການລັອກ ຫຼື ປົດລັອກຈາກ <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"ຫາກແອັບ <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ບໍ່ພ້ອມໃຫ້ບໍລິການ"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ໃບອະນຸຍາດໂອເພນຊອດ"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"ຄວາມສາມາດອື່ນໆໃນການຈັດການໃນ "<b>"ການຕັ້ງຄ່າ &gt; ຄວາມປອດໄພ &gt; ຂໍ້ມູນອຸປະກອນທີ່ມີການຈັດການ"</b>" ຈະບໍ່ໄດ້ນຳໃຊ້ກັບອຸປະກອນນີ້"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"ຈະບໍ່ມີການນຳໃຊ້ຄວາມສາມາດໃນການຈັດການໃນພາກສ່ວນອຸປະກອນທີ່ໄດ້ຮັບການສະໜັບສະໜູນທາງການເງິນຂອງການຕັ້ງຄ່າຄວາມປອດໄພກັບອຸປະກອນນີ້."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"ອຸປະກອນນີ້ໃຫ້ບໍລິການໂດຍ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"ລະບົບຈະດາວໂຫຼດແອັບ kiosk ແລະ ຕິດຕັ້ງໂດຍອັດຕະໂນມັດ"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"ລະບົບຈະຕິດຕັ້ງແອັບ kiosk ສຳລັບຜູ້ໃຊ້ຄົນນີ້"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ສາມາດຈຳກັດອຸປະກອນນີ້ໄດ້ ຫາກທ່ານບໍ່ຈ່າຍເງິນ"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ສາມາດຈຳກັດອຸປະກອນໄດ້ ຫາກທ່ານບໍ່ຈ່າຍເງິນ. ສຳລັບລາຍລະອຽດ, ໃຫ້ເບິ່ງ <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ຂໍ້ກຳນົດ ແລະ ເງື່ອນໄຂ<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ສາມາດຈຳກັດອຸປະກອນນີ້ໄດ້ ຫາກທ່ານບໍ່ຈ່າຍເງິນຕາມທີ່ກຳນົດ. ສຳລັບລາຍລະອຽດ, ໃຫ້ເບິ່ງ <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ຂໍ້ກຳນົດ ແລະ ເງື່ອນໄຂ<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ສາມາດຈຳກັດອຸປະກອນນີ້ໄດ້ ຫາກເຈົ້າຂອງບໍ່ຈ່າຍເງິນ"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"ເພື່ອຂໍຄວາມຊ່ວຍເຫຼືອ, ກະລຸນາ <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ຕິດຕໍ່ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"ກ່ອນໜ້າ"</string>
     <string name="next" msgid="8248291863254324326">"ຕໍ່ໄປ"</string>
     <string name="start" msgid="2842214844667658537">"ເລີ່ມ"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"ຂໍ້ມູນ"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"ຂໍ້ມູນການຈັດກຽມ"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"ລົງທະບຽນອຸປະກອນຂອງທ່ານ"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"ຕອນນີ້ທ່ານສາມາດລົງທະບຽນອຸປະກອນຂອງທ່ານໃນໂປຣແກຣມສະໜັບສະໜູນທາງການເງິນຂອງ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ໄດ້ແລ້ວ"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"ຕອນນີ້ທ່ານສາມາດລົງທະບຽນອຸປະກອນຂອງທ່ານໃນໂປຣແກຣມສະໜັບສະໜູນທາງການເງິນຂອງ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ໄດ້ແລ້ວ"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"ຕອນນີ້ທ່ານສາມາດລົງທະບຽນອຸປະກອນຂອງທ່ານໃນໂປຣແກຣມສະໜັບສະໜູນທາງການເງິນຂອງ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ໄດ້ແລ້ວ"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"ທ່ານຢູ່ໃນໂປຣແກຣມສະໜັບສະໜູນທາງການເງິນຂອງ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ການລົງທະບຽນອຸປະກອນ"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ສາມາດປ່ຽນການຕັ້ງຄ່າຢູ່ອຸປະກອນນີ້ໄດ້"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"ສຶກສາເພີ່ມເຕີມ"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ຂໍ້ມູນອຸປະກອນທີ່ໄດ້ຮັບການສະໜັບສະໜູນທາງການເງິນ"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"ຜູ້ໃຫ້ບໍລິການເຄຣດິດຂອງທ່ານສາມາດປ່ຽນການຕັ້ງຄ່າ ແລະ ຕິດຕັ້ງແອັບ kiosk ຢູ່ອຸປະກອນນີ້ໄດ້.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ອາດຈຳກັດອຸປະກອນນີ້ ຫາກທ່ານບໍ່ຈ່າຍເງິນຕາມກຳນົດ ຫຼື ຢຸດໃຊ້ຊິມຂອງ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nເພື່ອສຶກສາເພີ່ມເຕີມ, ກະລຸນາຕິດຕໍ່ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ສາມາດປ່ຽນການຕັ້ງຄ່າ ແລະ ຕິດຕັ້ງແອັບ kiosk ຢູ່ອຸປະກອນນີ້ໄດ້.\n\nຫາກທ່ານບໍ່ຈ່າຍເງິນ, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ສາມາດຈຳກັດອຸປະກອນຂອງທ່ານໄດ້.\n\nເພື່ອສຶກສາເພີ່ມເຕີມ, ກະລຸນາຕິດຕໍ່ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ສາມາດປ່ຽນການຕັ້ງຄ່າ ແລະ ຕິດຕັ້ງແອັບ kiosk ຢູ່ອຸປະກອນນີ້ໄດ້.\n\nນອກຈາກນັ້ນ, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ອາດຈຳກັດອຸປະກອນນີ້ນຳຫາກທ່ານບໍ່ຈ່າຍເງິນ ຫຼື ຢຸດໃຊ້ຊິມຂອງ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nເພື່ອສຶກສາເພີ່ມເຕີມ, ກະລຸນາຕິດຕໍ່ <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"ຈົນກວ່າທ່ານຈະຈ່າຍເງິນຄ່າອຸປະກອນຂອງທ່ານ, ທ່ານຈະບໍ່ສາມາດ:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"ປິດເປີດອຸປະກອນຂອງທ່ານໃໝ່ເພື່ອໃຫ້ຢູ່ໃນ safe mode"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"ປ່ຽນວັນທີ, ເວລາ ແລະ ເຂດເວລາ"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ໃຊ້ຕົວເລືອກນັກພັດທະນາ"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"ຫາກພົບບັນຫາໃນອຸປະກອນຂອງທ່ານ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ສາມາດເຮັດສິ່ງຕໍ່ໄປນີ້ໄດ້:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"ທ່ານສາມາດຖອນການຕິດຕັ້ງແອັບ <xliff:g id="KIOSK_APP">%1$s</xliff:g> ໄດ້"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"ເພື່ອຂໍຄວາມຊ່ວຍເຫຼືອ:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ຕິດຕໍ່ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"ການຈັດກຽມ"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{ອຸປະກອນຈະຣີເຊັດໃນອີກ 1 ມື້}other{ອຸປະກອນຈະຣີເຊັດໃນອີກ # ມື້}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"ອຸປະກອນຈະຣີເຊັດໃນອີກ <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ຂໍ້ມູນທັງໝົດໃນອຸປະກອນຈະຖືກລຶບອອກ. ເພື່ອຂໍຄວາມຊ່ວຍເຫຼືອໃນການລົງທະບຽນອຸປະກອນຂອງທ່ານ, ກະລຸນາຕິດຕໍ່ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"ກະລຸນາອະນຸຍາດໃຫ້ມີການແຈ້ງເຕືອນຈາກ DeviceLock ເພື່ອເລື່ອນການລົງທະບຽນອຸປະກອນອອກໄປກ່ອນ."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ການຈັດກຽມດ້ານການເງິນບໍ່ສຳເລັດ"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"ກະລຸນາຄລິກຢູ່ບ່ອນນີ້ສຳລັບວິທີໃນການຕິດຕໍ່ນັກການເງິນຂອງທ່ານ. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>ສຶກສາເພີ່ມເຕີມ<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"ອອກ"</string>
+    <string name="retry" msgid="7497287909193345356">"ລອງໃໝ່"</string>
 </resources>
diff --git a/DeviceLockController/res/values-lt/strings.xml b/DeviceLockController/res/values-lt/strings.xml
index e5cbe7a..cfc529d 100644
--- a/DeviceLockController/res/values-lt/strings.xml
+++ b/DeviceLockController/res/values-lt/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Visos „<xliff:g id="CREDITOR_APP">%1$s</xliff:g>“ pateiktos užrakinimo ar atrakinimo užklausos"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Jei programa „<xliff:g id="CREDITOR_APP">%1$s</xliff:g>“ nepasiekiama"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Atvirojo šaltinio licencijos"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Kitos skiltyje "<b>"„Nustatymai“ &amp;gt „Sauga“ &amp;gt „Tvarkomo įrenginio informacija“"</b>" esančios tvarkymo funkcijos netaikomos šiam įrenginiui"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Tvarkymo funkcijos, esančios finansuojamo įrenginio skiltyje „Saugos nustatymai“, netaikomos šiam įrenginiui."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Šį įrenginį teikia „<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Viešojo terminalo programa bus atsiųsta ir įdiegta automatiškai"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Viešojo terminalo programa bus įdiegta šiam naudotojui"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"„<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ gali apriboti šį įrenginį, jei praleisite mokėjimą"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"„<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ gali apriboti įrenginį, jei praleisite mokėjimą. Jei reikia išsamios informacijos, žr. skiltį <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>„Taisyklės ir nuostatos“<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"„<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ gali apriboti šį įrenginį, jei neatliksite reikiamų mokėjimų. Jei reikia išsamios informacijos, žr. skiltį <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>„Taisyklės ir nuostatos“<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"„<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ gali apriboti šį įrenginį, jei savininkas neatliks mokėjimų"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Jei reikia pagalbos, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>susisiekite su „<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Ankstesnis"</string>
     <string name="next" msgid="8248291863254324326">"Kitas"</string>
     <string name="start" msgid="2842214844667658537">"Pradėti"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informacija"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Pateikimo informac."</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Užregistruokite įrenginį"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Dabar galite užregistruoti įrenginį „<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ finansavimo programoje"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Dabar galite užregistruoti įrenginį „<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ finansavimo programoje"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Dabar galite užregistruoti įrenginį „<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ subsidijų programoje"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Dalyvaujate „<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ subsidijų programoje"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Įrenginio registracija"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"„<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ gali keisti šio įrenginio nustatymus"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Sužinokite daugiau"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Finansuojamo įrenginio informacija"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Jūsų kredito teikėjas gali keisti nustatymus ir įdiegti viešojo terminalo programą šiame įrenginyje.\n\n„<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>“ gali apriboti šį įrenginį, jei neatliksite reikiamų mokėjimų arba nustosite naudoti „<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>“ SIM kortelę.\n\nJei norite sužinoti daugiau, susisiekite su „<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>“."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"„<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>“ gali keisti nustatymus ir įdiegti viešojo terminalo programą šiame įrenginyje.\n\nJei praleisite mokėjimą, „<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>“ gali apriboti įrenginį.\n\nJei norite sužinoti daugiau, susisiekite su „<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>“."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"„<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>“ gali keisti nustatymus ir įdiegti viešojo terminalo programą šiame įrenginyje.\n\n„<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>“ gali apriboti šį įrenginį, jei praleisite mokėjimą arba nustosite naudoti „<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>“ SIM kortelę.\n\nJei norite sužinoti daugiau, susisiekite su „<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>“."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Nesumokėję už įrenginį negalėsite atlikti nurodytų veiksmų."</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Paleisti įrenginį iš naujo saugos režimu"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Keisti datą, laiką ir laiko juostas"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Naudoti kūrėjo parinktis"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Kilus problemų dėl įrenginio, „<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“ gali:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Galite pašalinti programą „<xliff:g id="KIOSK_APP">%1$s</xliff:g>“"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Jei reikia pagalbos, atlikite toliau nurodytus veiksmus."</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Susisiekite su „<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Pateikimas"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Įrenginys bus nustatytas iš naujo už vienos dienos}one{Įrenginys bus nustatytas iš naujo už # dienos}few{Įrenginys bus nustatytas iš naujo už # dienų}many{Įrenginys bus nustatytas iš naujo už # dienos}other{Įrenginys bus nustatytas iš naujo už # dienų}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Įrenginys bus nustatytas iš naujo už <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Visi įrenginio duomenys bus ištrinti. Jei reikia pagalbos dėl įrenginio registracijos, susisiekite su „<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>“"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Leiskite „DeviceLock“ pranešimus, kad ir toliau atidėtumėte įrenginio registraciją."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Finansavimo pateikti nepavyko"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Spustelėkite čia ir sužinokite, kaip susisiekti su finansuotoju. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Sužinokite daugiau<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Išeiti"</string>
+    <string name="retry" msgid="7497287909193345356">"Bandyti dar kartą"</string>
 </resources>
diff --git a/DeviceLockController/res/values-lv/strings.xml b/DeviceLockController/res/values-lv/strings.xml
index 409d455..fb9385e 100644
--- a/DeviceLockController/res/values-lv/strings.xml
+++ b/DeviceLockController/res/values-lv/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Visi bloķēšanas un atbloķēšanas pieprasījumi no lietotnes <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Vai lietotne <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ir pieejama"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Atklātā pirmkoda licences"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Citas pārvaldības iespējas, kas atrodamas sadaļā "<b>"Iestatījumi &gt; Drošība &gt; Informācija par pārvaldīto ierīci"</b>", neattiecas uz šo ierīci."</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Pārvaldības iespējas, kas atrodamas finansētās ierīces sadaļā drošības iestatījumos, neattiecas uz šo ierīci."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Šo ierīci nodrošina <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kioska lietotne tiks lejupielādēta un instalēta automātiski"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Šim lietotājam tiks instalēta kioska lietotne"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> var ierobežot piekļuvi šai ierīcei, ja kavēsiet maksājumus"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> var ierobežot piekļuvi ierīcei, ja kavēsiet maksājumus. Detalizētu informāciju skatiet <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>pakalpojumu sniegšanas noteikumos<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> var ierobežot piekļuvi šai ierīcei, ja neveiksiet maksājumus. Detalizētu informāciju skatiet <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>pakalpojumu sniegšanas noteikumos<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> var ierobežot piekļuvi šai ierīcei, ja īpašnieks neveiks maksājumus"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Lai saņemtu palīdzību, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>sazinieties ar <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Atpakaļ"</string>
     <string name="next" msgid="8248291863254324326">"Tālāk"</string>
     <string name="start" msgid="2842214844667658537">"Sākt"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informācija"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Nodrošin. inform."</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Ierīces reģistrēšana"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Tagad varat reģistrēt savu ierīci “<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>” finansēšanas programmā"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Tagad varat reģistrēt savu ierīci “<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>” finansēšanas programmā"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Tagad varat reģistrēt savu ierīci “<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>” subsidēšanas programmā"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Jūs piedalāties <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> subsidēšanas programmā"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Ierīces reģistrācija"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> var mainīt iestatījumus šajā ierīcē"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Uzzināt vairāk"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Finansētās ierīces informācija"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Jūsu kredīta nodrošinātājs var mainīt iestatījumus un instalēt kioska lietotni šajā ierīcē.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> var ierobežot piekļuvi šai ierīcei, ja neveiksiet maksājumus vai pārtrauksiet <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIM kartes izmantošanu.\n\nLai uzzinātu vairāk, sazinieties ar <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> var mainīt iestatījumus un instalēt kioska lietotni šajā ierīcē.\n\nJa laicīgi neveiksiet maksājumu, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> var ierobežot piekļuvi jūsu ierīcei.\n\nLai uzzinātu vairāk, sazinieties ar <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> var mainīt iestatījumus un instalēt kioska lietotni šajā ierīcē.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> var arī ierobežot piekļuvi šai ierīcei, ja laicīgi neveiksiet maksājumu vai pārtrauksiet <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM kartes izmantošanu.\n\nLai uzzinātu vairāk, sazinieties ar <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Kamēr nebūsiet samaksājis par ierīci, nevarēsiet:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Atkārtoti palaist ierīci drošajā režīmā"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Mainīt datumu, laiku un laika joslas"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Izmantot izstrādātāju opcijas"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Ja radīsies problēmas ar ierīci, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> varēs:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Varat atinstalēt lietotni <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Lai saņemtu palīdzību:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Sazināties ar <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Nodrošināšana"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Ierīce tiks atiestatīta pēc 1 dienas}zero{Ierīce tiks atiestatīta pēc # dienām}one{Ierīce tiks atiestatīta pēc # dienas}other{Ierīce tiks atiestatīta pēc # dienām}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Ierīce tiks atiestatīta pēc: <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Visi ierīces dati tiks izdzēsti. Lai saņemtu palīdzību par ierīces reģistrēšanu, sazinieties ar <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Lūdzu, atļaujiet DeviceLock paziņojumu, lai turpinātu ierīces reģistrācijas atlikšanu."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Neizdevās nodrošināt finansējumu"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Lūdzu, noklikšķiniet šeit, lai uzzinātu, kā sazināties ar finansētāju. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Uzziniet vairāk<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>."</string>
+    <string name="exit" msgid="645084771882733921">"Iziet"</string>
+    <string name="retry" msgid="7497287909193345356">"Mēģināt vēlreiz"</string>
 </resources>
diff --git a/DeviceLockController/res/values-mk/strings.xml b/DeviceLockController/res/values-mk/strings.xml
index ed6613e..83a74e4 100644
--- a/DeviceLockController/res/values-mk/strings.xml
+++ b/DeviceLockController/res/values-mk/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"сите барања за заклучување или отклучување од <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"ако апликацијата <xliff:g id="CREDITOR_APP">%1$s</xliff:g> не е достапна"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Лиценци за софтвер со отворен код"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Другите можности за управување во "<b>"Поставки &gt; Безбедност &gt; Информации за управуваните уреди"</b>" не важат за уредов"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Можностите за управување во делот „финансиран уред“ од поставките за „Безбедност“ не важат за уредов."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> го обезбедува уредов"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Апликацијата Kiosk автоматски ќе се преземе и ќе се инсталира"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Апликацијата Kiosk ќе се инсталира за овој корисник"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да го ограничи уредов ако пропуштите плаќање"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да го ограничи уредот ако пропуштите плаќање. За детали, погледнете во <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Услови и одредби<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да го ограничи уредов ако не ги извршите потребните плаќања. За повеќе информации, погледнете во <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Услови и одредби<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да го ограничи уредов ако сопственикот не плаќа"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"За помош, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>контактирајте со <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Претходно"</string>
     <string name="next" msgid="8248291863254324326">"Следно"</string>
     <string name="start" msgid="2842214844667658537">"Започни"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Информации"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Инфо. за подготовка"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Регистрирајте го уредот"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Сега може да го регистрирате вашиот уред во финансиската програма на <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Сега може да го регистрирате вашиот уред во програмата за финансирање на <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Сега може да го регистрирате вашиот уред во програмата за субвенции на <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Ја користите програмата за субвенции на <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Регистрирање на уредот"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да ги менува поставките на уредов"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Дознајте повеќе"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Информации за уредот на рати"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Вашиот давател на кредит може да ги менува поставките и да ја инсталира апликацијата Kiosk на уредот.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може да го ограничи овој уред ако не ги извршите потребните плаќања или да престанете да ја користите SIM-картичката на <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nЗа да дознаете повеќе, контактирајте со <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може да ги променува поставките и да ја инсталира апликацијата Kiosk на уредот.\n\nАко пропуштите плаќање, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> може да го ограничи вашиот уред.\n\nЗа да дознаете повеќе, контактирајте со <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може да ги променува поставките и да ја инсталира апликацијата Kiosk на уредот.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> може и да го ограничи уредов ако пропуштите плаќање или сопрете со користење на SIM-картичката на <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nЗа да дознаете повеќе, контактирајте со <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Додека не го отплатите вашиот уред, не може:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"да го рестартирате уредот во безбеден режим"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"да ги менува датумот, времето и часовната зона"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"да користи „Опции за програмери“"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Ако има проблем со уредот, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Може да ја деинсталирате апликацијата <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"За помош:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Контактирајте со <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Подготовка"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Уредот ќе се ресетира за 1 ден}one{Уредот ќе се ресетира за # ден}other{Уредот ќе се ресетира за # дена}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Уредот ќе се ресетира за <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Сите податоци на уредот ќе се избришат. За помош со регистрирањето на вашиот уред, контактирајте со <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Дозволете ги известувањата од DeviceLock за да продолжите да го одложувате регистрирањето на уредот."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Финансиските подготовки не беа успешни"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Кликнете овде за да ги видите начините за контакт со вашиот финансиер. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Дознајте повеќе<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Излези"</string>
+    <string name="retry" msgid="7497287909193345356">"Обиди се пак"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ml/strings.xml b/DeviceLockController/res/values-ml/strings.xml
index 3da8804..b069805 100644
--- a/DeviceLockController/res/values-ml/strings.xml
+++ b/DeviceLockController/res/values-ml/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> എന്നതിൽ നിന്നുള്ള, ലോക്ക് ചെയ്യാനോ അൺലോക്ക് ചെയ്യാനോ ഉള്ള ഏത് അഭ്യർത്ഥനയും"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ആപ്പ് ലഭ്യമല്ലെങ്കിൽ"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ഓപ്പൺ സോഴ്‌സ് ലൈസൻസുകൾ"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"ക്രമീകരണം &gt; സുരക്ഷ &gt; മാനേജ് ചെയ്യപ്പെടുന്ന ഉപകരണ വിവരങ്ങൾ"</b>" എന്നതിലെ മറ്റ് മാനേജ്‌മെന്റ് കഴിവുകൾ ഈ ഉപകരണത്തിന് ബാധകമാകില്ല"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"സുരക്ഷാ ക്രമീകരണത്തിലുള്ള ഫിനാൻസ് ചെയ്‌ത ഉപകരണ വിഭാഗത്തിലെ മാനേജ്മെന്റ് കഴിവുകൾ ഈ ഉപകരണത്തിന് ബാധകമല്ല."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> നൽകിയ ഉപകരണമാണിത്"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"കിയോസ്‌ക് ആപ്പ് സ്വയമേവ ഡൗൺലോഡ് ചെയ്ത് ഇൻസ്റ്റാൾ ചെയ്യും"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"ഈ ഉപയോക്താവിന് കിയോസ്‌ക് ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യും"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"നിങ്ങൾ ഒരു പേയ്‌മെന്റ് വിട്ടുപോയാൽ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിന് ഈ ഉപകരണം നിയന്ത്രിക്കാനാകും"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"നിങ്ങൾ ഒരു പേയ്‌മെന്റ് വിട്ടുപോയാൽ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിന് ഈ ഉപകരണം നിയന്ത്രിക്കാനാകും. വിശദാംശങ്ങൾക്ക്, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>നിബന്ധനകളും വ്യവസ്ഥകളും<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> കാണുക."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"നിങ്ങൾ ആവശ്യമായ പേയ്‌മെന്റുകൾ നടത്തുന്നില്ലെങ്കിൽ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിന് ഈ ഉപകരണം നിയന്ത്രിക്കാനാകും. വിശദാംശങ്ങൾക്ക്, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>നിബന്ധനകളും വ്യവസ്ഥകളും<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> കാണുക."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"ഉടമ പേയ്‌മെന്റുകൾ നടത്തുന്നില്ലെങ്കിൽ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിന് ഈ ഉപകരണം നിയന്ത്രിക്കാനാകും"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"സഹായത്തിന് <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>എന്നതിനെ ബന്ധപ്പെടുക<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"മുമ്പത്തേത്"</string>
     <string name="next" msgid="8248291863254324326">"അടുത്തത്"</string>
     <string name="start" msgid="2842214844667658537">"ആരംഭിക്കുക"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"വിവരങ്ങൾ"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"പ്രൊവിഷൻ വിവരങ്ങൾ"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"നിങ്ങളുടെ ഉപകരണം എൻറോൾ ചെയ്യുക"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"ഇപ്പോൾ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിന്റെ ഫിനാൻസിംഗ് പ്രോഗ്രാമിൽ നിങ്ങളുടെ ഉപകരണം എൻറോൾ ചെയ്യാനാകും"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"ഇപ്പോൾ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിന്റെ ഫിനാൻസ് പ്രോഗ്രാമിൽ നിങ്ങളുടെ ഉപകരണം എൻറോൾ ചെയ്യാനാകും"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"ഇപ്പോൾ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിന്റെ സബ്‌സിഡി പ്രോഗ്രാമിൽ നിങ്ങളുടെ ഉപകരണം എൻറോൾ ചെയ്യാനാകും"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"നിങ്ങൾ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> സബ്‌സിഡി പ്രോഗ്രാമിലുണ്ട്"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ഉപകരണ എൻറോൾമെന്റ്"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിന് ഈ ഉപകരണത്തിലെ ക്രമീകരണം മാറ്റാനാകും"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"കൂടുതലറിയുക"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ഫിനാൻസ് ചെയ്‌ത ഉപകരണത്തിന്റെ വിവരങ്ങൾ"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"നിങ്ങളുടെ ക്രെഡിറ്റ് ദാതാവിന് ക്രമീകരണം മാറ്റാനും ഉപകരണത്തിൽ കിയോസ്‌ക് ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യാനും കഴിയും.\n\nനിങ്ങൾ ആവശ്യമായ പേയ്‌മെന്റുകൾ നടത്തുന്നില്ലെങ്കിലോ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> എന്നതിന്റെ സിം ഉപയോഗിക്കുന്നത് നിർത്തുകയോ ചെയ്താൽ <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ഈ ഉപകരണം നിയന്ത്രിച്ചേക്കാം.\n\nകൂടുതലറിയാൻ, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> എന്നതിനെ ബന്ധപ്പെടുക."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> എന്നതിന് ക്രമീകരണം മാറ്റാനും ഉപകരണത്തിൽ കിയോസ്‌ക് ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യാനും കഴിയും.\n\nനിങ്ങൾ ഒരു പേയ്മെന്റ് മുടക്കിയാൽ, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> എന്നതിന് നിങ്ങളുടെ ഉപകരണം പരിമിതപ്പെടുത്താനാകും.\n\nകൂടുതലറിയാൻ, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> എന്നതിനെ ബന്ധപ്പെടുക."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> എന്നതിന് ക്രമീകരണം മാറ്റാനും ഉപകരണത്തിൽ കിയോസ്‌ക് ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യാനും കഴിയും.\n\nനിങ്ങൾ ഒരു പേയ്മെന്റ് മുടക്കിയാൽ അല്ലെങ്കിൽ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> എന്നതിന്റെ സിം ഉപയോഗിക്കുന്നത് നിർത്തുകയോ ചെയ്താൽ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ഈ ഉപകരണം നിയന്ത്രിച്ചേക്കാം.\n\nകൂടുതലറിയാൻ, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> എന്നതിനെ ബന്ധപ്പെടുക."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"ഉപകരണത്തിന് പേ ചെയ്യുന്നത് വരെ, ഇനിപ്പറയുന്നവ ചെയ്യാനാകില്ല:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"നിങ്ങളുടെ ഉപകരണം സുരക്ഷിത മോഡിലേക്ക് റീബൂട്ട് ചെയ്യുക"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"തീയതി, സമയം, സമയമേഖല എന്നിവ മാറ്റുക"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ഡെവലപ്പർ ഓ‌പ്ഷനുകൾ ഉപയോഗിക്കുക"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"ഉപകരണത്തിൽ എന്തെങ്കിലും പ്രശ്‌നമുണ്ടായാൽ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിന് ഇനിപ്പറയുന്നത് ചെയ്യാനാകും:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"നിങ്ങൾക്ക് <xliff:g id="KIOSK_APP">%1$s</xliff:g> ആപ്പ് അൺഇൻസ്‌റ്റാൾ ചെയ്യാം"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"സഹായം ലഭിക്കാൻ:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതുമായി ബന്ധപ്പെടുക<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"പ്രൊവിഷൻ"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{ഒരു ദിവസത്തിനുള്ളിൽ ഉപകരണം റീസെറ്റ് ചെയ്യും}other{# ദിവസത്തിനുള്ളിൽ ഉപകരണം റീസെറ്റ് ചെയ്യും}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"<xliff:g id="TIMER">%s</xliff:g>-നുള്ളിൽ ഉപകരണം റീസെറ്റ് ചെയ്യും"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"എല്ലാ ഉപകരണ ഡാറ്റയും ഇല്ലാതാക്കും. നിങ്ങളുടെ ഉപകരണം എൻറോൾ ചെയ്യുന്നതിനുള്ള സഹായത്തിന്, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> എന്നതിനെ ബന്ധപ്പെടുക"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"ഉപകരണത്തിന്റെ എൻറോൾമെന്റ് മാറ്റിവയ്ക്കുന്നത് തുടരാൻ DeviceLock-ൽ നിന്നുള്ള അറിയിപ്പ് അനുവദിക്കുക."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ഫിനാൻസിംഗ് പ്രൊവിഷനിംഗ് പരാജയപ്പെട്ടു"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"നിങ്ങളുടെ സാമ്പത്തിക വിദഗ്‌ധരെ ബന്ധപ്പെടുന്നതിനുള്ള മാർഗ്ഗങ്ങൾക്കായി ഇവിടെ ക്ലിക്ക് ചെയ്യുക. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>കൂടുതലറിയുക<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"പുറത്ത് കടക്കുക"</string>
+    <string name="retry" msgid="7497287909193345356">"വീണ്ടും ശ്രമിക്കുക"</string>
 </resources>
diff --git a/DeviceLockController/res/values-mn/strings.xml b/DeviceLockController/res/values-mn/strings.xml
index 49036dc..1c0efc6 100644
--- a/DeviceLockController/res/values-mn/strings.xml
+++ b/DeviceLockController/res/values-mn/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>-н аливаа түгжих эсвэл түгжээг тайлах хүсэлт"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Хэрэв <xliff:g id="CREDITOR_APP">%1$s</xliff:g> апп боломжгүй тохиолдолд"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Нээлттэй эхийн лицензүүд"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"Тохиргоо &gt; Аюулгүй байдал &gt; Удирддаг төхөөрөмжийн мэдээллийн"</b>" удирдлагын бусад чадамж энэ төхөөрөмжид хэрэгжихгүй"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Аюулгүй байдлын тохиргооны санхүүжсэн төхөөрөмжийн хэсэг дэх менежментийн чадамж нь энэ төхөөрөмжид хэрэгжихгүй."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Энэ төхөөрөмжийг <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-с нийлүүлдэг"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Киоск аппыг автоматаар татаж суулгана"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Киоск аппыг энэ хэрэглэгчид суулгана"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Хэрэв та төлбөрөө төлөөгүй бол <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> энэ төхөөрөмжийг хязгаарлах боломжтой"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Хэрэв та төлбөрөө төлөөгүй бол <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> энэ төхөөрөмжийг хязгаарлах боломжтой. Дэлгэрэнгүй мэдээлэл авах бол <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Үйлчилгээний ерөнхий нөхцөлийг<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> харна уу."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Хэрэв та шаардлагатай төлбөрийг төлөөгүй бол <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> энэ төхөөрөмжийг хязгаарлах боломжтой. Дэлгэрэнгүй мэдээлэл авах бол <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Үйлчилгээний ерөнхий нөхцөлийг<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> харна уу."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Хэрэв өмчлөгч төлбөрөө төлөөгүй бол <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> энэ төхөөрөмжийг хязгаарлах боломжтой"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Тусламж авах бол <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-тай холбогдоно уу<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Өмнөх"</string>
     <string name="next" msgid="8248291863254324326">"Дараах"</string>
     <string name="start" msgid="2842214844667658537">"Эхлүүлэх"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Мэдээлэл"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Бэлтгэлийн мэдээлэл"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Төхөөрөмжөө бүртгүүлнэ үү"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Та одоо төхөөрөмжөө <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-н санхүүгийн хөтөлбөрт бүртгүүлэх боломжтой"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Та одоо төхөөрөмжөө <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-н санхүүгийн хөтөлбөрт бүртгүүлэх боломжтой"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Та одоо төхөөрөмжөө <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-н татаасны хөтөлбөрт бүртгүүлэх боломжтой"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Та <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-н татаасны хөтөлбөрт байна"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Төхөөрөмж бүртгүүлэх"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> энэ төхөөрөмжийн тохиргоог өөрчлөх боломжтой"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Нэмэлт мэдээлэл авах"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Зээлээр авсан төхөөрөмжийн мэдээлэл"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Таны зээлийн үйлчилгээ үзүүлэгч уг төхөөрөмжид тохиргоог өөрчлөх болон киоск аппыг суулгах боломжтой.\n\nТа шаардлагатай төлбөрөө төлөөгүй эсвэл<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>-н SIM-г ашиглахаа боливол <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> энэ төхөөрөмжийг хязгаарлаж болно.\n\nНэмэлт мэдээлэл авахын тулд <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-тай холбогдоно уу."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> тохиргоог өөрчлөх болон төхөөрөмжид Киоск аппыг суулгах боломжтой.\n\nХэрэв та төлбөрөө төлөөгүй бол <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> таны төхөөрөмжийг хязгаарлах боломжтой.\n\nНэмэлт мэдээлэл авахын тулд <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-тай холбогдоно уу."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> тохиргоог өөрчлөх болон төхөөрөмжид Киоск аппыг суулгах боломжтой.\n\nХэрэв та төлбөр төлөөгүй эсвэл <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>-н SIM-г ашиглахаа боливол <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> энэ төхөөрөмжийг хязгаарлаж магадгүй.\n\nНэмэлт мэдээлэл авахын тулд <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>-тай холбогдоно уу."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Та төхөөрөмжийн төлбөрийг төлтлөө дараахыг хийж болохгүй:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Төхөөрөмжөө аюулгүй горимд дахин асаах"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Огноо, цаг болон цагийн бүсийг өөрчилнө үү"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Хөгжүүлэгчийн тохиргоог ашиглах"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Таны төхөөрөмжид асуудал гарвал <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> дараахыг хийж болно:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Та <xliff:g id="KIOSK_APP">%1$s</xliff:g> аппыг устгах боломжтой"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Тусламж авахын тулд:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-тай холбогдох<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Бэлтгэл"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Төхөөрөмжийг 1 хоногийн дараа шинэчилнэ}other{Төхөөрөмжийг # хоногийн дараа шинэчилнэ}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Төхөөрөмжийг <xliff:g id="TIMER">%s</xliff:g>-н дараа шинэчилнэ"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Төхөөрөмжийн бүх өгөгдлийг устгана. Төхөөрөмжөө бүртгүүлэх тусламж авах бол <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>-тай холбогдоно уу"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Төхөөрөмжийн бүртгэлийг үргэлжлүүлэн хойшлуулахын тулд DeviceLock-н мэдэгдлийг зөвшөөрнө үү."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Санхүүгийн бэлтгэлийг хийж чадсангүй"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Санхүүчтэйгээ холбоо барих аргуудыг авах бол энд товшино уу. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Нэмэлт мэдээлэл авах<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Гарах"</string>
+    <string name="retry" msgid="7497287909193345356">"Дахин оролдох"</string>
 </resources>
diff --git a/DeviceLockController/res/values-mr/strings.xml b/DeviceLockController/res/values-mr/strings.xml
index 0847a14..fb300bf 100644
--- a/DeviceLockController/res/values-mr/strings.xml
+++ b/DeviceLockController/res/values-mr/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> कडून आलेल्या कोणत्याही लॉक किंवा अनलॉक विनंत्या"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ॲप उपलब्ध नसल्यास"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"मुक्त स्रोत परवाने"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"सेटिंग्ज &gt; सुरक्षा &gt; व्यवस्थापित डिव्हाइसशी संबंधित माहिती"</b>" मधील इतर व्यवस्थापन क्षमता या डिव्हाइसवर लागू होत नाहीत"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"सुरक्षा सेटिंग्जच्या कर्जावर घेतलेल्या डिव्हाइसच्या विभागातील व्यवस्थापन क्षमता या डिव्हाइसला लागू होत नाहीत."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"हे डिव्हाइस <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> द्वारे पुरवले गेले आहे"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"कियोस्क अ‍ॅप आपोआप डाउनलोड आणि इंस्टॉल केले जाईल"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"या वापरकर्त्यासाठी कियोस्क ॲप इंस्टॉल केले जाईल"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"तुम्ही पेमेंट चुकवल्यास <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> डिव्हाइस प्रतिबंधित करू शकतो"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"तुम्ही एखादे पेमेंट चुकवल्यास, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> डिव्हाइस प्रतिबंधित करू शकते. तपशिलांसाठी, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>अटी आणि नियम<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> पहा."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"तुम्ही आवश्यक पेमेंट न केल्यास <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> डिव्हाइस प्रतिबंधित करू शकतो. तपशिलांसाठी <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>अटी आणि नियम<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> पहा."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"मालकाने पेमेंट न केल्यास, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> डिव्हाइस प्रतिबंधित करू शकतो"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"मदतीसाठी, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> शी संपर्क साधा<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"मागील"</string>
     <string name="next" msgid="8248291863254324326">"पुढील"</string>
     <string name="start" msgid="2842214844667658537">"सुरुवात करा"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"माहिती"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"तरतुदीची माहिती"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"तुमच्या डिव्हाइसची नोंदणी करा"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"तुम्ही आता तुमच्या डिव्हाइसची नोंदणी <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> च्या अर्थविषयक प्रोग्राममध्ये करू शकता"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"तुम्ही आता <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> च्या अर्थविषयक प्रोग्राममध्ये तुमच्या डिव्हाइसची नोंदणी करू शकता"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"तुम्ही आता तुमच्या डिव्हाइसची नोंदणी <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> च्या सबसिडीविषयक प्रोग्राममध्ये करू शकता"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"तुम्ही <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> च्या सबसिडी प्रोग्रामवर आहात"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"डिव्हाइसची नोंदणी"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> या डिव्हाइसवर सेटिंग्ज बदलू शकतो"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"अधिक जाणून घ्या"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"कर्जावर घेतलेल्या डिव्हाइसची माहिती"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"तुमचा क्रेडिट पुरवठादार डिव्हाइसवरील सेटिंग्ज बदलून कियोस्क ॲप इंस्टॉल करू शकतो.\n\nतुम्ही आवश्यक पेमेंट न केल्यास किंवा <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> चे सिम वापरणे थांबवल्यास, <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> हे डिव्हाइस प्रतिबंधित करू शकतो.\n\n अधिक जाणून घेण्यासाठी, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> शी संपर्क साधा."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> हा सेटिंग्ज बदलून डिव्हाइसवर कियोस्क ॲप इंस्टॉल करू शकतो.\n\nतुम्ही एखादे पेमेंट न केल्यास, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> हा तुमचे डिव्हाइस प्रतिबंधित करू शकतो.\n\nअधिक जाणून घेण्यासाठी, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> शी संपर्क साधा."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> हा सेटिंग्ज बदलून डिव्हाइसवर कियोस्क ॲप इंस्टॉल करू शकतो.\n\nतुम्ही एखादे पेमेंट न केल्यास किंवा <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> चे सिम वापरणे थांबवल्यास, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> हा हे डिव्हाइस प्रतिबंधितदेखील करू शकतो.\n\nअधिक जाणून घेण्यासाठी, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> शी संपर्क साधा."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"तुम्ही डिव्हाइससाठी पैसे देईपर्यंत पुढील गोष्टी करू शकत नाही:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"तुमचे डिव्हाइस सुरक्षित मोडमध्ये रीबूट करा"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"तारीख, वेळ आणि टाइम झोन बदला"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"डेव्हलपर पर्याय वापरणे"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"डिव्हाइससह काही चुकीचे झाल्यास, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> पुढील गोष्टी करू शकते:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"तुम्ही <xliff:g id="KIOSK_APP">%1$s</xliff:g> अ‍ॅप अनइंस्टॉल करू शकता"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"मदत मिळवण्यासाठी:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> शी संपर्क साधा<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"तरतूद"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{डिव्हाइस १ दिवसात रीसेट होईल}other{डिव्हाइस # दिवसांत रीसेट होईल}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"डिव्हाइस <xliff:g id="TIMER">%s</xliff:g> मध्ये रीसेट होईल"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"सर्व डिव्हाइस डेटा हटवला जाईल. तुमच्या डिव्हाइसची नोंदणी करण्यात मदतीसाठी, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> शी संपर्क साधा"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"कृपया डिव्हाइसची नोंदणी पुढे ढकलणे सुरू ठेवण्यासाठी DeviceLock कडील सूचनेला अनुमती द्या."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"आर्थिक तरतूद करता आली नाही"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"तुमच्या भांडवल पुरवणाऱ्या व्यक्तीशी संपर्क साधण्याच्या मार्गांसाठी येथे क्लिक करा. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>अधिक जाणून घ्या<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"बाहेर पडा"</string>
+    <string name="retry" msgid="7497287909193345356">"पुन्हा प्रयत्न करा"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ms/strings.xml b/DeviceLockController/res/values-ms/strings.xml
index 2d030a1..d01ec02 100644
--- a/DeviceLockController/res/values-ms/strings.xml
+++ b/DeviceLockController/res/values-ms/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Sebarang permintaan kunci atau buka kunci daripada <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Jika apl <xliff:g id="CREDITOR_APP">%1$s</xliff:g> tidak tersedia"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Lesen sumber terbuka"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Keupayaan pengurusan yang lain dalam "<b>"Tetapan &gt; Keselamatan &gt; Maklumat peranti terurus"</b>" tiada kaitan dengan peranti ini"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Keupayaan pengurusan dalam bahagian peranti dibiayai pada tetapan Keselamatan tiada kaitan dengan peranti ini."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Peranti ini disediakan oleh <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Apl Kios akan dimuat turun dan dipasang secara automatik"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Apl Kios akan dipasang untuk pengguna ini"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> boleh mengehadkan peranti ini jika bayaran anda tertunggak"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> boleh mengehadkan peranti ini jika bayaran anda tertunggak. Untuk mendapatkan butiran, lihat <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Terma &amp; Syarat<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> boleh mengehadkan peranti ini jika anda tidak membuat pembayaran yang diperlukan. Untuk mendapatkan butiran, lihat <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Terma &amp; Syarat<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> boleh mengehadkan peranti ini jika pemilik tidak membuat pembayaran"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Untuk mendapatkan bantuan, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>hubungi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Sebelumnya"</string>
     <string name="next" msgid="8248291863254324326">"Seterusnya"</string>
     <string name="start" msgid="2842214844667658537">"Mula"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Maklumat"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Maklumat peruntukan"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Daftarkan peranti anda"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Kini anda boleh mendaftarkan peranti anda dalam program pembiayaan <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Kini anda boleh mendaftarkan peranti anda dalam program kewangan <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Kini anda boleh mendaftarkan peranti anda dalam program subsidi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Anda menyertai program subsidi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Pendaftaran peranti"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> boleh menukar tetapan pada peranti ini"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Ketahui lebih lanjut"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Maklumat peranti yang dibiayai"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Pembekal kredit anda boleh mengubah tetapan dan memasang apl Kios pada peranti.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> boleh mengehadkan peranti ini jika anda tidak membuat pembayaran yang diperlukan atau berhenti menggunakan SIM <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nUntuk mengetahui lebih lanjut, hubungi <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> boleh menukar tetapan dan memasang apl Kios pada peranti.\n\nJika anda tidak membuat pembayaran, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> boleh mengehadkan peranti anda.\n\nUntuk mengetahui lebih lanjut, hubungi <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> boleh menukar tetapan dan memasang apl Kios pada peranti.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> juga boleh mengehadkan peranti ini jika anda tidak membuat pembayaran atau berhenti menggunakan SIM <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nUntuk mengetahui lebih lanjut, hubungi <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Selagi anda tidak membuat pembayaran untuk peranti, anda tidak boleh:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Melakukan but semula peranti anda dalam mod selamat"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Menukar tarikh, masa dan zon waktu"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Menggunakan pilihan pembangun"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Jika peranti anda bermasalah, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> boleh:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Anda boleh menyahpasang apl <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Untuk mendapatkan bantuan:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Hubungi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Peruntukan"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Peranti akan ditetapkan semula dalam masa 1 hari}other{Peranti akan ditetapkan semula dalam masa # hari}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Peranti akan ditetapkan semula dalam masa <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Semua data peranti akan dipadamkan. Untuk mendapatkan bantuan berkenaan dengan pendaftaran peranti anda, hubungi <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Sila benarkan pemberitahuan daripada DeviceLock untuk terus menangguhkan pendaftaran peranti."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Peruntukan pembiayaan telah gagal"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Sila klik di sini untuk mengetahui cara menghubungi pembiaya anda. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Ketahui lebih lanjut<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Keluar"</string>
+    <string name="retry" msgid="7497287909193345356">"Cuba lagi"</string>
 </resources>
diff --git a/DeviceLockController/res/values-my/strings.xml b/DeviceLockController/res/values-my/strings.xml
index 46f8193..df05c6e 100644
--- a/DeviceLockController/res/values-my/strings.xml
+++ b/DeviceLockController/res/values-my/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> မှ လော့ခ်ချခြင်း (သို့) လော့ခ်ဖွင့်ခြင်းဆိုင်ရာ တောင်းဆိုချက်များ"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> အက်ပ်ကို မရနိုင်ပါက"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"အခမဲ့ရင်းမြစ် လိုင်စင်များ"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"ဆက်တင်များ &gt; လုံခြုံရေး &gt; စီမံထားသော စက်ပစ္စည်း အချက်အလက်"</b>" ရှိ အခြားသော စီမံခန့်ခွဲမှုဆိုင်ရာ စွမ်းဆောင်ရည်များသည် ဤစက်အတွက် အကျုံးမဝင်ပါ"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"‘လုံခြုံရေး ဆက်တင်များ’ ၏ အရစ်ကျပေးချေဆဲ စက်အပိုင်းရှိ စီမံခန့်ခွဲမှုဆိုင်ရာ စွမ်းဆောင်ရည်များသည် ဤစက်အတွက် အကျုံးမဝင်ပါ။"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"ဤစက်ပစ္စည်းကို <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> က ပံ့ပိုးထားသည်"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk app ကို ဒေါင်းလုဒ်လုပ်ပြီး အလိုအလျောက် ထည့်သွင်းပါမည်"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kiosk app ကို ဤအသုံးပြုသူအတွက် ထည့်သွင်းပါမည်"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"ငွေပေးချေရန် ပျက်ကွက်ပါက <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> သည် ဤစက်ကို ကန့်သတ်နိုင်သည်"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"ငွေပေးချေမှု မပြုမိပါက <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> သည် ဤစက်ကို ကန့်သတ်နိုင်သည်။ အသေးစိတ်ကို <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ဝန်ဆောင်မှုစည်းမျဉ်းများ<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> တွင် ကြည့်ပါ။"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"လိုအပ်သော ငွေပေးချေမှုများ မပြုလုပ်ပါက <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> သည် ဤစက်ကို ကန့်သတ်နိုင်သည်။ အသေးစိတ်ကို <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ဝန်ဆောင်မှုစည်းမျဉ်းများ<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> တွင် ကြည့်ပါ။"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"ပိုင်ရှင်သည် ငွေပေးချေမှု မပြုလုပ်ပါက <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> သည် ဤစက်ကို ကန့်သတ်နိုင်သည်"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"အကူအညီအတွက် <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ကို ဆက်သွယ်နိုင်သည်<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>။"</string>
     <string name="previous" msgid="5241891780917802570">"ယခင်"</string>
     <string name="next" msgid="8248291863254324326">"ရှေ့သို့"</string>
     <string name="start" msgid="2842214844667658537">"စတင်ရန်"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"အချက်အလက်"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"ပံ့ပိုးမှု အချက်အလက်"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"သင့်စက်ကို စာရင်းသွင်းခြင်း"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"သင့်စက်ကို <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ၏ ငွေကြေးဆိုင်ရာ ပရိုဂရမ်တွင် စာရင်းသွင်းနိုင်ပါပြီ"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"သင့်စက်ကို <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ၏ ငွေကြေးဆိုင်ရာ အစီအစဉ်တွင် ယခု စာရင်းသွင်းနိုင်ပါပြီ"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"သင့်စက်ကို <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ထောက်ပံ့အစီအစဉ်တွင် စာရင်းသွင်းနိုင်ပါပြီ"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"သင်သည် <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ထောက်ပံ့အစီအစဉ်ကို သုံးနေသည်"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"စက်ပစ္စည်း စာရင်းသွင်းခြင်း"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> သည် ဤစက်တွင် ဆက်တင်များကို ပြောင်းနိုင်သည်"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"ပိုမိုလေ့လာရန်"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"အရစ်ကျပေးချေဆဲ စက်၏အချက်အလက်"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"သင်၏ ခရက်ဒစ် ဝန်ဆောင်မှုပေးသူသည် ဤစက်တွင် ဆက်တင်များပြောင်းလဲပြီး Kiosk app ထည့်သွင်းနိုင်သည်။\n\nသင်သည် လိုအပ်သော ငွေပေးချေများ မပြုလုပ်ပါက (သို့) <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ၏ ဆင်းမ်ကတ် အသုံးပြုခြင်းကို ရပ်လိုက်ပါက <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> သည် ဤစက်ကို ကန့်သတ်နိုင်သည်။\n\nပိုမိုလေ့လာရန် <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ကို ဆက်သွယ်နိုင်သည်။"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> သည် ဤစက်တွင် ဆက်တင်များပြောင်းနိုင်ပြီး Kiosk app ထည့်သွင်းနိုင်သည်။\n\nငွေပေးချေမှု မပြုလုပ်ပါက <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> သည် သင့်စက်ကို ကန့်သတ်နိုင်သည်။\n\nပိုမိုလေ့လာရန် <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ကို ဆက်သွယ်နိုင်သည်။"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> သည် ဤစက်တွင် ဆက်တင်များပြောင်းနိုင်ပြီး Kiosk app ထည့်သွင်းနိုင်သည်။\n\nငွေပေးချေမှု မပြုလုပ်ပါက (သို့) <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ၏ ဆင်းမ်ကတ်ကို မသုံးတော့ပါက <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> သည် ဤစက်ကိုလည်း ကန့်သတ်နိုင်သည်။\n\nပိုမိုလေ့လာရန် <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> ကို ဆက်သွယ်နိုင်သည်။"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"စက်အတွက် ပေးချေမှုမပြီးမချင်း ဖော်ပြပါတို့ကို မလုပ်နိုင်ပါ-"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"စက်ကို အန္တရာယ်ကင်းမှု စနစ်သို့သွားရန် ပြန်လည်စတင်ပါ"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"ရက်စွဲ၊ အချိန်နှင့် ဒေသစံတော်ချိန်များ ပြောင်းခြင်း"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ဆော့ဖ်ဝဲရေးသူအတွက် ရွေးစရာများကို သုံးပါ"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"သင့်စက် တစ်ခုခုဖြစ်ပါက <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> လုပ်နိုင်သည်မှာ-"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> အက်ပ်ကို ပရိုဂရမ်ဖယ်ရှားနိုင်သည်"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"အကူအညီရယူရန်-"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ကို ဆက်သွယ်ရန်<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"ပံ့ပိုးမှု"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{စက်ကို ၁ ရက်အကြာတွင် ပြင်ဆင်သတ်မှတ်မည်}other{စက်ကို # ရက်အကြာတွင် ပြင်ဆင်သတ်မှတ်မည်}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"စက်ကို <xliff:g id="TIMER">%s</xliff:g> အကြာတွင် ပြင်ဆင်သတ်မှတ်မည်"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"စက်ဒေတာအားလုံးကို ဖျက်ပါမည်။ သင့်စက်ကို စာရင်းသွင်းရာတွင် အကူအညီယူရန် <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ကို ဆက်သွယ်ပါ"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"စက်၏ စာရင်းသွင်းမှုကို ဆက်လက်ရွှေ့ဆိုင်းထားရန် DeviceLock မှ အကြောင်းကြားချက်ကို ခွင့်ပြုပါ။"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ငွေကြေးပံ့ပိုးမှု မအောင်မြင်ပါ"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"သင့်ငွေရှင်ကို ဆက်သွယ်ရန် နည်းလမ်းများအတွက် ဤနေရာကို နှိပ်ပါ။ <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>ပိုမိုလေ့လာရန်<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"ထွက်ရန်"</string>
+    <string name="retry" msgid="7497287909193345356">"ထပ်စမ်းရန်"</string>
 </resources>
diff --git a/DeviceLockController/res/values-nb/strings.xml b/DeviceLockController/res/values-nb/strings.xml
index 8db76de..f56c5db 100644
--- a/DeviceLockController/res/values-nb/strings.xml
+++ b/DeviceLockController/res/values-nb/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Alle forespørsler om å låse eller låse opp fra <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Hvis <xliff:g id="CREDITOR_APP">%1$s</xliff:g>-appen ikke er tilgjengelig"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Lisenser for åpen kildekode"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"De andre funksjonene for administrering i "<b>"Innstillinger &gt; Sikkerhet &gt; Informasjon om administrert enhet"</b>" gjelder ikke for denne enheten"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Funksjonene for administrering i delen om finansiert enhet i Sikkerhet-innstillingene gjelder ikke for denne enheten."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Denne enheten leveres av <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kioskappen lastes ned og installeres automatisk"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kioskappen installeres for denne brukeren"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begrense denne enheten hvis du hopper over en betaling"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begrense enheten hvis du hopper over en betaling. Du finner mer informasjon i <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>vilkårene<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begrense denne enheten hvis du ikke betaler det du skal. Du finner mer informasjon i <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>vilkårene<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begrense denne enheten hvis eieren ikke betaler"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Hvis du trenger hjelp, kan du <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>kontakte <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Forrige"</string>
     <string name="next" msgid="8248291863254324326">"Neste"</string>
     <string name="start" msgid="2842214844667658537">"Start"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informasjon"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Provisjoneringsinfo"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Registrer enheten din"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Nå kan du registrere enheten din i finansieringsprogrammet til <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Nå kan du registrere enheten din i finansieringsordningen til <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Nå kan du registrere enheten din i subsidieringsprogrammet til <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Du er med i subsidieringsprogrammet til <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Registrering av enheten"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan endre innstillingene på denne enheten"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Finn ut mer"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informasjon om den finansierte enheten"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Kredittleverandøren din kan endre innstillinger og installere kioskappen på enheten.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan begrense denne enheten hvis du ikke betaler det du skal, eller hvis du slutter å bruke SIM-kortet fra <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nFor å finne ut mer, kontakt <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan endre innstillinger og installere kioskappen på enheten.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kan begrense enheten hvis du ikke betaler avdragene.\n\nFor å finne ut mer, kontakt <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan endre innstillinger og installere kioskappen på enheten.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kan også begrense denne enheten hvis du ikke betaler avdragene, eller hvis du slutter å bruke SIM-kortet fra <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nFor å finne ut mer, kontakt <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Til du har betalt for enheten, kan du ikke"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"starte enheten din på nytt i sikker modus"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"endre dato, klokkeslett og tidssoner"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"bruke utvikleralternativer"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Hvis noe går galt med enheten din, kan <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Du kan avinstallere <xliff:g id="KIOSK_APP">%1$s</xliff:g>-appen"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Slik får du hjelp:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontakt <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provisjonering"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Enheten tilbakestilles om 1 dag}other{Enheten tilbakestilles om # dager}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Enheten tilbakestilles om <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Alle enhetsdata slettes. Hvis du trenger hjelp med å registrere enheten din, bør du kontakte <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Du må tillate varsler fra DeviceLock for å fortsette å utsette registreringen av enheten."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Kunne ikke provisjonere finansiering"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Klikk her for å finne måter å kontakte finansieringsløsningen din på. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Finn ut mer<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Avslutt"</string>
+    <string name="retry" msgid="7497287909193345356">"Prøv på nytt"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ne/strings.xml b/DeviceLockController/res/values-ne/strings.xml
index b069f94..458a363 100644
--- a/DeviceLockController/res/values-ne/strings.xml
+++ b/DeviceLockController/res/values-ne/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ले गर्ने लक वा अनलकसम्बन्धी सबै अनुरोधहरू"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> एप उपलब्ध छ कि छैन भन्ने कुरा"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"खुला स्रोतका लाइसेन्सहरू"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"सेटिङ &gt; सुरक्षा &gt; व्यवस्थापन गरिएको डिभाइससम्बन्धी जानकारी"</b>" मा भएका व्यवस्थापनसम्बन्धी अन्य सुविधाहरू यो डिभाइसमा लागू हुँदैनन्"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"सुरक्षासम्बन्धी सेटिङअन्तर्गतको \"किस्तामा खरिद गरिएको डिभाइस\" नामक खण्डमा भएका व्यवस्थापनसम्बन्धी सुविधाहरू यो डिभाइसमा लागू हुँदैनन्।"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ले यो डिभाइस उपलब्ध गराएको हो"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"किअस्क एप स्वतः डाउनलोड गरी इन्स्टल गरिने छ"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"यी प्रयोगकर्ताका लागि किअस्क एप इन्स्टल गरिने छ"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"तपाईंले रकम भुक्तानी गर्नुभएन भने <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ले यो डिभाइसमाथि प्रतिबन्ध लगाउन सक्छ"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"तपाईंले समयमै रकम भुक्तानी गर्नुभएन भने <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ले डिभाइसमाथि प्रतिबन्ध लगाउन सक्छन्। विवरणहरू प्राप्त गर्न <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>सेवाका सर्तहरू<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> हेर्नुहोस्।"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"तपाईंले तिर्नु पर्ने रकम भुक्तानी गर्नुभएन भने <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ले यो डिभाइसमाथि प्रतिबन्ध लगाउन सक्छ। विवरणहरू प्राप्त गर्न <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>सेवाका सर्तहरू<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> हेर्नुहोस्।"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"डिभाइसको मालिकले रकम भुक्तानी गर्नुभएन भने <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ले यो डिभाइसमाथि प्रतिबन्ध लगाउन सक्छ"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"मद्दत प्राप्त गर्न <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> मा सम्पर्क गर्नुहोस्<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>।"</string>
     <string name="previous" msgid="5241891780917802570">"अघिल्लो"</string>
     <string name="next" msgid="8248291863254324326">"अर्को"</string>
     <string name="start" msgid="2842214844667658537">"सुरु गर्नुहोस्"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"जानकारी"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"प्रावधानसम्बन्धी जानकारी"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"आफ्नो डिभाइस दर्ता गर्नुहोस्"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"तपाईं अब आफ्नो डिभाइस <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> को किस्ताबन्दी कार्यक्रममा दर्ता गर्न सक्नुहुन्छ"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"तपाईं अब आफ्नो डिभाइस <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> को किस्ताबन्दी कार्यक्रममा दर्ता गर्न सक्नुहुन्छ"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"तपाईं अब आफ्नो डिभाइस <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> को सहुलियत कार्यक्रममा दर्ता गर्न सक्नुहुन्छ"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"तपाईं <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> को सहुलियत कार्यक्रममा सामेल हुनुभएको छ"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"डिभाइस दर्ता गर्ने प्रक्रिया"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> यो डिभाइसका सेटिङ बदल्न सक्नुहुन्छ"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"थप जान्नुहोस्"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"किस्तामा खरिद गरिएको डिभाइससम्बन्धी जानकारी"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"तपाईंका क्रेडिट प्रदायक यो डिभाइसमा सेटिङ बदल्न र किअस्क एप इन्स्टल गर्न सक्छ।\n\nतपाईंले तिर्नु पर्ने रकम भुक्तानी गर्नुभएन वा <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> को SIM चलाउन छाड्नुभएन भने <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ले यो डिभाइसमाथि प्रतिबन्ध लगाउन सक्छ।\n\nथप जान्न <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> लाई सम्पर्क गर्नुहोस्।"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> यो डिभाइसका सेटिङ बदल्न र यसमा किअस्क एप इन्स्टल गर्न सक्छ।\n\nतपाईंले समयमै भुक्तानी गर्नुभएन भने <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ले तपाईंको डिभाइसमाथि प्रतिबन्ध लगाउन सक्छ।\n\nथप जान्न <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> लाई सम्पर्क गर्नुहोस्।"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> यो डिभाइसका सेटिङ बदल्न र यसमा किअस्क एप इन्स्टल गर्न सक्छ।\n\nतपाईंले समयमै भुक्तानी गर्नुभएन वा <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> को SIM चलाउन छाड्नुभयो भने <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ले यो डिभाइसमाथि प्रतिबन्ध लगाउन पनि सक्छ।\n\nथप जान्न <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> लाई सम्पर्क गर्नुहोस्।"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"तपाईंले डिभाइसको किस्ता वा सहुलियत भुक्तानी नगरेसम्म तपाईं निम्न कार्य गर्न सक्नुहुन्न:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"आफ्नो डिभाइस रिबुट गरेर सेफ मोडमा लैजान"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"मिति, समय र प्रामाणिक समय बदल्न"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"विकासकर्ता मोड प्रयोग गर्न"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"तपाईंको डिभाइसमा कुनै समस्या आएका खण्डमा <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ले निम्न कार्यहरू गर्न सक्छ:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"तपाईं <xliff:g id="KIOSK_APP">%1$s</xliff:g> एप अनइन्स्टल गर्न सक्नुहुन्छ"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"सहायता प्राप्त गर्नका निम्ति:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> मा सम्पर्क गर्नुहोस्<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"प्रावधान"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{डिभाइस १ दिनपछि रिसेट हुने छ}other{डिभाइस # दिनपछि रिसेट हुने छ}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"डिभाइस <xliff:g id="TIMER">%s</xliff:g> पछि रिसेट हुने छ"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"डिभाइसमा रहेका सबै डेटा मेटाइने छ। आफ्नो डिभाइस दर्ता गर्न <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> मा सम्पर्क गर्नुहोस्"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"डिभाइस दर्ता गर्ने प्रक्रिया स्थगन गरिराख्न कृपया DeviceLock बाट सूचना प्राप्त गर्ने सुविधा अन गर्नुहोस्।"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"किस्तामा भुक्तानी गर्ने प्रावधान प्राप्त गर्न सकिएन"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"किस्तामा भुक्तानी गर्ने सुविधा प्रदायकलाई सम्पर्क गर्ने तरिकाहरूका बारेमा जान्न कृपया यहाँ क्लिक गर्नुहोस्। <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>थप जान्नुहोस्<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"बाहिरिनुहोस्"</string>
+    <string name="retry" msgid="7497287909193345356">"फेरि प्रयास गर्नु…"</string>
 </resources>
diff --git a/DeviceLockController/res/values-nl/strings.xml b/DeviceLockController/res/values-nl/strings.xml
index c1a318f..0ecd4d3 100644
--- a/DeviceLockController/res/values-nl/strings.xml
+++ b/DeviceLockController/res/values-nl/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Alle vergrendelings- of ontgrendelingsverzoeken van <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Als de <xliff:g id="CREDITOR_APP">%1$s</xliff:g>-app niet beschikbaar is"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Opensource-licenties"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"De andere beheermogelijkheden in "<b>"Instellingen &gt; Beveiliging &gt; Informatie over beheerd apparaat"</b>" zijn niet van toepassing op dit apparaat"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"De beheermogelijkheden in het gedeelte voor gefinancierde apparaten van de beveiligingsinstellingen zijn niet van toepassing op dit apparaat."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Dit apparaat wordt geleverd door <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"De kiosk-app wordt automatisch gedownload en geïnstalleerd"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"De Kiosk-app wordt geïnstalleerd voor deze gebruiker"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan dit apparaat beperken als je een betaling mist"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan het apparaat beperken als je een betaling mist. Bekijk voor meer informatie de <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Algemene Voorwaarden<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan dit apparaat beperken als je de nodige betalingen niet doet. Bekijk voor meer informatie de <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Algemene Voorwaarden<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan dit apparaat beperken als de eigenaar geen betalingen doet"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Als je hulp nodig hebt, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>neem je contact op met <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Vorige"</string>
     <string name="next" msgid="8248291863254324326">"Volgende"</string>
     <string name="start" msgid="2842214844667658537">"Starten"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Info"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Registratie-info"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Je apparaat inschrijven"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Je kunt je apparaat nu inschrijven voor het financieringsprogramma van <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Je kunt je apparaat nu inschrijven voor het financieringsprogramma van <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Je kunt je apparaat nu inschrijven voor het subsidieprogramma van <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Je neemt deel aan het subsidieprogramma van <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Apparaatinschrijving"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan instellingen op dit apparaat wijzigen"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Meer informatie"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informatie over gefinancierd apparaat"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Je kredietverstrekker kan instellingen wijzigen en de Kiosk-app installeren op het apparaat.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan dit apparaat beperken als je de nodige betalingen niet doet of stopt met het gebruik van de simkaart van <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nNeem voor meer informatie contact op met <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan instellingen wijzigen en de Kiosk-app installeren op het apparaat.\n\nAls je een betaling mist, kan <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> je apparaat beperken.\n\nNeem voor meer informatie contact op met <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan instellingen wijzigen en de Kiosk-app installeren op het apparaat.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kan dit apparaat ook beperken als je een betaling mist of stopt met het gebruik van de simkaart van <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nNeem voor meer informatie contact op met <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Je kunt het volgende niet doen totdat je hebt betaald:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Je apparaat opnieuw opstarten in de veilige modus"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Datum, tijd en tijdzones wijzigen"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Ontwikkelaarsopties gebruiken"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Als er iets misgaat met je apparaat, kan <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Je kunt de <xliff:g id="KIOSK_APP">%1$s</xliff:g>-app verwijderen"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Als je hulp nodig hebt:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contact opnemen met <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Registratie"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Apparaat wordt over 1 dag gereset}other{Apparaat wordt over # dagen gereset}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Apparaat wordt gereset over <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Alle apparaatgegevens worden verwijderd. Neem contact op met <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> voor hulp bij de inschrijving van je apparaat."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Sta meldingen van DeviceLock toe om de inschrijving van het apparaat te kunnen uitstellen."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Financieringsregistratie is mislukt"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Klik hier voor manieren om contact op te nemen met de financierder. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Meer informatie<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Sluiten"</string>
+    <string name="retry" msgid="7497287909193345356">"Opnieuw proberen"</string>
 </resources>
diff --git a/DeviceLockController/res/values-or/strings.xml b/DeviceLockController/res/values-or/strings.xml
index 40eea81..08b69e2 100644
--- a/DeviceLockController/res/values-or/strings.xml
+++ b/DeviceLockController/res/values-or/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>ରୁ କୌଣସି ଲକ କିମ୍ବା ଅନଲକ କରିବାର ଅନୁରୋଧ"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"ଯଦି <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ଆପ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ଓପନ-ସୋର୍ସ ଲାଇସେନ୍ସଗୁଡ଼ିକ"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"ସେଟିଂସ &gt; ସୁରକ୍ଷା &gt; ପରିଚାଳିତ ଡିଭାଇସ ସୂଚନା"</b>"ରେ ଅନ୍ୟ ପରିଚାଳନା କ୍ଷମତାଗୁଡ଼ିକ ଏହି ଡିଭାଇସରେ ଲାଗୁ ହୁଏ ନାହିଁ"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"ସୁରକ୍ଷା ସେଟିଂସର ଫାଇନାନ୍ସଡ୍ ଡିଭାଇସ୍ ବିଭାଗରେ ଥିବା ପରିଚାଳନା ଦକ୍ଷତା ଏହି ଡିଭାଇସରେ ଲାଗୁ ହୁଏ ନାହିଁ।"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"ଏହି ଡିଭାଇସ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ଦ୍ୱାରା ପ୍ରଦାନ କରାଯାଇଛି"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk ଆପ ସ୍ୱତଃ ଡାଉନଲୋଡ ଏବଂ ଇନଷ୍ଟଲ ହେବ"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"ଏହି ୟୁଜରଙ୍କ ପାଇଁ Kiosk ଆପକୁ ଇନଷ୍ଟଲ କରାଯିବ"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"ଯଦି ଆପଣ କୌଣସି ପେମେଣ୍ଟ ମିସ କରନ୍ତି ତେବେ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ଏହି ଡିଭାଇସକୁ ପ୍ରତିବନ୍ଧିତ କରିପାରିବ"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"ଯଦି ଆପଣ କୌଣସି ପେମେଣ୍ଟ ମିସ କରନ୍ତି ତେବେ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ଡିଭାଇସକୁ ପ୍ରତିବନ୍ଧିତ କରିପାରିବ। ବିବରଣୀ ପାଇଁ, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ଚୁକ୍ତି ଏବଂ ସର୍ତ୍ତାବଳୀ <xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> ଭ୍ୟୁ କରନ୍ତୁ।"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"ଯଦି ଆପଣ ଆବଶ୍ୟକୀୟ ପେମେଣ୍ଟ ନକରନ୍ତି ତେବେ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ଏହି ଡିଭାଇସକୁ ପ୍ରତିବନ୍ଧିତ କରିପାରିବ। ବିବରଣୀ ପାଇଁ, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ଚୁକ୍ତି ଏବଂ ସର୍ତ୍ତାବଳୀ <xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> ଭ୍ୟୁ କରନ୍ତୁ।"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"ଯଦି ମାଲିକ ପେମେଣ୍ଟ ନକରନ୍ତି ତେବେ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ଏହି ଡିଭାଇସକୁ ପ୍ରତିବନ୍ଧିତ କରିପାରିବ"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"ସହାୟତା ପାଇଁ <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>।"</string>
     <string name="previous" msgid="5241891780917802570">"ପୂର୍ବବର୍ତ୍ତୀ"</string>
     <string name="next" msgid="8248291863254324326">"ପରବର୍ତ୍ତୀ"</string>
     <string name="start" msgid="2842214844667658537">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"ସୂଚନା"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"ବ୍ୟବସ୍ଥା ସୂଚନା"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"ଆପଣଙ୍କ ଡିଭାଇସକୁ ପଞ୍ଜିକରଣ କରନ୍ତୁ"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"ଆପଣ ବର୍ତ୍ତମାନ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ର ଫାଇନାନ୍ସିଂ ପ୍ରୋଗ୍ରାମରେ ଆପଣଙ୍କ ଡିଭାଇସକୁ ପଞ୍ଜିକରଣ କରିପାରିବେ"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"ଆପଣ ବର୍ତ୍ତମାନ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ର ଫାଇନାନ୍ସ ପ୍ରୋଗ୍ରାମରେ ଆପଣଙ୍କ ଡିଭାଇସକୁ ପଞ୍ଜିକରଣ କରିପାରିବେ"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"ଆପଣ ବର୍ତ୍ତମାନ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ର ସବସିଡି ପ୍ରୋଗ୍ରାମରେ ଆପଣଙ୍କ ଡିଭାଇସକୁ ପଞ୍ଜିକରଣ କରିପାରିବେ"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"ଆପଣ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ର ସବସିଡି ପ୍ରୋଗ୍ରାମରେ ଅଛନ୍ତି"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ଡିଭାଇସର ପଞ୍ଜିକରଣ"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ଏହି ଡିଭାଇସର ସେଟିଂସକୁ ପରିବର୍ତ୍ତନ କରିପାରିବେ"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ଫାଇନାନ୍ସଡ୍ ଡିଭାଇସ୍ ସୂଚନା"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"ଆପଣଙ୍କ କ୍ରେଡିଟ ପ୍ରଦାନକାରୀ ଡିଭାଇସରେ ସେଟିଂସ ପରିବର୍ତ୍ତନ କରି Kiosk ଆପ ଇନଷ୍ଟଲ କରିପାରିବେ।\n\nଯଦି ଆପଣ ଆବଶ୍ୟକୀୟ ପେମେଣ୍ଟ ନକରନ୍ତି କିମ୍ବା <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>ର SIM ବ୍ୟବହାର କରିବା ବନ୍ଦ କରନ୍ତି ତେବେ <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ଏହି ଡିଭାଇସକୁ ପ୍ରତିବନ୍ଧିତ କରିପାରେ।\n\nଅଧିକ ଜାଣିବା ପାଇଁ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ଡିଭାଇସରେ ସେଟିଂସ ପରିବର୍ତ୍ତନ କରି Kiosk ଆପ ଇନଷ୍ଟଲ କରିପାରିବ।\n\nଯଦି ଆପଣ କୌଣସି ପେମେଣ୍ଟ ମିସ କରନ୍ତି, ତେବେ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ଆପଣଙ୍କ ଡିଭାଇସକୁ ପ୍ରତିବନ୍ଧିତ କରିପାରିବ।\n\nଅଧିକ ଜାଣିବା ପାଇଁ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ଡିଭାଇସରେ ସେଟିଂସ ପରିବର୍ତ୍ତନ କରି Kiosk ଆପ ଇନଷ୍ଟଲ କରିପାରିବ।\n\nଯଦି ଆପଣ କୌଣସି ପେମେଣ୍ଟ ମିସ କରନ୍ତି କିମ୍ବା <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>ର SIM ବ୍ୟବହାର କରିବା ବନ୍ଦ କରନ୍ତି, ତେବେ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ଏହି ଡିଭାଇସକୁ ପ୍ରତିବନ୍ଧିତ ମଧ୍ୟ କରିପାରିବ।\n\nଅଧିକ ଜାଣିବା ପାଇଁ <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"ଆପଣ ଡିଭାଇସ ପାଇଁ ପେମେଣ୍ଟ ନକରିବା ଯାଏଁ ଏସବୁ କରିପାରିବେ ନାହିଁ:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"ଆପଣଙ୍କ ଡିଭାଇସକୁ ସୁରକ୍ଷିତ ମୋଡରେ ରିବୁଟ କରନ୍ତୁ"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"ତାରିଖ, ସମୟ ଏବଂ ଟାଇମ ଜୋନଗୁଡ଼ିକୁ ବଦଳାନ୍ତୁ"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ଡେଭେଲପର ବିକଳ୍ପଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିପାରିବ"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"ଯଦି ଡିଭାଇସରେ କିଛି ତ୍ରୁଟି ହୁଏ, ତେବେ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"ଆପଣ <xliff:g id="KIOSK_APP">%1$s</xliff:g> ଆପକୁ ଅନଇନଷ୍ଟଲ କରିପାରିବେ"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"ସାହାଯ୍ୟ ପାଇବାକୁ:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"ବ୍ୟବସ୍ଥା"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{ଡିଭାଇସ 1 ଦିନରେ ରିସେଟ ହେବ}other{ଡିଭାଇସ # ଦିନରେ ରିସେଟ ହେବ}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"ଡିଭାଇସ <xliff:g id="TIMER">%s</xliff:g>ରେ ରିସେଟ ହେବ"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ସମସ୍ତ ଡିଭାଇସ ଡାଟା ଡିଲିଟ ହୋଇଯିବ। ଆପଣଙ୍କ ଡିଭାଇସକୁ ପଞ୍ଜିକରଣ କରିବାରେ ସହାୟତା ପାଇଁ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"ଡିଭାଇସର ପଞ୍ଜିକରଣ ବିଳମ୍ବ କରିବା ଜାରି ରଖିବା ପାଇଁ ଦୟାକରି DeviceLockରୁ ବିଜ୍ଞପ୍ତିକୁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ଫାଇନାନ୍ସିଂ ବ୍ୟବସ୍ଥା ବିଫଳ ହୋଇଛି"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"ଆପଣଙ୍କ ଫାଇନାନ୍ସର ସହ କଣ୍ଟାକ୍ଟ କରିବାକୁ ଉପାୟଗୁଡ଼ିକ ପାଇଁ ଦୟାକରି ଏଠାରେ କ୍ଲିକ କରନ୍ତୁ। <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>ଅଧିକ ଜାଣନ୍ତୁ<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"ବାହାରି ଯାଆନ୍ତୁ"</string>
+    <string name="retry" msgid="7497287909193345356">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
 </resources>
diff --git a/DeviceLockController/res/values-pa/strings.xml b/DeviceLockController/res/values-pa/strings.xml
index 875ef70..2435f2e 100644
--- a/DeviceLockController/res/values-pa/strings.xml
+++ b/DeviceLockController/res/values-pa/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ਤੋਂ ਲਾਕ ਜਾਂ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕੋਈ ਬੇਨਤੀ"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ਐਪ ਉਪਲਬਧ ਹੈ ਜਾਂ ਨਹੀਂ"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ਖੁੱਲ੍ਹੇ ਸਰੋਤ ਲਾਇਸੰਸ"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"ਇਸ ਡੀਵਾਈਸ \'ਤੇ "<b>"ਸੈਟਿੰਗਾਂ, &amp;gt ਸੁਰੱਖਿਆ, &amp;gt ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਡੀਵਾਈਸ ਬਾਰੇ ਜਾਣਕਾਰੀ"</b>" ਵਿੱਚ ਹੋਰ ਪ੍ਰਬੰਧਨ ਸਮਰੱਥਾਵਾਂ ਲਾਗੂ ਨਹੀਂ ਹੁੰਦੀਆਂ"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"ਸੁਰੱਖਿਆ ਸੈਟਿੰਗਾਂ ਦੇ ਵਿੱਤ ਪ੍ਰਬੰਧਿਤ ਡੀਵਾਈਸ ਸੈਕਸ਼ਨ ਵਿਚਲੀਆਂ ਪ੍ਰਬੰਧਨ ਸਮਰੱਥਾਵਾਂ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਲਾਗੂ ਨਹੀਂ ਹੁੰਦੀਆਂ।"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਮੁਹੱਈਆ ਕਰਵਾਇਆ ਗਿਆ ਹੈ"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"ਕਿਓਸਕ ਐਪ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਡਾਊਨਲੋਡ ਅਤੇ ਸਥਾਪਤ ਹੋ ਜਾਵੇਗੀ"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"ਕਿਓਸਕ ਐਪ ਇਸ ਵਰਤੋਂਕਾਰ ਲਈ ਸਥਾਪਤ ਕੀਤੀ ਜਾਵੇਗੀ"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਕੋਈ ਭੁਗਤਾਨ ਨਾ ਕਰਨ \'ਤੇ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਪ੍ਰਤਿਬੰਧਿਤ ਕਰ ਸਕਦਾ ਹੈ"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"ਜੇ ਤੁਸੀਂ ਭੁਗਤਾਨ ਖੁੰਝਾ ਦਿੰਦੇ ਹੋ, ਤਾਂ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਡੀਵਾਈਸ ਨੂੰ ਪ੍ਰਤਿਬੰਧਿਤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। ਵੇਰਵਿਆਂ ਲਈ, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ਨਿਯਮ ਅਤੇ ਸ਼ਰਤਾਂ<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> ਦੇਖੋ।"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਲੋੜੀਂਦੇ ਭੁਗਤਾਨ ਨਾ ਕਰਨ \'ਤੇ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਪ੍ਰਤਿਬੰਧਿਤ ਕਰ ਸਕਦਾ ਹੈ। ਵੇਰਵਿਆਂ ਲਈ, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ਨਿਯਮ ਅਤੇ ਸ਼ਰਤਾਂ<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> ਦੇਖੋ।"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"ਮਾਲਕ ਵੱਲੋਂ ਭੁਗਤਾਨ ਨਾ ਕਰਨ \'ਤੇ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਪ੍ਰਤਿਬੰਧਿਤ ਕਰ ਸਕਦਾ ਹੈ"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"ਮਦਦ ਲਈ, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਨਾਲ ਸੰਪਰਕ ਕਰੋ<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>।"</string>
     <string name="previous" msgid="5241891780917802570">"ਪਿੱਛੇ"</string>
     <string name="next" msgid="8248291863254324326">"ਅੱਗੇ"</string>
     <string name="start" msgid="2842214844667658537">"ਸ਼ੁਰੂ ਕਰੋ"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"ਜਾਣਕਾਰੀ"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"ਵਿਵਸਥਾ ਜਾਣਕਾਰੀ"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਦਰਜ ਕਰੋ"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"ਤੁਸੀਂ ਹੁਣ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਦੇ ਵਿੱਤ ਪ੍ਰੋਗਰਾਮ ਵਿੱਚ ਆਪਣਾ ਡੀਵਾਈਸ ਦਰਜ ਕਰ ਸਕਦੇ ਹੋ"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"ਤੁਸੀਂ ਹੁਣ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਦੇ ਵਿੱਤ ਪ੍ਰੋਗਰਾਮ ਵਿੱਚ ਆਪਣਾ ਡੀਵਾਈਸ ਦਰਜ ਕਰ ਸਕਦੇ ਹੋ"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"ਤੁਸੀਂ ਹੁਣ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਦੇ ਸਬਸਿਡੀ ਪ੍ਰੋਗਰਾਮ ਵਿੱਚ ਆਪਣਾ ਡੀਵਾਈਸ ਦਰਜ ਕਰ ਸਕਦੇ ਹੋ"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"ਤੁਸੀਂ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਦੇ ਸਬਸਿਡੀ ਪ੍ਰੋਗਰਾਮ \'ਤੇ ਹੋ"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"ਡੀਵਾਈਸ ਦਰਜ ਕਰਨਾ"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬਦਲ ਸਕਦਾ ਹੈ"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"ਹੋਰ ਜਾਣੋ"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ਵਿੱਤ ਪ੍ਰਬੰਧਿਤ ਡੀਵਾਈਸ ਬਾਰੇ ਜਾਣਕਾਰੀ"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"ਤੁਹਾਡਾ ਕ੍ਰੈਡਿਟ ਪ੍ਰਦਾਨਕ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬਦਲ ਕੇ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਕਿਓਸਕ ਐਪ ਸਥਾਪਤ ਕਰ ਸਕਦਾ ਹੈ।\n\n ਜੇ ਤੁਸੀਂ ਲੋੜੀਂਦੇ ਭੁਗਤਾਨ ਨਹੀਂ ਕਰਦੇ ਜਾਂ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ਦੇ ਸਿਮ ਦੀ ਵਰਤੋਂ ਕਰਨਾ ਬੰਦ ਨਹੀਂ ਕਰ ਦਿੰਦੇ ਹੋ, ਤਾਂ <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਪ੍ਰਤਿਬੰਧਿਤ ਕਰ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਨ ਲਈ, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ਵੱਲੋਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬਦਲ ਕੇ ਡੀਵਾਈਸ \'ਤੇ ਕਿਓਸਕ ਐਪ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।\n\nਜੇ ਤੁਸੀਂ ਭੁਗਤਾਨ ਖੁੰਝਾ ਦਿੰਦੇ ਹੋ, ਤਾਂ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ਵੱਲੋਂ ਡੀਵਾਈਸ ਨੂੰ ਪ੍ਰਤਿਬੰਧਿਤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਨ ਲਈ, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ਵੱਲੋਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬਦਲ ਕੇ ਡੀਵਾਈਸ \'ਤੇ ਕਿਓਸਕ ਐਪ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।\n\nਜੇ ਤੁਸੀਂ ਭੁਗਤਾਨ ਖੁੰਝਾ ਦਿੰਦੇ ਹੋ ਜਾਂ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ਦੀ ਸਿਮ ਨੂੰ ਵਰਤਣਾ ਬੰਦ ਕਰ ਦਿੰਦੇ ਹੋ, ਤਾਂ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ਵੱਲੋਂ ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਪ੍ਰਤਿਬੰਧਿਤ ਵੀ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਨ ਲਈ, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"ਆਪਣੇ ਡੀਵਾਈਸ ਦਾ ਭੁਗਤਾਨ ਨਾ ਕੀਤੇ ਜਾਣ ਤੱਕ ਤੁਸੀਂ ਇਹ ਨਹੀਂ ਕਰ ਸਕਦੇ:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਰੀਬੂਟ ਕਰੋ"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"ਤਾਰੀਖ, ਸਮਾਂ ਅਤੇ ਸਮਾਂ ਖੇਤਰ ਬਦਲੋ"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"ਡੀਵਾਈਸ ਨਾਲ ਗੜਬੜ ਹੋਣ \'ਤੇ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਇਹ ਕਰ ਸਕਦਾ ਹੈ:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"ਤੁਸੀਂ <xliff:g id="KIOSK_APP">%1$s</xliff:g> ਐਪ ਨੂੰ ਅਣਸਥਾਪਤ ਕਰ ਸਕਦੇ ਹੋ"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"ਮਦਦ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਨੂੰ ਸੰਪਰਕ ਕਰੋ<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"ਵਿਵਸਥਾ"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{ਡੀਵਾਈਸ 1 ਦਿਨ ਵਿੱਚ ਰੀਸੈੱਟ ਹੋ ਜਾਵੇਗਾ}one{ਡੀਵਾਈਸ # ਦਿਨ ਵਿੱਚ ਰੀਸੈੱਟ ਹੋ ਜਾਵੇਗਾ}other{ਡੀਵਾਈਸ # ਦਿਨਾਂ ਵਿੱਚ ਰੀਸੈੱਟ ਹੋ ਜਾਵੇਗਾ}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"ਡੀਵਾਈਸ <xliff:g id="TIMER">%s</xliff:g> ਵਿੱਚ ਰੀਸੈੱਟ ਹੋ ਜਾਵੇਗਾ"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ਸਾਰੇ ਡੀਵਾਈਸ ਡਾਟੇ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ। ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨੂੰ ਦਰਜ ਕਰਨ ਵਿੱਚ ਮਦਦ ਲਈ, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ਨੂੰ ਸੰਪਰਕ ਕਰੋ"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"ਕਿਰਪਾ ਕਰਕੇ ਡੀਵਾਈਸ ਨੂੰ ਦਰਜ ਕਰਨ ਦੀ ਪ੍ਰਕਿਰਿਆ ਨੂੰ ਮੁਲਤਵੀ ਕਰਨਾ ਜਾਰੀ ਰੱਖਣ ਲਈ, DeviceLock ਤੋਂ ਸੂਚਨਾ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ।"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ਵਿੱਤ ਵਿਵਸਥਾ ਅਸਫਲ ਰਹੀ"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਫਾਈਨੈਂਸਰ ਨਾਲ ਸੰਪਰਕ ਕਰਨ ਦੇ ਤਰੀਕਿਆਂ ਲਈ ਇੱਥੇ ਕਲਿੱਕ ਕਰੋ। <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>ਹੋਰ ਜਾਣੋ<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"ਬਾਹਰ ਜਾਓ"</string>
+    <string name="retry" msgid="7497287909193345356">"ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
 </resources>
diff --git a/DeviceLockController/res/values-pl/strings.xml b/DeviceLockController/res/values-pl/strings.xml
index 15ef24c..4d96f35 100644
--- a/DeviceLockController/res/values-pl/strings.xml
+++ b/DeviceLockController/res/values-pl/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Wszystkie prośby o zablokowanie i odblokowanie z aplikacji <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Jeśli aplikacja <xliff:g id="CREDITOR_APP">%1$s</xliff:g> nie jest dostępna"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licencje typu open source"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Inne możliwości zarządzania w sekcji "<b>"Ustawienia &gt; Bezpieczeństwo &gt; Informacje o urządzeniu zarządzanym"</b>" nie dotyczą tego urządzenia"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Możliwości zarządzania w sekcji finansowanego urządzenia w ustawieniach Bezpieczeństwa nie dotyczą tego urządzenia"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"To urządzenie dostarcza organizacja <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Aplikacja Kiosk zostanie pobrana i zainstalowana automatycznie"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Aplikacja Kiosk zostanie zainstalowana dla tego użytkownika"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> może zablokować to urządzenie, jeśli nie uregulujesz płatności"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Operator <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> może ograniczyć możliwości korzystania z tego urządzenia, jeśli nie uregulujesz płatności. Szczegółowe informacje znajdziesz w <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>warunkach korzystania z usługi<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> może zablokować to urządzenie, jeśli nie dokonasz wymaganych płatności. Szczegółowe informacje znajdziesz w <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>warunkach korzystania z usługi<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> może zablokować to urządzenie, jeśli właściciel nie dokona płatności"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Aby uzyskać pomoc, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>skontaktuj się z firmą <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Wstecz"</string>
     <string name="next" msgid="8248291863254324326">"Dalej"</string>
     <string name="start" msgid="2842214844667658537">"Zarejestruj"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informacje"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Informacje finansowe"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Zarejestruj swoje urządzenie"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Możesz teraz zarejestrować swoje urządzenie w programie finansowania <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Możesz teraz zarejestrować urządzenie w programie finansowania w firmie <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Możesz teraz zarejestrować swoje urządzenie w programie dopłat <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Korzystasz z programu dopłat <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Rejestrowanie urządzenia"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> może zmieniać ustawienia tego urządzenia"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Więcej informacji"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informacje o urządzeniu finansowanym"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Operator udzielający kredytu może zmieniać ustawienia i zainstalować na urządzeniu aplikację Kiosk.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> może zablokować to urządzenie, jeśli nie dokonasz wymaganych płatności lub przestaniesz korzystać z karty SIM <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nAby dowiedzieć się więcej, skontaktuj się z <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> może zmienić ustawienia i zainstalować aplikację kiosku na urządzeniu.\n\nJeśli nie dokonasz płatności, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> może nałożyć ograniczenia na Twoje urządzenie.\n\nAby dowiedzieć się więcej, skontaktuj się z <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> może zmienić ustawienia i zainstalować aplikację kiosku na urządzeniu.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> może także nałożyć ograniczenia na to urządzenie, jeśli nie dokonasz płatności lub przestaniesz używać karty SIM <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nAby dowiedzieć się więcej, skontaktuj się z <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Dopóki nie zapłacisz za swoje urządzenie, nie możesz:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Ponowne uruchamianie urządzenia w trybie awaryjnym"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Zmiana daty, godziny i strefy czasowej"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Korzystanie z opcji dla programistów"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"W razie problemów z urządzeniem, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> może:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Możesz odinstalować aplikację <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Aby uzyskać pomoc:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Skontaktuj się z firmą <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Finansowanie"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Urządzenie zostanie zresetowane za 1 dzień}few{Urządzenie zostanie zresetowane za # dni}many{Urządzenie zostanie zresetowane za # dni}other{Urządzenie zostanie zresetowane za # dnia}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Urządzenie zostanie zresetowane za <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Wszystkie dane z urządzenia zostaną usunięte. Aby uzyskać pomoc w zarejestrowaniu urządzenia, skontaktuj się z <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Zezwól na powiadomienia z DeviceLock, aby nadal odraczać rejestrację urządzenia."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Inicjowanie finansowania nie powiodło się"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Kliknij tutaj, aby dowiedzieć się, jak skontaktować się ze swoim podmiotem finansującym. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Więcej informacji<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Zakończ"</string>
+    <string name="retry" msgid="7497287909193345356">"Ponów"</string>
 </resources>
diff --git a/DeviceLockController/res/values-pt-rPT/strings.xml b/DeviceLockController/res/values-pt-rPT/strings.xml
index 98d335c..c9bfb1a 100644
--- a/DeviceLockController/res/values-pt-rPT/strings.xml
+++ b/DeviceLockController/res/values-pt-rPT/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Qualquer pedido para bloquear ou desbloquear da app <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Se a app <xliff:g id="CREDITOR_APP">%1$s</xliff:g> não estiver disponível"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licenças de código aberto"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"As outras capacidades de gestão em "<b>"Definições &gt; Segurança &gt; Informações do dispositivo gerido"</b>" não se aplicam a este dispositivo"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"As capacidades de gestão na secção de dispositivos financiados das Definições de segurança não se aplicam a este dispositivo."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Este dispositivo foi fornecido pelo fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"A app de quiosque vai ser transferida e instalada automaticamente"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"A app de quiosque vai ser instalada para este utilizador"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"O fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restringir este dispositivo se falhar um pagamento"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"O fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restringir o dispositivo se falhar um pagamento. Para ver os detalhes, consulte os <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termos de Utilização<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"O fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restringir este dispositivo se não fizer os pagamentos necessários. Para obter detalhes, veja os <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termos de Utilização<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"O fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restringir este dispositivo se o proprietário não fizer os pagamentos"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Para obter ajuda, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>contacte <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Anterior"</string>
     <string name="next" msgid="8248291863254324326">"Seguinte"</string>
     <string name="start" msgid="2842214844667658537">"Iniciar"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informações"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Inf. de aprovision."</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Inscreva o seu dispositivo"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Já pode inscrever o seu dispositivo no programa de financiamento do fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Já pode inscrever o seu dispositivo no programa de financiamento do fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Já pode inscrever o seu dispositivo no programa de subsídio do fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Faz parte do programa de subsídio de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Inscrição do dispositivo"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"O fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode alterar as definições neste dispositivo"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Saber mais"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informações do dispositivo financiado"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"O seu fornecedor de crédito pode alterar as definições e instalar a app de quiosque no dispositivo.\n\nO <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pode restringir este dispositivo se não fizer os pagamentos necessários nem parar de usar o SIM do fornecedor <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPara saber mais, contacte o fornecedor <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"O fornecedor <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pode alterar as definições e instalar a app de quiosque no dispositivo.\n\nSe falhar um pagamento, o fornecedor <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> pode restringir o dispositivo.\n\nPara saber mais, contacte o fornecedor <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"O fornecedor <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pode alterar as definições e instalar a app de quiosque no dispositivo.\n\nO fornecedor <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> também pode restringir este dispositivo se falhar um pagamento ou deixar de usar o SIM do fornecedor <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPara saber mais, contacte o fornecedor <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Enquanto não pagar pelo seu dispositivo, não pode:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reiniciar o dispositivo no modo de segurança"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Alterar data, hora e fusos horários"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Usar opções de programador"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Se algo correr mal, o fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Pode desinstalar a app <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Para obter ajuda:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contactar o fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Aprovisionar"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{O dispositivo vai ser reposto dentro de 1 dia}other{O dispositivo vai ser reposto dentro de # dias}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"O dispositivo vai ser reposto dentro de <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Todos os dados do dispositivo vão ser eliminados. Para obter ajuda para inscrever o seu dispositivo, contacte o fornecedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Permita que a notificação do DeviceLock continue a adiar a inscrição do dispositivo."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"O aprovisionamento do financiamento falhou"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Clique aqui para ver formas de contactar o seu financiador. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Saiba mais<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Sair"</string>
+    <string name="retry" msgid="7497287909193345356">"Tentar novamente"</string>
 </resources>
diff --git a/DeviceLockController/res/values-pt/strings.xml b/DeviceLockController/res/values-pt/strings.xml
index 96314dc..168a727 100644
--- a/DeviceLockController/res/values-pt/strings.xml
+++ b/DeviceLockController/res/values-pt/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Todas as solicitações de bloqueio ou desbloqueio do app <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Se o app <xliff:g id="CREDITOR_APP">%1$s</xliff:g> não estiver disponível"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licenças de código aberto"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Os outros recursos de gerenciamento em "<b>"Configurações &gt; Segurança &gt; Informações do dispositivo gerenciado"</b>" não se aplicam a este dispositivo"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Os recursos de gerenciamento na seção do dispositivo financiado das Configurações de segurança não se aplicam a este dispositivo."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Este dispositivo é fornecido pela <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"O aplicativo de quiosque será baixado e instalado automaticamente"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"O aplicativo de quiosque será instalado para este usuário"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"O provedor (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>) pode restringir este dispositivo caso você atrase um pagamento"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"O provedor <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restringir o dispositivo caso você atrase um pagamento. Para mais detalhes, consulte os <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termos e Condições<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"A <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restringir este dispositivo caso você não faça os pagamentos necessários. Para mais detalhes, consulte os <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termos e Condições<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"A <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode restringir este dispositivo caso o proprietário não faça os pagamentos"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Para receber ajuda, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>entre em contato com <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Anterior"</string>
     <string name="next" msgid="8248291863254324326">"Próxima"</string>
     <string name="start" msgid="2842214844667658537">"Iniciar"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informações"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Sobre provisionar"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Registrar seu dispositivo"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Agora você pode registrar seu dispositivo no programa de financiamento da <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Você já pode registrar seu dispositivo no programa financeiro deste provedor: <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Agora você pode registrar seu dispositivo no programa de subsídios da <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Você está no programa de subsídios da <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Registro do dispositivo"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"A <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> pode mudar as configurações neste dispositivo"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Saiba mais"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informações do dispositivo financiado"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Sua provedora de crédito pode mudar as configurações e instalar o aplicativo de quiosque no dispositivo.\n\nA <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> poderá restringir este dispositivo se você não fizer os pagamentos necessários ou parar de usar o chip da <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPara saber mais, entre em contato com <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"A provedora <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pode mudar as configurações e instalar o aplicativo de quiosque no dispositivo.\n\nSe você perder um pagamento, a <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> poderá restringir o dispositivo.\n\nPara saber mais, entre em contato com a <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"A provedora <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> pode mudar as configurações e instalar o aplicativo de quiosque no dispositivo.\n\nA <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> também poderá restringir este dispositivo se você não fizer um pagamento ou parar de usar o chip da <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPara saber mais, entre em contato com a <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Até terminar de pagar pelo dispositivo, você não poderá:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reiniciar o dispositivo no modo de segurança"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Mudar data, hora e fuso horário"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Usar as opções do desenvolvedor"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Se algo der errado, a <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> poderá:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Você pode desinstalar o app <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Para receber ajuda:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Entre em contato com <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provisionar"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{O dispositivo será redefinido em 1 dia}one{O dispositivo será redefinido em # dia}other{O dispositivo será redefinido em # dias}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"O dispositivo será redefinido em <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Todos os dados do dispositivo serão excluídos. Para receber ajuda para registrar seu dispositivo, entre em contato com <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Conceda permissão à notificação do DeviceLock para continuar adiando a inscrição do dispositivo."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Falha do provisionamento de financiamento"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Clique aqui para aprender a entrar em contato com seu financiador. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Saiba mais<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Sair"</string>
+    <string name="retry" msgid="7497287909193345356">"Repetir"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ro/strings.xml b/DeviceLockController/res/values-ro/strings.xml
index 403b5d8..cd36c07 100644
--- a/DeviceLockController/res/values-ro/strings.xml
+++ b/DeviceLockController/res/values-ro/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Toate solicitările de blocare sau deblocare de la <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Dacă aplicația <xliff:g id="CREDITOR_APP">%1$s</xliff:g> nu este disponibilă"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licențe open source"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Celelalte capacități de gestionare din "<b>"Setări &gt; Securitate &gt; Informații privind dispozitivul gestionat"</b>" nu se aplică pentru acest dispozitiv"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Capacitățile de gestionare din secțiunea privind dispozitivele finanțate din Setări de securitate nu se aplică pentru acest dispozitiv."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Acest dispozitiv este oferit de <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Aplicația chioșc va fi descărcată și instalată automat"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Aplicația chioșc va fi instalată pentru acest utilizator"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> poate limita folosirea acestui dispozitiv dacă nu faci o plată"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> poate limita folosirea acestui dispozitiv dacă nu faci o plată. Pentru detalii, consultă <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termenii și condițiile <xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> poate limita folosirea acestui dispozitiv dacă nu faci plățile necesare. Pentru detalii, vezi <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Termeni și condiții <xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> poate limita folosirea acestui dispozitiv, dacă proprietarul nu face plățile"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Pentru ajutor, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>contactează <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Înapoi"</string>
     <string name="next" msgid="8248291863254324326">"Înainte"</string>
     <string name="start" msgid="2842214844667658537">"Pornește"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informații"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Despre provizionare"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Înregistrează dispozitivul"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Îți poți înregistra acum dispozitivul în programul de finanțare <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Îți poți înregistra acum dispozitivul în programul de finanțare <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Îți poți înregistra acum dispozitivul în programul de subvenționare<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Faci parte din programul de subvenționare <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Înregistrarea dispozitivului"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> poate schimba setările pe acest dispozitiv"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Află mai multe"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informații privind dispozitivul finanțat"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Creditorul poate să modifice setările și să instaleze aplicația chioșc pe dispozitiv.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> poate să limiteze acest dispozitiv dacă nu faci plățile necesare sau dacă nu mai folosești cardul SIM <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPentru a afla mai multe, contactează <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> poate să modifice setările și să instaleze aplicația chioșc pe dispozitiv.\n\nDacă nu faci o plată, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> îți poate restricționa dispozitivul.\n\nCa să afli mai multe, contactează <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> poate să modifice setările și să instaleze aplicația chioșc pe dispozitiv.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> îți poate restricționa dispozitivul dacă nu faci o plată sau nu mai folosești cardul SIM de la <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nCa să afli mai multe, contactează <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Înainte să plătești pentru dispozitiv, nu poți:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"să repornești dispozitivul în modul sigur;"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Modifică data, ora și fusurile orare"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"să folosească opțiuni pentru dezvoltatori;"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Dacă se întâmplă ceva cu dispozitivul, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> poate:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Poți să dezinstalezi aplicația <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Pentru a obține ajutor:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Contactează <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Configurează accesul pentru utilizatori"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Dispozitivul se va reseta într-o zi}few{Dispozitivul se va reseta în # zile}other{Dispozitivul se va reseta în # de zile}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Dispozitivul se va reseta în <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Toate datele dispozitivului vor fi șterse. Pentru ajutor la înregistrarea dispozitivului, contactează <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Permite notificările de la DeviceLock să continue amânarea înregistrării dispozitivului."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Provizionarea finanțării nu a reușit"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Dă clic aici pentru mai multe modalități de a lua legătura cu expertul financiar. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Află mai multe<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Ieși"</string>
+    <string name="retry" msgid="7497287909193345356">"Încearcă din nou"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ru/strings.xml b/DeviceLockController/res/values-ru/strings.xml
index 402bb72..39d9355 100644
--- a/DeviceLockController/res/values-ru/strings.xml
+++ b/DeviceLockController/res/values-ru/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Запросы на блокировку и разблокировку от приложения \"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>\"."</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Данные о том, что приложение \"<xliff:g id="CREDITOR_APP">%1$s</xliff:g>\" недоступно на устройстве."</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Лицензии открытого ПО"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Другие функции управления, перечисленные в разделе "<b>"Настройки &gt; Безопасность &gt; Информация об управляемом устройстве"</b>", к этому устройству не применяются."</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"К этому устройству не применяются функции управления, перечисленные в разделе настроек безопасности для купленного в кредит устройства."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Устройство предоставлено кредитором \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Киоск-приложение будет скачано и установлено автоматически."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Для пользователя будет установлено киоск-приложение."</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Кредитор \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" может ограничить работу устройства, если вы пропустите платеж."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Кредитор \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" может ограничить работу устройства, если вы пропустите платеж. Подробные сведения об этом есть в <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Условиях использования<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Если вы не будете совершать необходимые выплаты, кредитор \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" может ограничить работу устройства. Подробные сведения представлены в <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Условиях использования<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Кредитор \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" может ограничить работу устройства, если его владелец не вносит платежи."</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"За помощью обращайтесь к <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>поставщику \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Назад"</string>
     <string name="next" msgid="8248291863254324326">"Далее"</string>
     <string name="start" msgid="2842214844667658537">"Начать"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Информация"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Данные о настройке"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Зарегистрируйте устройство"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Вы можете зарегистрировать устройство в программе финансирования кредитора \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Вы можете зарегистрировать устройство в программе финансирования поставщика \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Вы можете зарегистрировать устройство в программе субсидирования кредитора \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Вы получаете субсидирование компании \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\""</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Регистрация устройства"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> может изменять настройки устройства."</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Подробнее"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Об устройстве в программе финансирования"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Кредитор может изменить настройки устройства и установить на него киоск-приложение.\n\nЕсли вы не совершаете необходимые выплаты или не используете SIM-карту компании \"<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>\", кредитор \"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>\" может ограничить работу устройства.\n\nЗа дополнительной информацией обращайтесь в компанию \"<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\"."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"Кредитор \"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>\" может изменить настройки устройства и установить на него киоск-приложение.\n\nЕсли вы пропустите платеж, кредитор \"<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>\" может ограничить работу устройства.\n\nЗа дополнительной информацией обращайтесь в компанию \"<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\"."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"Кредитор \"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>\" может изменить настройки устройства и установить на него киоск-приложение.\n\nЕсли вы пропустите платеж или перестанете пользоваться SIM-картой компании \"<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\", кредитор \"<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>\" может ограничить работу устройства.\n\nЗа дополнительной информацией обращайтесь в компанию \"<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>\"."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Что вы не можете делать до погашения кредита:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Переводить устройство в безопасный режим"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Изменять дату, время и часовой пояс на устройстве"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Изменять параметры для разработчиков"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"При наличии проблем кредитор \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\" может:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Вы можете удалить приложение \"<xliff:g id="KIOSK_APP">%1$s</xliff:g>\""</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Нужна помощь?"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Обратитесь к поставщику (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>)<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Инициализация"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{До сброса настроек остался 1 день}one{До сброса настроек остался # день}few{До сброса настроек осталось # дня}many{До сброса настроек осталось # дней}other{До сброса настроек осталось # дня}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Время до сброса настроек: <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"С устройства будут удалены все данные. Если вам нужна помощь с регистрацией устройства, свяжитесь с кредитором \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Чтобы отложить регистрацию устройства, разрешите DeviceLock присылать вам уведомления."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Не удалось настроить финансирование"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Вы можете связаться с финансовым специалистом. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Подробнее…<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Выйти"</string>
+    <string name="retry" msgid="7497287909193345356">"Повторить попытку"</string>
 </resources>
diff --git a/DeviceLockController/res/values-si/strings.xml b/DeviceLockController/res/values-si/strings.xml
index 3b676eb..5a3e1b9 100644
--- a/DeviceLockController/res/values-si/strings.xml
+++ b/DeviceLockController/res/values-si/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> වෙතින් වන කිනම් හෝ අගුළු දැමීමේ හෝ අගුළු හැරීමේ ඉල්ලීම්"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> යෙදුම ලබා ගත නොහැකි නම්"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"විවෘත මූලාශ්‍ර බලපත්‍ර"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"සැකසීම් &gt; ආරක්ෂාව &gt; කළමනාකරණය කළ උපාංග තතු"</b>" තුළ වෙනත් කළමනාකරණ හැකියා මෙම උපාංගයට නොයෙදෙයි"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"ආරක්ෂක සැකසීම්වල මූල්‍යමය උපාංග අංශයේ කළමනාකරණ හැකියා මෙම උපාංගයට අදාළ නොවේ."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"මෙම උපාංගය <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> මගින් සපයනු ලබයි"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk යෙදුම ස්වයංක්‍රීයව බාගත කර ස්ථාපනය කරනු ලැබේ"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"මෙම පරිශීලකයා සඳහා Kiosk යෙදුම ස්ථාපනය කරනු ලැබේ"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> හට ඔබට ගෙවීමක් මඟ හැරුණහොත් මෙම උපාංගය සීමා කළ හැක"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> හට ඔබට ගෙවීමක් මඟ හැරුණහොත් උපාංගය සීමා කළ හැක. විස්තර සඳහා, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>නියමයන් සහ කොන්දේසි<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> බලන්න."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> හට ඔබ අවශ්‍ය ගෙවීම් නොකරන්නේ නම් මෙම උපාංගය සීමා කළ හැක. විස්තර සඳහා, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>නියමයන් සහ කොන්දේසි<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> බලන්න."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>හට හිමිකරු ගෙවීම් නොකරන්නේ නම් මෙම උපාංගය සීමා කළ හැක"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"උදවු සඳහා, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> සම්බන්ධ කර ගන්න<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"පෙර"</string>
     <string name="next" msgid="8248291863254324326">"මීළඟ"</string>
     <string name="start" msgid="2842214844667658537">"ආරම්භය"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"තතු"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"ප්‍රතිපාදන තතු"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"ඔබේ උපාංගය ලියාපදිංචි කරන්න"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"ඔබට දැන් <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ගේ මූල්‍ය වැඩසටහනට ඔබේ උපාංගය ලියාපදිංචි කළ හැක"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"ඔබට දැන් <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ගේ සහනාධාර වැඩසටහනට ඔබේ උපාංගය ලියාපදිංචි කළ හැක"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"ඔබට දැන් <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ගේ සහනාධාර වැඩසටහනට ඔබේ උපාංගය ලියාපදිංචි කළ හැක"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"ඔබ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ගේ සහනාධාර වැඩසටහනේ සිටී"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"උපාංගය ලියාපදිංචි කිරීම"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> හට මෙම උපාංගයෙහි සැකසීම් වෙනස් කළ හැක"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"තව දැන ගන්න"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"මූල්‍යනය කළ උපාංග තතු"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"ඔබේ ණය සපයන්නාට සැකසීම් වෙනස් කර උපාංගයේ Kiosk යෙදුම ස්ථාපනය කළ හැක.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ඔබ අවශ්‍ය ගෙවීම් නොකරන්නේ නම් හෝ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>ගේ SIM භාවිතා කිරීම නවත්වන්නේ නම් මෙම උපාංගය සීමා කළ හැක.\n\nතව දැන ගැනීම සඳහා, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> සම්බන්ධ කර ගන්න."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> හට සැකසීම් වෙනස් කර උපාංගයෙහි Kiosk යෙදුම ස්ථාපනය කළ හැක.\n\nඔබට ගෙවීමක් මග හැරුණහොත්, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> හට ඔබේ උපාංගය සීමා කළ හැක.\n\nතව දැන ගැනීම සඳහා, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> සම්බන්ධ කර ගන්න."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> හට සැකසීම් වෙනස් කර උපාංගයෙහි Kiosk යෙදුම ස්ථාපනය කළ හැක.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ඔබට ගෙවීමක් මග හැරුණහොත් හෝ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>ගේ SIM භාවිතා කිරීම නැවැත්වූ විට මෙම උපාංගය සීමා කිරීම ද කළ හැක.\n\nතව දැන ගැනීම සඳහා, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> සම්බන්ධ කර ගන්න."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"ඔබ ඔබේ උපාංගය සඳහා ගෙවන තුරු, ඔබට කළ නොහැක:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"ඔබේ උපාංගය ආරක්ෂිත ප්‍රකාරයට නැවත පණ ගැන්වීම"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"දිනය, වේලාව, සහ වේලා කලාප වෙනස් කිරීම"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"සංවර්ධක විකල්ප භාවිත කිරීම"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"ඔබේ උපාංගයේ යම් දෙයක් වැරදී ගියහොත්, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> හට හැක්කේ:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"ඔබට <xliff:g id="KIOSK_APP">%1$s</xliff:g> යෙදුම අස්ථාපනය කළ හැක"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"උදවු ලබා ගැනීම සඳහා:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> සම්බන්ධ කර ගන්න<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"සැපයීම"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{උපාංගය 1 දිනකින් යළි සකසනු ඇත}one{උපාංගය දින #කින් යළි සකසනු ඇත}other{උපාංගය දින #කින් යළි සකසනු ඇත}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"උපාංගය <xliff:g id="TIMER">%s</xliff:g>කින් යළි සකසනු ඇත"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"සියලු උපාංග දත්ත මකා දැමෙනු ඇත. ඔබේ උපාංගය ලියාපදිංචි කිරීමට උදවු සඳහා, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> සම්බන්ධ කර ගන්න"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"උපාංගය ලියාපදිංචි කිරීම කල් දැමීම දිගටම කරගෙන යාමට DeviceLock වෙතින් දැනුම්දීමට ඉඩ දෙන්න."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"මූල්‍ය ප්‍රතිපාදන අසමත් වී ඇත"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"ඔබේ මූල්‍යකරු සම්බන්ධ කර ගැනීමට ක්‍රම සඳහා මෙතැන ක්ලික් කරන්න. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>තව දැන ගන්න<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"පිටවන්න"</string>
+    <string name="retry" msgid="7497287909193345356">"යළි උත්සාහ කරන්න"</string>
 </resources>
diff --git a/DeviceLockController/res/values-sk/strings.xml b/DeviceLockController/res/values-sk/strings.xml
index c7e7a82..1644fbc 100644
--- a/DeviceLockController/res/values-sk/strings.xml
+++ b/DeviceLockController/res/values-sk/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Všetky žiadosti o uzamknutie alebo odomknutie z aplikácie <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Ak aplikácia <xliff:g id="CREDITOR_APP">%1$s</xliff:g> nie je k dispozícii"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licencie open source"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Ostatné možnosti správy v sekcii "<b>"Nastavenia &gt; Zabezpečenie &gt; Informácie o spravovanom zariadení"</b>" sa na toto zariadenie nevzťahujú"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Možnosti správy v sekcii financovaného zariadenia v nastaveniach zabezpečenia sa na toto zariadenie nevzťahujú."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Toto zariadenie poskytuje <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Verejná aplikácia sa stiahne a nainštaluje automaticky"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Verejná aplikácia sa nainštaluje pre tohto používateľa"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Ak nezaplatíte splátku, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> môže toto zariadenie obmedziť"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Ak nezaplatíte splátku, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> môže zariadenie obmedziť. Podrobnosti nájdete v <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>zmluvných podmienkach<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Ak nezaplatíte povinné splátky, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> môže toto zariadenie obmedziť. Podrobnosti nájdete v <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>zmluvných podmienkach<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Ak vlastník nebude platiť splátky, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> môže toto zariadenie obmedziť"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Ak potrebujete pomoc, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>kontaktujte <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Naspäť"</string>
     <string name="next" msgid="8248291863254324326">"Ďalej"</string>
     <string name="start" msgid="2842214844667658537">"Začať"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informácie"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Info o poskytovaní"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Zaregistrujte svoje zariadenie"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Teraz môžete zariadenie zaregistrovať do programu financovania od poskytovateľa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Teraz môžete zariadenie zaregistrovať do programu financovania od poskytovateľa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Zariadenie môžete zaregistrovať do programu finančnej pomoci od poskytovateľa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Ste v programe finančnej pomoci poskytovateľa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Registrácia zariadenia"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> môže zmeniť nastavenia v tomto zariadení"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Ďalšie informácie"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informácie o financovanom zariadení"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Poskytovateľ úveru môže v tomto zariadení zmeniť nastavenia a nainštalovať verejnú aplikáciu.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> môže toto zariadenie obmedziť, ak nebudete splácať povinné splátky alebo prestanete používať SIM kartu poskytovateľa <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nViac sa dozviete od poskytovateľa <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> môže v tomto zariadení zmeniť nastavenia a nainštalovať verejnú aplikáciu.\n\nAk zmeškáte platbu, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> môže obmedziť vaše zariadenie.\n\nViac sa dozviete od poskytovateľa <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> môže v tomto zariadení zmeniť nastavenia a nainštalovať verejnú aplikáciu.\n\nAk zmeškáte platbu alebo prestanete používať SIM kartu poskytovateľa <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> môže toto zariadenie aj obmedziť.\n\nViac sa dozviete od poskytovateľa <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Kým za zariadenie nezaplatíte, nemôžete:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Reštartujte zariadenie do núdzového režimu"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Zmeňte dátum, čas a časové pásma"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Použite nastavenie Pre vývojárov"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Ak sa so zariadením niečo stane, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> môže:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Aplikáciu <xliff:g id="KIOSK_APP">%1$s</xliff:g> môžete odinštalovať"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Ako získať pomoc:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontaktovať banku <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Poskytovanie"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Zariadenie sa resetuje o 1 deň}few{Zariadenie sa resetuje o # dni}many{Zariadenie sa resetuje o # dňa}other{Zariadenie sa resetuje o # dní}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Zariadenie sa resetuje o <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Všetky údaje budú zo zariadenia odstránené. Ak potrebujete pomoc s registráciou zariadenia, kontaktujte <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Ak chcete pokračovať v odložení registrácie zariadenia, povoľte upozornenia v nastavení zámky zariadenia"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Financie sa nepodarilo poskytnúť"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Ak chcete zistiť, ako kontaktovať správcu financií, kliknite tu. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Ďalšie informácie<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Zavrieť"</string>
+    <string name="retry" msgid="7497287909193345356">"Skúsiť znova"</string>
 </resources>
diff --git a/DeviceLockController/res/values-sl/strings.xml b/DeviceLockController/res/values-sl/strings.xml
index 71dc681..4e6ec3b 100644
--- a/DeviceLockController/res/values-sl/strings.xml
+++ b/DeviceLockController/res/values-sl/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Vse zahteve aplikacije <xliff:g id="CREDITOR_APP">%1$s</xliff:g> za zaklepanje ali odklepanje"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Podatek, da aplikacija <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ni na voljo"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Odprtokodne licence"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Druge zmožnosti upravljanja, ki so navedene v "<b>"Nastavitve &gt; Varnost &gt; Podatki o upravljani napravi"</b>", ne veljajo za to napravo"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Zmožnosti upravljanja, ki so v varnostnih nastavitvah navedene za napravo na obroke, ne veljajo za to napravo."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"To napravo zagotavlja <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Aplikacija Kiosk bo samodejno prenesena in nameščena."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Aplikacija Kiosk bo nameščena za tega uporabnika"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> lahko omeji uporabo te naprave v primeru zamude pri plačilu."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> lahko omeji uporabo naprave v primeru zamude pri plačilu. Za podrobnosti si oglejte <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>določila in pogoje<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> lahko omeji uporabo te naprave v primeru neplačevanja obrokov. Za podrobnosti si oglejte <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>določila in pogoje<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> lahko omeji uporabo te naprave, če lastnik ne plačuje obrokov."</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Če potrebujete pomoč, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>se obrnite na ponudnika <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Nazaj"</string>
     <string name="next" msgid="8248291863254324326">"Naprej"</string>
     <string name="start" msgid="2842214844667658537">"Začni"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Podatki"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Podatki o pripravi"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Včlanite napravo"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Zdaj lahko napravo včlanite v program financiranja pri ponudniku <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Zdaj lahko napravo včlanite v program financiranja pri ponudniku <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Zdaj lahko napravo včlanite v program subvencioniranja pri ponudniku <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Ste v programu subvencioniranja pri ponudniku <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Včlanitev naprave"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"Ponudnik <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> lahko spreminja nastavitve v tej napravi"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Več o tem"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Podatki o napravi na obroke"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Ponudnik obročnega odplačila lahko v napravi spreminja nastavitve in namesti aplikacijo Kiosk.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> lahko omeji uporabo te naprave v primeru neplačila obrokov ali prenehanja uporabe kartice SIM ponudnika <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nZa več informacij se obrnite na ponudnika <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> lahko v napravi spreminja nastavitve in namesti aplikacijo Kiosk.\n\nČe ne plačate obroka, lahko <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> omeji uporabo naprave.\n\nZa več informacij se obrnite na ponudnika <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> lahko v napravi spreminja nastavitve in namesti aplikacijo Kiosk.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> lahko tudi omeji uporabo te naprave, če ne plačate obroka ali prenehate uporabljati kartico SIM ponudnika <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nZa več informacij se obrnite na ponudnika <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Dokler naprave ne odplačate, ne morete izvajati teh dejanj:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Vnovični zagon naprave v varnem načinu"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Spreminjanje datuma, ure in časovnega pasu"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Uporaba možnosti za razvijalce"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"V primeru težav z napravo ima <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> te možnosti:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Aplikacijo <xliff:g id="KIOSK_APP">%1$s</xliff:g> lahko odmestite"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Če potrebujete pomoč:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Stopite v stik s ponudnikom <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Priprava"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Naprava bo ponastavljena čez 1 dan}one{Naprava bo ponastavljena čez # dan}two{Naprava bo ponastavljena čez # dneva}few{Naprava bo ponastavljena čez # dni}other{Naprava bo ponastavljena čez # dni}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Naprava bo ponastavljena čez <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Vsi podatki v napravi bodo izbrisani. Če potrebujete pomoč pri včlanitvi naprave, se obrnite na ponudnika <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>."</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Dovolite obvestila iz aplikacije DeviceLock, če želite še naprej prelagati včlanitev te naprave."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Priprava na financiranje ni uspela"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Kliknite tukaj, če si želite ogledati, kako se lahko obrnete na ponudnika obročnega odplačila. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Več o tem<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Zapri"</string>
+    <string name="retry" msgid="7497287909193345356">"Poskusi znova"</string>
 </resources>
diff --git a/DeviceLockController/res/values-sq/strings.xml b/DeviceLockController/res/values-sq/strings.xml
index f5c77a7..99ab5a0 100644
--- a/DeviceLockController/res/values-sq/strings.xml
+++ b/DeviceLockController/res/values-sq/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Çfarëdo kërkese për kyçje ose shkyçje nga <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Nëse aplikacioni <xliff:g id="CREDITOR_APP">%1$s</xliff:g> nuk ofrohet"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licencat me burim të hapur"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Aftësitë e tjera të menaxhimit te "<b>"Cilësimet &gt; Siguria &gt; Informacioni i pajisjes së menaxhuar"</b>" nuk zbatohen për këtë pajisje"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Aftësitë e menaxhimit në seksionin e pajisjes së financuar te cilësimet e \"Sigurisë\" nuk zbatohen për këtë pajisje."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Kjo pajisje ofrohet nga <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Aplikacioni \"Kioskë\" do të shkarkohet dhe instalohet automatikisht"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Aplikacioni \"Kioskë\" do të instalohet për këtë përdorues"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> mund ta kufizojë këtë pajisje nëse harron një pagesë"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> mund ta kufizojë pajisjen nëse ti harron një pagesë. Për detaje, shiko <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kushtet e përgjithshme<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> mund ta kufizojë këtë pajisje nëse nuk kryen pagesat e nevojshme. Për detaje, shiko <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kushtet e përgjithshme<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> mund ta kufizojë këtë pajisje nëse zotëruesi nuk kryen pagesat"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Për ndihmë, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>kontakto me <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Prapa"</string>
     <string name="next" msgid="8248291863254324326">"Para"</string>
     <string name="start" msgid="2842214844667658537">"Nis"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Informacione"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Të dhëna: përgatitja"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Regjistro pajisjen tënde"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Tani mund ta regjistrosh pajisjen në programin e financimit të <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Tani mund ta regjistrosh pajisjen tënde në programin e financimit të <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Tani mund ta regjistrosh pajisjen tënde në programin e subvencionit të <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Je në programin e subvencionit të <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Regjistrimi i pajisjes"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> mund të ndryshojë cilësimet në këtë pajisje"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Mëso më shumë"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Informacionet e pajisjes së financuar"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Ofruesi yt i blerjes me këste mund të ndryshojë cilësimet dhe të instalojë aplikacionin \"Kioskë\" në pajisje.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> mund ta kufizojë këtë pajisje nëse ti nuk kryen pagesat e nevojshme ose nuk e përdor më kartën SIM të <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPër të mësuar më shumë, kontakto <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> mund të ndryshojë cilësimet dhe të instalojë aplikacionin \"Kioskë\" në pajisje.\n\nNëse harron një pagesë, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> mund ta kufizojë pajisjen tënde.\n\nPër të mësuar më shumë, kontakto me <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> mund të ndryshojë cilësimet dhe të instalojë aplikacionin \"Kioskë\" në pajisje.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> mund ta kufizojë gjithashtu këtë pajisje nëse harron një pagesë ose ndalon përdorimin e kartës SIM të <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPër të mësuar më shumë, kontakto me <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Derisa të paguash për pajisjen tënde, nuk mund:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Të rindezësh pajisjen në modalitetin e sigurt"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Të ndryshojë datën, orën dhe brezat orarë"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Të përdorë opsionet e zhvilluesit"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Nëse ndodh ndonjë problem me pajisjen, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> mund:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Mund ta çinstalosh aplikacionin <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Për të marrë ndihmë:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontakto me <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Përgatitja"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Pajisja do të rivendoset pas 1 dite}other{Pajisja do të rivendoset pas # ditësh}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Pajisja do të rivendoset pas: <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Të gjitha të dhënat e pajisjes do të fshihen. Për ndihmë në lidhje me regjistrimin e pajisjes, kontakto <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Lejo njoftimet nga DeviceLock që të vazhdosh të shtysh regjistrimin e pajisjes."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Përgatitja e financimit nuk u krye"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Kliko këtu për mënyrat për të kontaktuar me financuesin tënd. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Mëso më shumë<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Dil"</string>
+    <string name="retry" msgid="7497287909193345356">"Riprovo"</string>
 </resources>
diff --git a/DeviceLockController/res/values-sr/strings.xml b/DeviceLockController/res/values-sr/strings.xml
index 9ca3e8f..ddf5380 100644
--- a/DeviceLockController/res/values-sr/strings.xml
+++ b/DeviceLockController/res/values-sr/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Сви захтеви за закључавање и откључавање које шаље <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Ако апликација <xliff:g id="CREDITOR_APP">%1$s</xliff:g> није доступна"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Лиценце отвореног кода"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Остале могућности управљања у одељку "<b>"Подешавања &gt; Безбедност &gt; Информације о уређају којим се управља"</b>" нису примењиве на овај уређај"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Могућности управљања у одељку финансираног уређаја у подешавањима безбедности не примењују се на овај уређај."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Овај уређај пружа <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Киоск апликација ће се аутоматски преузети и инсталирати"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Киоск апликација ће бити инсталирана за овог корисника"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да ограничи овај уређај ако пропустите плаћање"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да постави ограничење за уређај ако пропустите плаћање. Детаље потражите у <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>условима и одредбама<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да ограничи овај уређај ако не извршите неопходна плаћања. Детаље потражите у <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>условима и одредбама<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да ограничи овај уређај ако власник не изврши плаћања"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Обратите се оператеру <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g> да бисте добили помоћ."</string>
     <string name="previous" msgid="5241891780917802570">"Претходно"</string>
     <string name="next" msgid="8248291863254324326">"Даље"</string>
     <string name="start" msgid="2842214844667658537">"Покрени"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Информације"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Додељивање"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Региструјте уређај"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Сада можете да региструјете уређај за <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> финансијски програм"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Сада можете да региструјете уређај за <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> финансијски програм"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Сада можете да региструјете уређај за <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> програм субвенција"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Укључени сте у <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> програм субвенција"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Регистрација уређаја"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може да мења подешавања на овом уређају"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Сазнајте више"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Информације о финансираном уређају"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Добављач кредита може да промени подешавања и инсталира киоск апликацију на уређају.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може да ограничи уређај ако не извршите неопходна плаћања или престанете да користите <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIM.\n\nДа бисте сазнали више, обратите се: <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може да промени подешавања и инсталира киоск апликацију на уређају.\n\nАко пропустите плаћање, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> може да ограничи ваш уређај.\n\nДа бисте сазнали више, обратите се добављачу услуге <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може да промени подешавања и инсталира киоск апликацију на уређају.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> може да ограничи овај уређај пропустите плаћање или престанете да користите <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM.\n\nДа бисте сазнали више, обратите се добављачу услуге <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Док не платите за уређај, не можете:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Рестартујте уређај у безбедном режиму"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Промените датум, време и временске зоне"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Користите опције за програмере"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Ако нешто није у реду с уређајем, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Можете да деинсталирате апликацију <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"За помоћ:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Обратите се оператеру <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Додељивање"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Уређај ће се ресетовати за 1 дан}one{Уређај ће се ресетовати за # дан}few{Уређај ће се ресетовати за # дана}other{Уређај ће се ресетовати за # дана}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Уређај ће се ресетовати за <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Сви подаци са уређаја ће бити избрисани. За помоћ при регистровању уређаја, обратите се: <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Дозволите обавештења Закључавања уређаја да бисте наставили са одлагањем регистрације уређаја."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Додељивање финансирања није успело"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Кликните овде да бисте видели начине за ступање у контакт са финансијером. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Сазнајте више<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Изађи"</string>
+    <string name="retry" msgid="7497287909193345356">"Пробај поново"</string>
 </resources>
diff --git a/DeviceLockController/res/values-sv/strings.xml b/DeviceLockController/res/values-sv/strings.xml
index ec37c67..99b3593 100644
--- a/DeviceLockController/res/values-sv/strings.xml
+++ b/DeviceLockController/res/values-sv/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Begäranden om att låsa eller låsa upp från <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Om <xliff:g id="CREDITOR_APP">%1$s</xliff:g>-appen inte är tillgänglig"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Licenser för öppen källkod"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Övriga hanteringsfunktioner i "<b>"Inställningar &gt; Säkerhet &gt; Information om hanterad enhet"</b>" gäller inte för den här enheten"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Hanteringsfunktionerna i avsnittet om den finansierade enheten under säkerhetsinställningarna gäller inte för den här enheten."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Enheten tillhandahålls av <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kioskappen laddas ned och installeras automatiskt"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kioskappen installeras för den här användaren"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begränsa användningen av enheten om en betalning uteblir"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begränsa användningen av enheten om en betalning uteblir. Läs <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>användarvillkoren<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> för mer information."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begränsa användningen av enheten om du inte gör de nödvändiga inbetalningarna. Läs <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>användarvillkoren<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> för mer information."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan begränsa användningen av enheten om ägaren inte gör inbetalningar"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontakta <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g> om du vill ha hjälp."</string>
     <string name="previous" msgid="5241891780917802570">"Tidigare"</string>
     <string name="next" msgid="8248291863254324326">"Nästa"</string>
     <string name="start" msgid="2842214844667658537">"Starta"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Information"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Info om tillhandahållande"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Registrera din enhet"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Nu kan du registrera din enhet för avbetalningsprogrammet hos <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Nu kan du registrera din enhet för avbetalningsprogrammet hos <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Nu kan du registrera din enhet för finansiering med <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Du får finansiering med <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Registrering av enhet"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> kan ändra inställningar på den här enheten"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Läs mer"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Information om finansierad enhet"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Långivaren kan ändra inställningar och installera kioskappen på enheten.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan spärra enheten om du inte gör de nödvändiga inbetalningarna eller slutar använda SIM-kortet från <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nKontakta <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> om du vill veta mer."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan ändra inställningar och installera kioskappen på enheten.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kan spärra enheten om du missar en betalning.\n\nKontakta <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> om du vill veta mer."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> kan ändra inställningar och installera kioskappen på enheten.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kan spärra enheten om du missar en betalning eller slutar att använda SIM-kortet från <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nKontakta <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> om du vill veta mer."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Du måste betala för enheten innan du kan göra följande:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Starta om enheten i säkert läge"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Ändra datum, tid och tidszon"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Använd utvecklaralternativ"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Om något går fel med enheten kan <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Du kan avinstallera <xliff:g id="KIOSK_APP">%1$s</xliff:g>-appen"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Så här får du hjälp:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Kontakta <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Tillhandahållande"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Enheten återställs om 1 dag}other{Enheten återställs om # dagar}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Enheten återställs om <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"All enhetsdata raderas. Kontakta <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> om du behöver hjälp att registrera enheten"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Tillåt aviseringar från DeviceLock för att fortsätta att skjuta upp registreringen av enheten."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Tillhandahållande av finansiering misslyckades"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Klicka här för att visa hur du kontaktar finansiären. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Läs mer<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Stäng"</string>
+    <string name="retry" msgid="7497287909193345356">"Försök igen"</string>
 </resources>
diff --git a/DeviceLockController/res/values-sw/strings.xml b/DeviceLockController/res/values-sw/strings.xml
index fce6ce9..7e0646b 100644
--- a/DeviceLockController/res/values-sw/strings.xml
+++ b/DeviceLockController/res/values-sw/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Ombi lolote la kufunga au kufungua kifaa linalotumwa na <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Ikiwa programu ya <xliff:g id="CREDITOR_APP">%1$s</xliff:g> haipatikani"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Leseni za programu huria"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Vipengele vingine vya udhibiti katika "<b>"Mipangilio &gt; Usalama &gt; Maelezo kuhusu vifaa vinavyodhibitiwa"</b>" havitumiki kwenye kifaa hiki"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Vipengele vya udhibiti kwenye sehemu ya vifaa vinavyotolewa kwa mkopo katika mipangilio ya Usalama havitumiki kwenye kifaa hiki."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Kifaa hiki kimetolewa na <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Programu ya Kiosk itapakuliwa na kusakinishwa kiotomatiki"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Programu ya Kiosk itasakinishwa kwa mtumiaji huyu"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> inaweza kuweka vizuizi kwenye kifaa hiki ukikosa kulipa"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> inaweza kuweka vizuizi kwenye kifaa hiki ukikosa kulipa. Ili upate maelezo zaidi, angalia <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Sheria na Masharti<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> inaweza kuweka vizuizi kwenye kifaa hiki ukikosa kulipa kiwango kilichobainishwa. Ili upate maelezo zaidi, angalia <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Sheria na Masharti<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> inaweza kuweka vizuizi kwenye kifaa hiki mmiliki akikosa kulipa"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Kwa usaidizi, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>wasiliana na <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Iliyotangulia"</string>
     <string name="next" msgid="8248291863254324326">"Endelea"</string>
     <string name="start" msgid="2842214844667658537">"Anza"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Maelezo"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Maelezo ya fidia"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Sajili kifaa chako"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Sasa unaweza kusajili kifaa chako kwenye mpango wa ufadhili wa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Sasa unaweza kusajili kifaa chako kwenye mpango wa ufadhili wa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Sasa unaweza kusajili kifaa chako kwenye mpango wa ruzuku wa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Umesajiliwa kwenye mpango wa ruzuku wa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Kusajili kifaa"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> inaweza kubadilisha mipangilio kwenye kifaa hiki"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Pata maelezo zaidi"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Maelezo ya kifaa cha kinachofadhiliwa"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Aliyekuuzia kifaa kwa mkopo anaweza kubadilisha mipangilio na kusakinisha programu ya Kiosk kwenye kifaa hiki.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> inaweza kuweka vizuizi kwenye kifaa hiki ukikosa kulipa kiwango kilichobainishwa au ukiacha kutumia SIM ya <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nIli upate maelezo zaidi, wasiliana na <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> anaweza kubadilisha mipangilio na kusakinisha programu inayotumia skrini nzima kwenye kifaa.\n\nUkikosa kulipa, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> anaweza kudhibiti matumizi ya kifaa chako.\n\nWasiliana na <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ili upate maelezo zaidi."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> anaweza kubadilisha mipangilio na kusakinisha programu inayotumia skrini nzima kwenye kifaa.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> anaweza pia kudhibiti matumizi ya kifaa chako ukikosa kulipa au ukiacha kutumia SIM ya <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nWasiliana na <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> ili upate maelezo zaidi."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Hadi utakapolipia kifaa chako, hutaweza:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Kuwasha kifaa chako tena katika hali salama"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Badilisha tarehe, saa, na saa za eneo"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Kutumia chaguo za wasanidi programu"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Kifaa chako kikipata hitilafu, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> inaweza:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Unaweza kuondoa programu ya <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Ili upate usaidizi:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Wasiliana na <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Fidia"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Mipangilio ya kifaa itawekwa upya baada ya siku 1}other{Mipangilio ya kifaa itawekwa upya baada ya siku #}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Mipangilio ya kifaa itabadilika baada ya <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Data yote kwenye kifaa itafutwa. Ili upate usaidizi kuhusu kusajili kifaa chako, wasiliana na <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Tafadhali ruhusu arifa za DeviceLock ili uendelee kuahirisha usajili wa kifaa."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Imeshindwa kuandaa fidia ya ufadhili."</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Tafadhali bofya hapa ili upate maelezo kuhusu jinsi ya kuwasiliana na mfadhili wako. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Pata maelezo zaidi<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Funga"</string>
+    <string name="retry" msgid="7497287909193345356">"Jaribu tena"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ta/strings.xml b/DeviceLockController/res/values-ta/strings.xml
index 76881e2..9be4094 100644
--- a/DeviceLockController/res/values-ta/strings.xml
+++ b/DeviceLockController/res/values-ta/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ஆப்ஸிடமிருந்து பெறப்பட்ட லாக்/அன்லாக் கோரிக்கைகள்"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"சாதனத்தில் <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ஆப்ஸ் இல்லாமல் இருப்பது"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ஓப்பன் சோர்ஸ் உரிமங்கள்"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"அமைப்புகள் &gt; பாதுகாப்பு &gt; நிர்வகிக்கப்படும் சாதனத் தகவல்கள்"</b>" என்பதிலுள்ள பிற மேலாண்மைத் திறன்கள் இந்தச் சாதனத்திற்குப் பொருந்தாது"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"பாதுகாப்பு அமைப்புகளில் \'கடன் மூலம் பெற்ற சாதனம்\' பிரிவிலுள்ள நிர்வாகத் திறன்கள் இந்தச் சாதனத்திற்குப் பொருந்தாது."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"இந்தச் சாதனம் <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> நிறுவனத்தால் வழங்கப்பட்டது"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk ஆப்ஸ் தானாகவே பதிவிறக்கப்பட்டு நிறுவப்படும்"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"இந்தப் பயனருக்கு Kiosk ஆப்ஸ் நிறுவப்படும்"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"பேமெண்ட் செலுத்தத் தவறினால் இந்தச் சாதனத்தை <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> கட்டுப்படுத்த முடியும்"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"நீங்கள் பேமெண்ட் செய்யத் தவறினால் சாதனத்தை <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> கட்டுப்படுத்தலாம். தகவல்களுக்கு, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>விதிமுறைகளையும் நிபந்தனைகளையும்<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> பாருங்கள்."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"போதுமான பேமெண்ட்டுகளை நீங்கள் செய்யாவிட்டால், இந்தச் சாதனத்தை <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> கட்டுப்படுத்த முடியும். தகவல்களுக்கு, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>விதிமுறைகளையும் நிபந்தனைகளையும்<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> பாருங்கள்."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"பேமெண்ட்டுகளை உரிமையாளர் செய்யாவிட்டால் இந்தச் சாதனத்தை <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> கட்டுப்படுத்த முடியும்"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"உதவிக்கு, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ஐத் தொடர்புகொள்ளுங்கள்<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"முந்தையது"</string>
     <string name="next" msgid="8248291863254324326">"அடுத்து"</string>
     <string name="start" msgid="2842214844667658537">"தொடங்கு"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"தகவல்கள்"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"வழங்கலுக்கான தகவல்"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"உங்கள் சாதனத்தைப் பதிவுசெய்யுங்கள்"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"உங்கள் சாதனத்தை <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> இன் நிதித் திட்டத்திற்கு இப்போது பதிவுசெய்யலாம்"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"உங்கள் சாதனத்தை <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> இன் நிதித் திட்டத்தில் இப்போது பதிவுசெய்யலாம்"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"உங்கள் சாதனத்தை <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> இன் மானியத் திட்டத்திற்கு இப்போது பதிவுசெய்யலாம்"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> மானியத் திட்டத்தில் உள்ளீர்கள்"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"சாதனத்தைப் பதிவுசெய்தல்"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"இந்தச் சாதனத்திலுள்ள அமைப்புகளை <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> மாற்ற முடியும்"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"மேலும் அறிக"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"கடன் மூலம் பெறப்பட்ட சாதனத்தின் தகவல்கள்"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"உங்கள் கடன் வழங்குநரால் சாதனத்தில் உள்ள அமைப்புகளை மாற்றவும் kiosk ஆப்ஸை நிறுவவும் முடியும்.\n\nபோதுமான பேமெண்ட்டுகளைச் செய்யாவிட்டாலோ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> சிம்மைப் பயன்படுத்துவதை நிறுத்தினாலோ இந்தச் சாதனத்தை <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> கட்டுப்படுத்தக்கூடும்.\n\nமேலும் அறிந்துகொள்ள <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ஐத் தொடர்புகொள்ளவும்."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"அமைப்புகளை மாற்றி, சாதனத்தில் கியோஸ்க் ஆப்ஸை <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ஆல் நிறுவ முடியும்.\n\nநீங்கள் பணம் செலுத்தத் தவறினால், உங்கள் சாதனத்தை <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ஆல் தடை செய்ய முடியும்.\n\nமேலும் அறிய <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ஐத் தொடர்பு கொள்ளவும்."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"அமைப்புகளை மாற்றி, சாதனத்தில் கியோஸ்க் ஆப்ஸை <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> நிறுவலாம்.\n\nநீங்கள் பணம் செலுத்தத் தவறினாலோ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> இன் சிம்மைப் பயன்படுத்துவதை நிறுத்தினாலோ இந்தச் சாதனத்தை <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ஆல் தடை செய்ய முடியும்.\n\nமேலும் அறிய <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> ஐத் தொடர்புகொள்ளவும்."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"சாதனத்திற்குப் பணம் செலுத்தும்வரை இவற்றைச் செய்ய முடியாது:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"பாதுகாப்புப் பயன்முறைக்குச் சாதனத்தை மறுபடி தொடங்குதல்"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"தேதியையும் நேரத்தையும் நேர மண்டலங்களையும் மாற்றலாம்"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"டெவெலப்பர் விருப்பங்களைப் பயன்படுத்தலாம்"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"சாதனத்தில் தவறு நிகழ்ந்தால், <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> செய்பவை:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> ஆப்ஸை நீங்கள் நிறுவல் நீக்கலாம்"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"உதவிக்கு:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ஐத் தொடர்புகொள்ளுங்கள்<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"வழங்கல்"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{சாதனம் 1 நாளில் மீட்டமைக்கப்படும்}other{சாதனம் # நாட்களில் மீட்டமைக்கப்படும்}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"<xliff:g id="TIMER">%s</xliff:g>ல் சாதனம் மீட்டமைக்கப்படும்"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"சாதனத்திலுள்ள அனைத்துத் தரவும் நீக்கப்படும். சாதனத்தைப் பதிவுசெய்வதற்கான உதவிக்கு, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ஐத் தொடர்புகொள்ளவும்"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"சாதனத்தின் பதிவைத் தொடர்ந்து ஒத்திவைக்க DeviceLock அனுப்பும் அறிவிப்பை அனுமதியுங்கள்."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"கடன் வழங்கல் தோல்வியடைந்தது"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"கடன் வழங்குநரைத் தொடர்புகொள்வதற்கான வழிகளை அறிந்துகொள்ள இங்கே கிளிக் செய்யுங்கள். <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>மேலும் அறிக<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"வெளியேறு"</string>
+    <string name="retry" msgid="7497287909193345356">"மீண்டும் முயல்க"</string>
 </resources>
diff --git a/DeviceLockController/res/values-te/strings.xml b/DeviceLockController/res/values-te/strings.xml
index 07b42fc..766d7c2 100644
--- a/DeviceLockController/res/values-te/strings.xml
+++ b/DeviceLockController/res/values-te/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> నుండి లాక్ చేయడానికి లేదా అన్‌లాక్ చేయడానికి ఏవైనా రిక్వెస్ట్‌లు రావడం"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> యాప్ అందుబాటులో లేకపోవడం"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ఓపెన్ సోర్స్ లైసెన్స్‌లు"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"సెట్టింగ్‌లు &gt; సెక్యూరిటీ &gt; నిర్వహించే పరికర సమాచారం"</b>"లోని ఇతర నిర్వహణ సామర్థ్యాలు ఈ పరికరానికి వర్తించవు"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"సెక్యూరిటీ సెట్టింగ్‌లకు సంబంధించిన ఫైనాన్స్ చేసిన పరికర విభాగంలో మేనేజ్‌మెంట్ సామర్థ్యాలు ఈ పరికరానికి వర్తించవు."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"ఈ పరికరం <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ద్వారా అందించబడింది"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk యాప్ ఆటోమేటిక్‌గా డౌన్‌లోడ్ అయి, ఇన్‌స్టాల్ అవుతుంది"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"ఈ యూజర్ కోసం కియోస్క్ యాప్ ఇన్‌స్టాల్ అవుతుంది"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"మీరు పేమెంట్‌ను మిస్ చేస్తే, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ఈ పరికరంపై పరిమితి విధించవచ్చు"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"మీరు పేమెంట్ చేయడం మిస్ చేస్తే, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> పరికరాన్ని పరిమితం చేయవచ్చు. వివరాల కోసం, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>నియమాలు &amp; షరతులను<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> చూడండి."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"మీరు అవసరమైన పేమెంట్‌లు చేయకపోతే <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ఈ పరికరంపై పరిమితి విధించవచ్చు. వివరాల కోసం, <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>నియమాలు &amp; షరతులు<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> చూడండి."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"ఓనర్ పేమెంట్‌లు చేయకపోతే <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ఈ పరికరంపై పరిమితి విధించవచ్చు"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"సహాయం కోసం, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> చేయండి<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"మునుపటి"</string>
     <string name="next" msgid="8248291863254324326">"తర్వాత"</string>
     <string name="start" msgid="2842214844667658537">"ప్రారంభించండి"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"సమాచారం"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"కేటాయింపు సమాచారం"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"మీ పరికరాన్ని ఎన్‌రోల్ చేయండి"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"మీరు ఇప్పుడు మీ పరికరాన్ని <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ఫైనాన్సింగ్ ప్రోగ్రామ్‌లో ఎన్‌రోల్ చేయవచ్చు"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"మీరు ఇప్పుడు మీ పరికరాన్ని <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ఫైనాన్స్ ప్రోగ్రామ్‌లో ఎన్‌రోల్ చేయవచ్చు"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"మీరు మీ పరికరాన్ని <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> సబ్సిడీ ప్రోగ్రామ్‌లో ఎన్‌రోల్ చేయవచ్చు"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"మీరు <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> సబ్సిడీ ప్రోగ్రామ్‌లో ఉన్నారు"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"పరికర ఎన్‌రోల్‌మెంట్"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ఈ పరికరంలోని సెట్టింగ్‌లను మార్చగలరు"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"మరింత తెలుసుకోండి"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ఫైనాన్స్ చేసిన పరికర సమాచారం"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"మీ క్రెడిట్ ప్రొవైడర్ సెట్టింగ్‌లను మార్చి, పరికరంలో కియోస్క్ యాప్‌ను ఇన్‌స్టాల్ చేయగలరు.\n\nమీరు అవసరమైన పేమెంట్‌లు చేయకపోతే లేదా <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIMని ఉపయోగించడం ఆపివేస్తే <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ఈ పరికరంపై పరిమితులు విధించవచ్చు.\n\nమరింత తెలుసుకోవడానికి, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>ని సంప్రదించండి."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> సెట్టింగ్‌లను మార్చి, పరికరంలో కియోస్క్ యాప్‌ను ఇన్‌స్టాల్ చేయగలరు.\n\nమీరు పేమెంట్ చేయడం మిస్ అయితే, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> మీ పరికరాన్ని పరిమితం చేయవచ్చు.\n\nమరింత తెలుసుకోవడానికి, <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>‌ను కాంటాక్ట్ చేయండి."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> సెట్టింగ్‌లను మార్చి, పరికరంలో కియోస్క్ యాప్‌ను ఇన్‌స్టాల్ చేయగలరు.\n\nమీరు పేమెంట్ చేయడం మిస్ అయితే లేదా <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIMను ఉపయోగించడం ఆపివేసినట్లయితే <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> కూడా ఈ పరికరాన్ని పరిమితం చేయవచ్చు.\n\nమరింత తెలుసుకోవడానికి, <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>‌ను కాంటాక్ట్ చేయండి."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"మీరు మీ పరికరం కోసం పేమెంట్ చేసే వరకు, వీటిని మీరు చేయలేరు:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"మీ పరికరాన్ని సురక్షిత మోడ్‌లోకి రీబూట్ చేయండి"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"తేదీ, టైమ్, ఇంకా టైమ్ జోన్‌లను మార్చండి"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"డెవలపర్ ఆప్షన్‌లను ఉపయోగించండి"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"మీ పరికరంతో ఏదైనా తప్పు జరిగితే, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> వీటిని చేయవచ్చు:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"మీరు <xliff:g id="KIOSK_APP">%1$s</xliff:g> యాప్‌ను అన్ఇన్‌స్టాల్ చేయవచ్చు"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"సహాయం పొందడానికి:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g>‌ను సంప్రదించండి<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"కేటాయింపు"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{పరికరం 1 రోజులో రీసెట్ అవుతుంది}other{పరికరం # రోజులలో రీసెట్ అవుతుంది}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"పరికరం <xliff:g id="TIMER">%s</xliff:g>లో రీసెట్ అవుతుంది"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"మొత్తం పరికరం డేటా తొలగించబడుతుంది. మీ పరికరాన్ని ఎన్‌రోల్ చేయడంలో సహాయం కోసం, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>ని సంప్రదించండి"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"పరికరం ఎన్‌రోల్‌మెంట్ జాప్యాన్ని కొనసాగించడానికి DeviceLock నుండి నోటిఫికేషన్‌ను అనుమతించండి."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"ఫైనాన్సింగ్ కేటాయింపు విఫలమైంది"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"మీ ఫైనాన్షియర్‌ను కాంటాక్ట్ చేయగల మార్గాల కోసం దయచేసి ఇక్కడ క్లిక్ చేయండి. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>మరింత తెలుసుకోండి<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"నిష్క్రమించు"</string>
+    <string name="retry" msgid="7497287909193345356">"మళ్లీ ట్రై చేయండి"</string>
 </resources>
diff --git a/DeviceLockController/res/values-th/strings.xml b/DeviceLockController/res/values-th/strings.xml
index cb9c7f8..a3dcc71 100644
--- a/DeviceLockController/res/values-th/strings.xml
+++ b/DeviceLockController/res/values-th/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"คำขอล็อกหรือปลดล็อกจาก <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"เห็นว่าแอป <xliff:g id="CREDITOR_APP">%1$s</xliff:g> พร้อมใช้งานหรือไม่"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"ใบอนุญาตโอเพนซอร์ส"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"ความสามารถอื่นๆ สำหรับการจัดการใน"<b>"การตั้งค่า &gt; ความปลอดภัย &gt; ข้อมูลอุปกรณ์ที่มีการจัดการ"</b>"จะไม่ได้นำมาใช้กับอุปกรณ์นี้"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"ความสามารถในการจัดการในส่วนอุปกรณ์ที่ได้รับการสนับสนุนทางการเงินของการตั้งค่าความปลอดภัยจะไม่นำมาใช้กับอุปกรณ์นี้"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"อุปกรณ์นี้ให้บริการโดย <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"ระบบจะดาวน์โหลดและติดตั้งแอปคีออสก์โดยอัตโนมัติ"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"ระบบจะติดตั้งแอปคีออสก์สำหรับผู้ใช้รายนี้"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> สามารถจำกัดอุปกรณ์นี้ได้หากคุณไม่ชำระเงิน"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> สามารถจำกัดอุปกรณ์ได้หากคุณไม่ชำระเงิน ดูรายละเอียดได้ที่<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ข้อกำหนดและเงื่อนไข<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> สามารถจำกัดอุปกรณ์นี้ได้หากคุณไม่ชำระเงินตามที่กำหนด ดูรายละเอียดได้ที่<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ข้อกำหนดและเงื่อนไข<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> สามารถจำกัดอุปกรณ์นี้ได้หากเจ้าของไม่ชำระเงิน"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"หากต้องการความช่วยเหลือ โปรด<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ติดต่อ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
     <string name="previous" msgid="5241891780917802570">"ก่อนหน้า"</string>
     <string name="next" msgid="8248291863254324326">"ถัดไป"</string>
     <string name="start" msgid="2842214844667658537">"เริ่ม"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"ข้อมูล"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"ข้อมูลการจัดเตรียม"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"ลงทะเบียนอุปกรณ์ของคุณ"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"ตอนนี้คุณลงทะเบียนอุปกรณ์ในโปรแกรมสนับสนุนทางการเงินของ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ได้แล้ว"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"ตอนนี้คุณลงทะเบียนอุปกรณ์ในโปรแกรมสนับสนุนทางการเงินของ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ได้แล้ว"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"ตอนนี้คุณลงทะเบียนอุปกรณ์ในโปรแกรมสนับสนุนทางการเงินของ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ได้แล้ว"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"คุณอยู่ในโปรแกรมสนับสนุนทางการเงินของ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"การลงทะเบียนอุปกรณ์"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> สามารถเปลี่ยนการตั้งค่าในอุปกรณ์นี้ได้"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"ดูข้อมูลเพิ่มเติม"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"ข้อมูลอุปกรณ์ที่มีการสนับสนุนทางการเงิน"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"ผู้ให้บริการเครดิตจะเปลี่ยนการตั้งค่าและติดตั้งแอปคีออสก์ในอุปกรณ์ได้\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> อาจจำกัดอุปกรณ์นี้หากคุณไม่ชำระเงินตามที่กำหนดหรือหยุดใช้ซิมของ <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>\n\nโปรดติดต่อ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> หากต้องการทราบข้อมูลเพิ่มเติม"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> จะเปลี่ยนการตั้งค่าและติดตั้งแอปคีออสก์ในอุปกรณ์ได้\n\nหากคุณไม่ชำระเงิน <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> จะจำกัดอุปกรณ์ได้\n\nโปรดติดต่อ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> เพื่อสอบถามข้อมูลเพิ่มเติม"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> จะเปลี่ยนการตั้งค่าและติดตั้งแอปคีออสก์ในอุปกรณ์ได้\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> อาจจำกัดอุปกรณ์นี้ด้วยหากคุณไม่ชำระเงินหรือหยุดใช้ซิมของ <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>\n\nโปรดติดต่อ <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> เพื่อสอบถามข้อมูลเพิ่มเติม"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"คุณจะทำสิ่งต่อไปนี้ไม่ได้จนกว่าจะชำระเงินค่าอุปกรณ์"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"รีบูตอุปกรณ์ให้อยู่ในโหมดปลอดภัย"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"เปลี่ยนวันที่ เวลา และเขตเวลา"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ใช้ตัวเลือกสำหรับนักพัฒนาแอป"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"หากพบปัญหาในอุปกรณ์ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> จะทำสิ่งต่อไปนี้ได้"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"คุณจะถอนการติดตั้งแอป <xliff:g id="KIOSK_APP">%1$s</xliff:g> ได้"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"วิธีรับความช่วยเหลือ"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>ติดต่อ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"จัดเตรียม"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{อุปกรณ์จะรีเซ็ตในอีก 1 วัน}other{อุปกรณ์จะรีเซ็ตในอีก # วัน}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"อุปกรณ์จะรีเซ็ตในอีก <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"ระบบจะลบข้อมูลทั้งหมดในอุปกรณ์ โปรดติดต่อขอความช่วยเหลือในการลงทะเบียนอุปกรณ์จาก <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"โปรดอนุญาตการแจ้งเตือนจาก DeviceLock เพื่อเลื่อนการลงทะเบียนอุปกรณ์ออกไปก่อน"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"การจัดเตรียมด้านการเงินไม่สำเร็จ"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"โปรดคลิกที่นี่สำหรับวิธีในการติดต่อนักการเงิน <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>ดูข้อมูลเพิ่มเติม<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"ออก"</string>
+    <string name="retry" msgid="7497287909193345356">"ลองอีกครั้ง"</string>
 </resources>
diff --git a/DeviceLockController/res/values-tl/strings.xml b/DeviceLockController/res/values-tl/strings.xml
index 225a986..0b3224f 100644
--- a/DeviceLockController/res/values-tl/strings.xml
+++ b/DeviceLockController/res/values-tl/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Anumang kahilingan sa pag-lock o pag-unlock mula sa <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Kung hindi available ang <xliff:g id="CREDITOR_APP">%1$s</xliff:g> app"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Mga open-source na lisensya"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Hindi nalalapat sa device na ito ang iba pang kakayahan sa pamamahala sa "<b>"Mga Setting &gt; Seguridad &gt; Impormasyon ng pinapamahalaang device"</b></string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Hindi nalalapat sa device na ito ang mga kakayahan sa pamamahala sa seksyon ng pinopondohang device ng Mga setting ng seguridad."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Nagmula sa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ang device na ito"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Awtomatikong ida-download at ii-install ang Kiosk app"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Ii-install ang Kiosk app para sa user na ito"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Puwedeng paghigpitan ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ang device na ito kung may malampasan kang pagbabayad"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Puwedeng paghigpitan ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ang device kung may napalampas kang pagbabayad. Para sa mga detalye, basahin ang <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Mga Tuntunin at Kundisyon<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Puwedeng paghigpitan ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ang device na ito kung hindi mo maibibigay ang mga kinakailangang pagbabayad. Para sa mga detalye, basahin ang <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Mga Tuntunin at Kundisyon<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Puwedeng paghigpitan ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ang device na ito kung hindi nagbabayad ang may-ari"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Para sa tulong, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>makipag-ugnayan sa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Nakaraan"</string>
     <string name="next" msgid="8248291863254324326">"Susunod"</string>
     <string name="start" msgid="2842214844667658537">"Magsimula"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Impormasyon"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Info ng provision"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"I-enroll ang iyong device"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Puwede mo na ngayong i-enroll ang iyong device sa financing program ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Puwede mo na ngayong i-enroll ang iyong device sa finance program ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Puwede mo na ngayong i-enroll ang iyong device sa subsidy program ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Nasa subsidy program ka ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Pag-enroll ng device"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"Puwedeng baguhin ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ang mga setting sa device na ito"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Matuto pa"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Impormasyon ng pinopondohang device"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Mababago ng iyong credit provider ang mga setting at makakapag-install ito ng Kiosk app sa device.\n\nPuwedeng paghigpitan ng <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ang device na ito kung hindi mo maibibigay ang mga kinakailangang pagbabayad o hindi mo na gagamitin ang SIM ng <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nPara matuto pa, makipag-ugnayan sa <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"Magagawa ng <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> na baguhin ang mga setting at i-install ang Kiosk app sa device.\n\nKung may malalaktawan kang pagbabayad, puwedeng paghigpitan ng <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ang iyong device.\n\nPara matuto pa, makipag-ugnayan sa <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"Magagawa ng <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> na baguhin ang mga setting at i-install ang Kiosk app sa device.\n\nPuwede ring paghigpitan ng <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> ang device na ito kung may malaktawan kang pagbabayad o ihinto mo ang paggamit sa SIM ng <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nPara matuto pa, makipag-ugnayan sa <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Hanggang sa mabayaran mo ang device, hindi mo magagawang:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"I-reboot ang iyong device sa safe mode"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Baguhin ang petsa, oras, at mga time zone"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Gamitin ang mga opsyon ng developer"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Kung magkaproblema sa device mo, magagawa ng <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> na:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Puwede mong i-uninstall ang <xliff:g id="KIOSK_APP">%1$s</xliff:g> app"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Para humingi ng tulong:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Makipag-ugnayan sa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provision"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Mare-reset ang device sa loob ng 1 araw}one{Mare-reset ang device sa loob ng # araw}other{Mare-reset ang device sa loob ng # na araw}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Mare-reset ang device sa loob ng <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Made-delete ang lahat ng data ng device. Para sa tulong sa pag-enroll ng iyong device, makipag-ugnayan sa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Payagan ang notification mula sa DeviceLock para patuloy na ipagpaliban ang pag-enroll ng device."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Hindi nagtagumpay ang provisioning ng financing"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Mag-click dito para sa mga paraan para makipag-ugnayan sa iyong financier. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Matuto pa<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Lumabas"</string>
+    <string name="retry" msgid="7497287909193345356">"Subukan ulit"</string>
 </resources>
diff --git a/DeviceLockController/res/values-tr/strings.xml b/DeviceLockController/res/values-tr/strings.xml
index c14fadd..edb8dcd 100644
--- a/DeviceLockController/res/values-tr/strings.xml
+++ b/DeviceLockController/res/values-tr/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> uygulamasından tüm kilitleme ve kilidi açma istekleri"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> uygulamasının kullanılıp kullanılmadığını"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Açık kaynak lisansları"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"Ayarlar &gt; Güvenlik &gt; Yönetilen cihaz bilgisi"</b>"\'ndeki diğer yönetim özellikleri bu cihaz için geçerli değildir"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Güvenlik ayarlarının finanse edilen cihaz bölümündeki yönetim özellikleri bu cihaza uygulanmaz."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Bu cihaz, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> tarafından sağlanmaktadır"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk uygulaması otomatik olarak indirilip yüklenecek."</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kiosk uygulaması bu kullanıcı için yüklenecek"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Ödemeyi aksatırsanız <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu cihazı kısıtlayabilir."</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Ödemeyi aksatırsanız <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> cihazı kısıtlayabilir. Ayrıntılar için <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Hükümler ve Koşullar<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>\'a bakın."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Gerekli ödemeleri yapmazsanız <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu cihazı kısıtlayabilir. Ayrıntılar için <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Hükümler ve Koşullar<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>\'ı inceleyin."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Cihazın sahibi ödeme yapmazsa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu cihazı kısıtlayabilir"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Yardım almak için <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ile iletişime geçin<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Önceki"</string>
     <string name="next" msgid="8248291863254324326">"Sonraki"</string>
     <string name="start" msgid="2842214844667658537">"Başlat"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Bilgi"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Provizyon bilgileri"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Cihazınızı kaydettirin"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Cihazınızı artık <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> finans programına kaydedebilirsiniz"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Cihazınızı artık <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> finans programına kaydettirebilirsiniz"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Cihazınızı artık <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> yardım programına kaydettirebilirsiniz"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> yardım programındasınız"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Cihaz kaydı"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu cihazdaki ayarları değiştirebilir"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Daha fazla bilgi"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Finanse edilen cihaz bilgisi"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Sözleşmeli cihaz sağlayıcınız ayarları değiştirebilir ve Kiosk uygulamasını cihaza yükleyebilir.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>, gerekli ödemeleri yapmazsanız veya <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIM\'ini kullanmayı bırakırsanız bu cihazı kısıtlayabilir.\n\nDaha fazla bilgi edinmek için <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ile iletişime geçin."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>, ayarları değiştirebilir ve Kiosk uygulamasını cihaza yükleyebilir.\n\nÖdemelerden birini yapmazsanız <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>, cihazınızı kısıtlayabilir.\n\nDaha fazla bilgi edinmek için <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> ile iletişime geçin."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ayarları değiştirebilir ve Kiosk uygulamasını cihaza yükleyebilir.\n\nAyrıca <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>, ödemelerden birini yapmazsanız veya <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM\'ini kullanmayı bırakırsanız bu cihazı kısıtlayabilir.\n\nDaha fazla bilgi edinmek için <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> ile iletişime geçin."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Cihazınız için ödeme yapana kadar şu işlemleri yapamazsınız:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Cihazınız güvenli modda yeniden başlatma"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Tarih, saat ve saat dilimini değiştirme"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Geliştirici seçeneklerini kullanma"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Cihazınızda sorun olursa <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> şunları yapabilir:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> uygulamasını kaldırabilirsiniz"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Yardım almak için:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ile iletişime geçin<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Provizyon"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Cihaz 1 gün içinde sıfırlanacak}other{Cihaz # gün içinde sıfırlanacak}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Cihaz <xliff:g id="TIMER">%s</xliff:g> içinde sıfırlanacak"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Tüm cihaz verileri silinecek. Cihazınızı kaydetmeyle ilgili yardım almak için <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ile iletişime geçin"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Cihazın kaydını ertelemeye devam etmek için lütfen DeviceLock bildirimlerine izin verin."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Finans provizyonu başarısız oldu"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Finans yetkilinizle iletişime geçme yöntemleri için lütfen burayı tıklayın. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Daha fazla bilgi<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Çıkış"</string>
+    <string name="retry" msgid="7497287909193345356">"Tekrar dene"</string>
 </resources>
diff --git a/DeviceLockController/res/values-uk/strings.xml b/DeviceLockController/res/values-uk/strings.xml
index 3ad6e20..39f1713 100644
--- a/DeviceLockController/res/values-uk/strings.xml
+++ b/DeviceLockController/res/values-uk/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Усі запити на блокування й розблокування з додатка <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Інформація про відсутність додатка <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Ліцензії відкритого коду"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Інші можливості керування в розділі "<b>"Налаштування &gt; Безпека &gt; Інформація про керований пристрій"</b>" не застосовуються до цього пристрою"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"До цього пристрою не застосовуються функції керування, описані в розділі налаштування безпеки для пристроїв, придбаних у кредит."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Цей пристрій надала організація <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Додаток-термінал буде завантажено й установлено автоматично"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Для цього користувача буде встановлено додаток-термінал"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Якщо не здійснити платіж, організація <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може обмежити користування цим пристроєм"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Якщо не здійснити платіж, організація <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може обмежити користування пристроєм. Щоб дізнатися більше, перегляньте <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Умови використання<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Якщо не здійснити необхідні платежі, організація <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може обмежити користування цим пристроєм. Щоб дізнатися більше, перегляньте <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Умови використання<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Якщо власник не здійснюватиме платежі, організація <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може обмежити користування цим пристроєм"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Щоб отримати допомогу, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>зв’яжіться з оператором <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Назад"</string>
     <string name="next" msgid="8248291863254324326">"Далі"</string>
     <string name="start" msgid="2842214844667658537">"Почати"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Інформація"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Дані про підготовку"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Зареєструйте свій пристрій"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Тепер ви можете зареєструвати пристрій у програмі фінансування організації <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Тепер ви можете зареєструвати пристрій у програмі фінансування організації <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Тепер ви можете зареєструвати пристрій у програмі субсидій організації <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Ви учасник програми субсидій (<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>)"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Реєстрація пристрою"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"Організація <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> може змінювати налаштування на цьому пристрої"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Докладніше"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Дані про пристрій, куплений у кредит"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Ваш кредитор може змінювати налаштування й встановлювати додаток-термінал на пристрої.\n\nЯкщо ви не здійснюватимете необхідні платежі або припините користуватися SIM-картою <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>, організація <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може обмежити користування цим пристроєм.\n\nЩоб дізнатися більше, зв’яжіться з організацією <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може змінювати налаштування й встановлювати додаток-термінал на пристрої.\n\nЯкщо не здійснити платіж, організація <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> може обмежити користування пристроєм.\n\nЩоб дізнатися більше, зв’яжіться з організацією <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> може змінювати налаштування й встановлювати додаток-термінал на пристрої.\n\nЯкщо ви не здійснюватимете необхідні платежі або припините користуватися SIM-картою <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>, організація <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> може обмежити користування цим пристроєм.\n\nЩоб дізнатися більше, зв’яжіться з організацією <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Доки ви не заплатите за пристрій, ви не зможете:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"перезапускати пристрій у безпечному режимі"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"змінювати дату, час і часові пояси"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"використовувати параметри розробника"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Якщо щось станеться з пристроєм, організація <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> зможе:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"ви зможете видалити додаток <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Щоб отримати допомогу:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Зв’язатися з постачальником пристрою \"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>\"<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Підготовка"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Налаштування пристрою буде скинуто через 1 день}one{Налаштування пристрою буде скинуто через # день}few{Налаштування пристрою буде скинуто через # дні}many{Налаштування пристрою буде скинуто через # днів}other{Налаштування пристрою буде скинуто через # дня}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Налаштування пристрою буде скинуто за <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Усі дані пристрою буде видалено. Щоб отримати допомогу з реєстрацією пристрою, зв’яжіться з організацією <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Дозвольте сповіщення від DeviceLock, щоб продовжити відкладення реєстрації пристрою."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Фінансування не надано"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Натисніть тут, щоб дізнатися, як зв’язатися зі своїм кредитором. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Докладніше<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Закрити"</string>
+    <string name="retry" msgid="7497287909193345356">"Повторити"</string>
 </resources>
diff --git a/DeviceLockController/res/values-ur/strings.xml b/DeviceLockController/res/values-ur/strings.xml
index 9ada0f2..c5d2b0b 100644
--- a/DeviceLockController/res/values-ur/strings.xml
+++ b/DeviceLockController/res/values-ur/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"‫<xliff:g id="CREDITOR_APP">%1$s</xliff:g> سے مقفل یا غیر مقفل کرنے کی کوئی بھی درخواست"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"اگر <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ایپ دستیاب نہیں ہے"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"اوپن سورس لائسنسز"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"ترتیبات &gt; سیکیورٹی &gt; نظم کردہ آلے کی معلومات"</b>" میں مینیجمنٹ کی دیگر صلاحیتیں اس آلہ پر لاگو نہیں ہوتی ہیں"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"سیکیورٹی کی ترتیبات کے مالی تعاون یافتہ آلے کے سیکشن میں موجود نظم و نسق کی صلاحیتیں اس آلے پر لاگو نہیں ہوتی ہیں۔"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"یہ آلہ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> نے فراہم کیا ہے"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"‫Kiosk ایپ خودکار طور پر ڈاؤن لوڈ اور انسٹال ہو جائے گی"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kiosk ایپ اس صارف کے لیے انسٹال کی جائے گی"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"ادائیگی چھوٹ جانے پر <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> اس آلہ کو محدود کر سکتا ہے"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"اگر آپ سے ادائیگی چھوٹ جاتی ہے تو <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> آلہ کو محدود کر سکتا ہے۔ تفصیلات کے لیے، <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>شرائط و ضوابط<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> دیکھیں۔"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"اگر آپ ضروری ادائیگیاں نہیں کرتے ہیں تو <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> اس آلہ کو محدود کر سکتا ہے۔ تفصیلات کے لیے، <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>شرائط و ضوابط<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> دیکھیں۔"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"اگر مالک ادائیگیاں نہیں کرتا ہے تو <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> اس آلے کو محدود کر سکتا ہے"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"مدد کیلئے، <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> سے رابطہ کریں<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>۔"</string>
     <string name="previous" msgid="5241891780917802570">"پچھلا"</string>
     <string name="next" msgid="8248291863254324326">"آگے جائیں"</string>
     <string name="start" msgid="2842214844667658537">"شروع کریں"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"معلومات"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"فراہمی کی معلومات"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"اپنے آلہ کا اندراج کرائيں"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"اب آپ اپنے آلے کا اندراج <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> کے فنانسنگ پروگرام میں کر سکتے ہیں"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"اب آپ اپنے آلے کا اندراج <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> کے فائنانس پروگرام میں کر سکتے ہیں"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"اب آپ اپنے آلے کا اندراج <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> کے سبسڈی پروگرام میں کر سکتے ہیں"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"آپ <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> کے سبسڈی پروگرام پر ہیں"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"آلہ کا اندراج"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> اس آلہ پر ترتیبات کو تبدیل کر سکتا ہے"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"مزید جانیں"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"مالی تعاون یافتہ آلے کی معلومات"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"آپ کا کریڈٹ فراہم کنندہ ترتیبات تبدیل کر سکتا ہے اور آلہ پر Kiosk ایپ انسٹال کر سکتا ہے۔\n\nاگر آپ ضروری ادائیگیاں نہیں کرتے ہیں یا <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> کا SIM استعمال کرنا بند نہیں کرتے ہیں تو <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> اس آلہ پر پابندی لگا سکتا ہے۔\n\nمزید جاننے کیلئے <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> سے رابطہ کریں۔"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ترتیبات تبدیل کر سکتاہے اور آلے پر کیوسک ایپ انسٹال کر سکتا ہے۔\n\nاگر آپ ادائیگی نہیں کرتے ہیں تو <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> آپ کے آلے پر پابندی لگا سکتا ہے۔\n\nمزید جاننے کے لیے <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> سے رابطہ کریں۔"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ترتیبات تبدیل کر سکتا ہے اور آلے پر کیوسک ایپ انسٹال کر سکتا ہے۔\n\nاگر آپ ادائیگی نہیں کرتے ہیں یا <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> کا SIM استعمال کرنا بند کر دیتے ہیں تو <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> آپ کے آلے پر پابندی بھی لگا سکتا ہے۔\n\nمزید جاننے کے لیے <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> سے رابطہ کریں۔"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"جب تک آپ اپنے آلے کیلئے ادائیگی نہیں کر دیتے، آپ یہ نہیں کر سکتے:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"اپنا آلہ حفاظتی وضع میں ریبوٹ نہیں کر سکتے ہیں"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"تاریخ، وقت اور ٹائم زونز تبدیل کریں"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"ڈویلپر کے اختیارات کا استعمال کر سکتا ہے"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"اگر آپ کے آلے کے ساتھ کچھ غلط ہو جاتا ہے تو <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> کر سکتا ہے:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"آپ <xliff:g id="KIOSK_APP">%1$s</xliff:g> ایپ اَن انسٹال نہیں کر سکتے ہیں"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"مدد حاصل کرنے کے لیے:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> سے رابطہ کریں<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"فراہمی"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{آلہ 1 دن میں ری سیٹ ہو جائے گا}other{آلہ # دن میں ری سیٹ ہو جائے گا}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"آلہ <xliff:g id="TIMER">%s</xliff:g> میں ری سیٹ ہو جائے گا"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"آلہ کا تمام ڈیٹا حذف کر دیا جائے گا۔ اپنے آلے کے اندراج میں مدد کے لیے، <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> سے رابطہ کریں"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"براہ کرم آلہ کا اندراج موخر کرنے کے لیے DeviceLock سے اطلاع کی اجازت دیں۔"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"فنانسنگ کی فراہمی ناکام ہو گئی ہے"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"اپنے سرمایہ کار سے رابطہ کرنے کے طریقوں کیلئے براہ کرم یہاں کلک کریں۔ <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>مزید جانیں<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"باہر نکلیں"</string>
+    <string name="retry" msgid="7497287909193345356">"پھر کوشش کریں"</string>
 </resources>
diff --git a/DeviceLockController/res/values-uz/strings.xml b/DeviceLockController/res/values-uz/strings.xml
index 765c86f..cde81cc 100644
--- a/DeviceLockController/res/values-uz/strings.xml
+++ b/DeviceLockController/res/values-uz/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ilovasidan barcha talablarni qulflash yoki ochish"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Agar <xliff:g id="CREDITOR_APP">%1$s</xliff:g> ilovasi ishlamaganda"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Ochiq kodli dastur litsenziyalari"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"Sozlamalar &gt; Xavfsizlik &gt; Boshqariluvchi qurilmaga oid axborot"</b>" ichidagi boshqa boshqaruv imkoniyatlaridan bu qurilmada foydalanmang"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Xavfsizlik sozlamalarida moliyalashtirilgan qurilma boʻlimidagi boshqaruv imkoniyatlari bu qurilmaga tatbiq qilinmaydi."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Bu qurilma <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> tomonidan taqdim etilgan"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Kiosk ilovasi avtomatik ravishda yuklab olinadi va oʻrnatiladi"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Kiosk ilovasi bu foydalanuvchi uchun oʻrnatiladi"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"Agar toʻlov qilmasangiz, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu qurilmani cheklashi mumkin"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"Agar toʻlov qilmasangiz, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> qurilmani cheklashi mumkin. Tafsilotlar uchun <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Foydalanish shartlari<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> bilan tanishing."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"Agar kerakli toʻlovlarni amalga oshirmasangiz, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu qurilmani cheklashi mumkin. Tafsilotlar uchun <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Foydalanish shartlari<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g> bilan tanishing."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"Agar egasi toʻlovlarni amalga oshirmasa, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu qurilmani cheklashi mumkin"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Yordam uchun <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bilan bogʻlaning<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Avvalgisi"</string>
     <string name="next" msgid="8248291863254324326">"Keyingisi"</string>
     <string name="start" msgid="2842214844667658537">"Boshlash"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Axborot"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Taʼminlash axboroti"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Qurilmangizni qayd qiling"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Endi qurilmangizni <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> moliyaviy dasturida qayd qilishingiz mumkin"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Endi qurilmangizni <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> moliyaviy dasturida qayd qilishingiz mumkin"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Endi qurilmangizni <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> subsidiya dasturida qayd qilishingiz mumkin"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> subsidiya dasturidasiz"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Qurilmani qayd qilish"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bu qurilmada sozlamalarni oʻzgartirishi mumkin"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Batafsil"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Moliyalashtirilgan qurilmaga oid axborot"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Kredit idorangiz sozlash jarayonida qurilmada sozlamalarni oʻzgartirishi va Kiosk ilovasini oʻrnatishi mumkin.\n\nAgar kerakli toʻlovlarni amalga oshirmasangiz yoki <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> SIM kartangizdan foydalanishni toʻxtsangiz, <xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> bu qurilmani cheklashi mumkin.\n\nBatafsil axborot olish uchun <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> bilan bogʻlaning."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> qurilmada sozlamalarni oʻzgartirishi va Kiosk ilovasini oʻrnatishi mumkin.\n\nToʻlovni oʻtkazib yuborsangiz, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> qurilmani qulflashi mumkin.\n\nBatafsil axborot olish uchun <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> operatoriga murojaat qiling."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> qurilmada sozlamalarni oʻzgartirishi va Kiosk ilovasini oʻrnatishi mumkin.\n\nToʻlovni oʻtkazib yuborsangiz yoki <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g> SIM kartasidan foydalanishni toʻxtatsangiz, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> qurilmani qulflashi mumkin.\n\nBatafsil axborot olish uchun <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g> operatoriga murojaat qiling."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Qurilmangiz uchun toʻlovni toʻliq amalga oshirmaguningizgacha siz:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Qurilmani xavfsiz rejimda qayta yoqish"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Sana, vaqt va vaqt mintaqalarini oʻzgartirish"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Dasturchi sozlamalaridan foydalanishi mumkin"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Agar qurilmangiz bilan muammo chiqsa, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"<xliff:g id="KIOSK_APP">%1$s</xliff:g> ilovasini oʻchirib tashlashingiz mumkin"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Yordam olish uchun:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g><xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bilan aloqaga chiqish<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Taʼminlash"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Qurilma 1 kundan keyin asliga qaytariladi}other{Qurilma # kundan keyin asliga qaytariladi}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Qurilma <xliff:g id="TIMER">%s</xliff:g>dan keyin asliga qaytariladi"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Barcha qurilma maʼlumotlari oʻchirib tashlanadi. Qurilmangizni qayd qilish uchun <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> bilan bogʻlaning"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Qurilmani qayd qilishni kechiktirish uchun DeviceLock bildirishnomasiga ruxsat bering."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Moliyaviy taʼminot amalga oshmadi"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Moliyachingizga murojaat qilish usullari uchun shu yerga bosing. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Batafsil<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Chiqish"</string>
+    <string name="retry" msgid="7497287909193345356">"Qayta urinish"</string>
 </resources>
diff --git a/DeviceLockController/res/values-vi/strings.xml b/DeviceLockController/res/values-vi/strings.xml
index 584fce5..65dcb03 100644
--- a/DeviceLockController/res/values-vi/strings.xml
+++ b/DeviceLockController/res/values-vi/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Mọi yêu cầu khoá hoặc mở khoá của <xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Nếu ứng dụng <xliff:g id="CREDITOR_APP">%1$s</xliff:g> không có sẵn"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Giấy phép nguồn mở"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Các tính năng quản lý khác trong phần "<b>"Cài đặt &gt; Bảo mật &gt; Thông tin thiết bị được quản lý"</b>" không áp dụng cho thiết bị này"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Các tính năng quản lý trong mục Thông tin về thiết bị trả góp của phần cài đặt Bảo mật không áp dụng cho thiết bị này."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Thiết bị này do <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> cung cấp"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"Ứng dụng Kiosk sẽ tự động được tải xuống và cài đặt"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"Ứng dụng Kiosk sẽ được cài đặt cho người dùng này"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> có thể hạn chế thiết bị này nếu bạn không thanh toán kịp thời"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> có thể hạn chế thiết bị này nếu bạn không thanh toán kịp thời. Để biết thông tin chi tiết, hãy xem <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Điều khoản và điều kiện<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> có thể hạn chế thiết bị này nếu bạn không thanh toán những khoản cần thiết. Để biết thông tin chi tiết, hãy xem <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Điều khoản và điều kiện<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> có thể hạn chế thiết bị này nếu chủ sở hữu thiết bị không thanh toán"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Để được trợ giúp, hãy <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>liên hệ với <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Trước"</string>
     <string name="next" msgid="8248291863254324326">"Tiếp theo"</string>
     <string name="start" msgid="2842214844667658537">"Bắt đầu"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Thông tin"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Thông tin cấp vốn"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Đăng ký thiết bị của bạn"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Bây giờ, bạn có thể đăng ký thiết bị này vào chương trình hỗ trợ tài chính của <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Bây giờ, bạn có thể đăng ký chương trình hỗ trợ tài chính của <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> cho thiết bị này"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Bây giờ, bạn có thể đăng ký thiết bị này vào chương trình trợ cấp của <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Bạn đang tham gia chương trình trợ cấp của <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Đăng ký thiết bị"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> có thể thay đổi các chế độ cài đặt trên thiết bị này"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Tìm hiểu thêm"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Thông tin về thiết bị trả góp"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Tổ chức tín dụng của bạn có thể thay đổi các chế độ cài đặt và cài đặt ứng dụng Kiosk trên thiết bị này.\n\n<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> có thể hạn chế thiết bị này nếu bạn không thanh toán những khoản cần thiết hoặc ngừng sử dụng SIM của <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nĐể tìm hiểu thêm, hãy liên hệ với <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> có thể thay đổi chế độ cài đặt và cài đặt ứng dụng Kiosk trên thiết bị.\n\nNếu bạn không thanh toán kịp thời, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> có thể áp dụng chế độ hạn chế đối với thiết bị của bạn.\n\nĐể tìm hiểu thêm, hãy liên hệ với <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> có thể thay đổi chế độ cài đặt và cài đặt ứng dụng Kiosk trên thiết bị.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> cũng có thể áp dụng chế độ hạn chế đối với thiết bị của bạn nếu bạn không thanh toán kịp thời hoặc ngừng sử dụng SIM của <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nĐể tìm hiểu thêm, hãy liên hệ với <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Trước khi thanh toán cho thiết bị này, bạn không thể:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Khởi động lại thiết bị ở chế độ an toàn"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Thay đổi ngày, giờ và múi giờ"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Dùng tuỳ chọn cho nhà phát triển"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Nếu thiết bị này gặp vấn đề, <xliff:g id="PROVIDER_NAME">%1$s</xliff:g> có thể:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Bạn có thể gỡ cài đặt ứng dụng <xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Cách nhận trợ giúp:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Liên hệ với <xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Cấp vốn"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Thiết bị sẽ đặt lại sau 1 ngày}other{Thiết bị sẽ đặt lại sau # ngày}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Thiết bị sẽ đặt lại sau <xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Mọi dữ liệu trên thiết bị sẽ bị xoá. Để được trợ giúp đăng ký thiết bị của bạn, hãy liên hệ với <xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Vui lòng cho phép DeviceLock gửi thông báo để tiếp tục trì hoãn quá trình đăng ký thiết bị."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Cấp vốn tài chính không thành công"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Vui lòng nhấp vào đây để biết cách liên hệ với bên hỗ trợ tài chính của bạn. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Tìm hiểu thêm<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Thoát"</string>
+    <string name="retry" msgid="7497287909193345356">"Thử lại"</string>
 </resources>
diff --git a/DeviceLockController/res/values-zh-rCN/strings.xml b/DeviceLockController/res/values-zh-rCN/strings.xml
index 7f54108..b49090e 100644
--- a/DeviceLockController/res/values-zh-rCN/strings.xml
+++ b/DeviceLockController/res/values-zh-rCN/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"来自“<xliff:g id="CREDITOR_APP">%1$s</xliff:g>”的所有锁定或解锁请求"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"“<xliff:g id="CREDITOR_APP">%1$s</xliff:g>”应用是否不可用"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"开源许可"</string>
-    <string name="footer_notice" msgid="7606898520964750584"><b>"设置 &gt; 安全 &gt; 受管理设备的信息"</b>"中的其他管理功能不适用于此设备"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"在安全设置中,分期付款设备部分中的管理功能不适用于此设备。"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"此设备由<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>提供"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"系统会自动下载并安装自助服务终端应用"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"系统将为此用户安装自助服务终端应用"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"如果您未按时支付款项,<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>可以限制您使用此设备"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"如果您未按时支付款项,<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>可能会限制您使用此设备。如需了解详情,请查看<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>条款及条件<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>。"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"如果您未支付必要款项,<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>可以限制您使用此设备。如需了解详情,请参阅<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>条款及条件<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>。"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"如果所有者未付款,<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>可以限制其使用此设备"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"如需帮助,请<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>联系<xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>。"</string>
     <string name="previous" msgid="5241891780917802570">"上一步"</string>
     <string name="next" msgid="8248291863254324326">"下一页"</string>
     <string name="start" msgid="2842214844667658537">"立即开始"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"信息"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"配置信息"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"注册您的设备"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"您的设备现在就能注册<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>的分期付款计划"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"您的设备现在就能注册<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>的补贴计划"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"您的设备现在就能注册<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>的补贴计划"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"您已加入<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>的补贴计划"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"设备注册"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>可更改此设备的设置"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"了解详情"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"分期付款设备信息"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"您的分期付款提供商可更改此设备的设置并在此设备上安装自助服务终端应用。\n\n如果您未支付必要款项或停止使用<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>的 SIM 卡,<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>可能会限制您使用此设备。\n\n如需了解详情,请与<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>联系。"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>可更改此设备的设置并在此设备上安装自助服务终端应用。\n\n如果您未按时支付款项,<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>可能会限制您使用此设备。\n\n如需了解详情,请与<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>联系。"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>可更改此设备的设置并在此设备上安装自助服务终端应用。\n\n如果您未按时支付款项或停止使用<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>的 SIM 卡,<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>也可能会限制您使用此设备。\n\n如需了解详情,请与<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>联系。"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"在支付设备款项之前,您无法执行以下操作:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"重新启动设备并进入安全模式"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"更改日期、时间和时区"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"使用开发者选项"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"如果设备出现问题,<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>可执行以下操作:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"您可以卸载“<xliff:g id="KIOSK_APP">%1$s</xliff:g>”应用"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"获取帮助:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>联系<xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"配置"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{设备将在 1 天后重置}other{设备将在 # 天后重置}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"设备将在 <xliff:g id="TIMER">%s</xliff:g>后重置"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"系统将删除所有设备数据。如需注册设备方面的帮助,请与<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>联系。"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"请允许 DeviceLock 发送通知,以继续推迟设备注册。"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"分期付款设备配置失败"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"请点击此处查看分期付款提供商的联系方式。<xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>了解详情<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"退出"</string>
+    <string name="retry" msgid="7497287909193345356">"重试"</string>
 </resources>
diff --git a/DeviceLockController/res/values-zh-rHK/strings.xml b/DeviceLockController/res/values-zh-rHK/strings.xml
index 9a3fb0a..ce5cea8 100644
--- a/DeviceLockController/res/values-zh-rHK/strings.xml
+++ b/DeviceLockController/res/values-zh-rHK/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"任何來自「<xliff:g id="CREDITOR_APP">%1$s</xliff:g>」的鎖定或解鎖要求"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"「<xliff:g id="CREDITOR_APP">%1$s</xliff:g>」應用程式是否無法使用"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"開放原始碼授權"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"「設定」&gt; [安全性] &gt; [受管理的裝置資料] "<b></b>"中的其他管理功能不適用於此裝置"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"喺安全性設定入面,分期付款裝置部分嘅管理功能套用唔到去呢部裝置"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"此裝置由「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」提供"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"系統將自動下載及安裝 Kiosk 應用程式"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"系統將為此使用者安裝 Kiosk 應用程式"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"如果你未按時支付款項,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可限制此裝置"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"如果你未按時支付款項,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可限制裝置。詳情請參閱《<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>條款及細則<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>》。"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"如果你未支付必要款項,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可限制此裝置。詳情請參閱《<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>條款及細則<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>》。"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"如果裝置擁有者未支付款項,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可限制此裝置"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"如需協助,請<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>聯絡「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>。"</string>
     <string name="previous" msgid="5241891780917802570">"返回"</string>
     <string name="next" msgid="8248291863254324326">"繼續"</string>
     <string name="start" msgid="2842214844667658537">"開始"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"資料"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"佈建資料"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"註冊裝置"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"裝置現可註冊「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」的分期付款計劃"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"裝置現可註冊「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」的分期付款計劃"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"裝置現可註冊「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」的資助計劃"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"你已加入「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」的資助計劃"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"裝置註冊"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可變更此裝置的設定"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"瞭解詳情"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"分期付款裝置資料"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"信貸提供者可在裝置上變更設定及安裝 Kiosk 應用程式。\n\n如果你未支付必要款項,或停止使用「<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>」的 SIM 卡,「<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>」可能會限制此裝置。\n\n如要瞭解詳情,請聯絡「<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>」。"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"「<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>」可在裝置上變更設定及安裝 Kiosk 應用程式。\n\n如果你未支付款項,「<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>」可能會限制此裝置。\n\n如要瞭解詳情,請聯絡「<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>」。"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"「<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>」可在裝置上變更設定及安裝 Kiosk 應用程式。\n\n如果你未支付款項,或停止使用「<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>」的 SIM 卡,「<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>」可能會限制此裝置。\n\n如要瞭解詳情,請聯絡「<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>」。"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"在支付裝置費用前,你無法執行以下操作:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"重新啟動裝置並進入安全模式"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"變更日期、時間和時區"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"使用開發人員選項"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"如果裝置發生問題,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可執行以下操作:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"你可解除安裝「<xliff:g id="KIOSK_APP">%1$s</xliff:g>」應用程式"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"如需協助:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>聯絡<xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"佈建"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{裝置將在 1 天後重設}other{裝置將在 # 天後重設}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"裝置將在 <xliff:g id="TIMER">%s</xliff:g>後重設"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"系統將會刪除所有裝置資料。如需有關註冊裝置的協助,請聯絡「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"如要繼續延後註冊裝置,請允許 DeviceLock 傳送通知。"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"無法佈建分期付款計劃"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"按一下即可查看分期付款提供者的聯絡方法。<xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>瞭解詳情<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"離開"</string>
+    <string name="retry" msgid="7497287909193345356">"重試"</string>
 </resources>
diff --git a/DeviceLockController/res/values-zh-rTW/strings.xml b/DeviceLockController/res/values-zh-rTW/strings.xml
index dcb9fe6..92ade51 100644
--- a/DeviceLockController/res/values-zh-rTW/strings.xml
+++ b/DeviceLockController/res/values-zh-rTW/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"任何來自「<xliff:g id="CREDITOR_APP">%1$s</xliff:g>」的鎖定或解鎖要求"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"「<xliff:g id="CREDITOR_APP">%1$s</xliff:g>」應用程式是否無法使用"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"開放原始碼授權"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"「設定」&gt;「安全性」&gt;「受管理的裝置資訊」"<b></b>"中的其他管理功能不適用於這部裝置"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"在安全性設定中,分期付款裝置部分的管理功能不適用於這部裝置。"</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"這部裝置是由「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」提供"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"系統將自動下載及安裝 Kiosk 應用程式"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"系統將為這名使用者安裝 Kiosk 應用程式"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"如果你未按時支付款項,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可以限制這部裝置"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"如果你未按時支付款項,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」就會對這部裝置設限。詳情請參閱《<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>條款及細則<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>》。"</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"如果你未支付必要款項,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可以限制這部裝置。詳情請參閱相關<xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>條款及細則<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>。"</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"如果裝置擁有者未支付款項,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可以限制這部裝置"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"如需協助,請<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>聯絡「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>。"</string>
     <string name="previous" msgid="5241891780917802570">"返回"</string>
     <string name="next" msgid="8248291863254324326">"繼續"</string>
     <string name="start" msgid="2842214844667658537">"開始"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"資訊"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"佈建資訊"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"註冊你的裝置"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"裝置現在就能註冊「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」分期付款計畫"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"現在可以為裝置註冊「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」分期付款計畫"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"裝置現在就能註冊「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」補助計畫"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"你已加入「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」補助計畫"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"裝置註冊"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可變更這部裝置的設定"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"瞭解詳情"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"分期付款裝置資訊"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"信貸提供者可在裝置上變更設定及安裝 Kiosk 軟體。\n\n如果你未支付必要款項,或是停止使用「<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>」的 SIM 卡,「<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>」可能會限制這部裝置。\n\n如要瞭解詳情,請與「<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>」聯絡。"</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"「<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>」可在裝置上變更設定及安裝資訊站應用程式。\n\n如果你未按時支付款項,「<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>」可能會限制你的裝置。\n\n詳情請洽「<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>」。"</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"「<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g>」可在裝置上變更設定及安裝資訊站應用程式。\n\n如果你未按時支付款項,或停止使用「<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>」的 SIM 卡,「<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>」也可能會限制這部裝置。\n\n詳情請洽「<xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>」。"</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"在支付裝置費用前,你無法執行下列操作:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"重新啟動裝置並進入安全模式"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"變更日期、時間和時區"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"使用開發人員選項"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"如果裝置發生問題,「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」可執行下列操作:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"你可以解除安裝「<xliff:g id="KIOSK_APP">%1$s</xliff:g>」應用程式"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"如何尋求協助:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>聯絡「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」<xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"佈建"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{裝置將在 1 天後重設}other{裝置將在 # 天後重設}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"裝置將在 <xliff:g id="TIMER">%s</xliff:g>後重設"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"所有裝置資料皆會刪除。如需有關註冊裝置的協助,請與「<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>」聯絡"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"如要繼續延後裝置註冊作業,請允許 DeviceLock 傳送通知。"</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"無法佈建分期付款計畫"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"按一下即可查看分期付款服務提供者的聯絡方式。<xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>瞭解詳情<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"結束"</string>
+    <string name="retry" msgid="7497287909193345356">"重試"</string>
 </resources>
diff --git a/DeviceLockController/res/values-zu/strings.xml b/DeviceLockController/res/values-zu/strings.xml
index be9bcb7..f738af8 100644
--- a/DeviceLockController/res/values-zu/strings.xml
+++ b/DeviceLockController/res/values-zu/strings.xml
@@ -44,14 +44,13 @@
     <string name="exposure_lock_unlock_text" msgid="6827412845847260579">"Noma yiziphi izicelo zokukhiya noma ukuvula ezivela ku-<xliff:g id="CREDITOR_APP">%1$s</xliff:g>"</string>
     <string name="exposure_disable_dlc_text" msgid="2898692398106736423">"Uma i-app ye-<xliff:g id="CREDITOR_APP">%1$s</xliff:g> ingatholakali"</string>
     <string name="open_source_licenses" msgid="6464389386262455443">"Amalayisensi omthombo ovulekile"</string>
-    <string name="footer_notice" msgid="7606898520964750584">"Amanye amakhono okuphatha kokuthi "<b>"Amasethingi &gt; Ukuvikeleka &gt; Nolwazi lwedivayisi ephethwe"</b>" awasebenzi kule divayisi"</string>
     <string name="footer_notice_content_description" msgid="2160540400079419440">"Amandla wokuphatha esigabeni sedivayisi enikwe imali samasethingi wokuphepha awasebenzi kule divayisi."</string>
     <string name="device_provided_by_provider" msgid="290593329676291991">"Le divayisi ihlinzekwa yi-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="download_kiosk_app" msgid="1845089944897502656">"I-app ye-Kiosk izodawunilodwa futhi ifakwe ngokuzenzekelayo"</string>
     <string name="install_kiosk_app_secondary_user" msgid="49911908012320834">"I-app ye-Kiosk izofakwa kulo msebenzisi"</string>
-    <string name="restrict_device_if_missing_payment" msgid="5721216628714899148">"I-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ingakhawula le divayisi uma uphethelwa inkokhelo"</string>
+    <string name="restrict_device_if_missing_payment" msgid="8883980285859496904">"I-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ingabekela idivayisi imingcele uma ungakhokhile. Ukuze uthole imininingwane, buka <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Imigomo Nemibandela<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="restrict_device_if_dont_make_payment" msgid="1619095674945507015">"I-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ingakhawula le divayisi uma ungenzi izinkokhelo ezidingekayo. Ukuze uthole imininingwane, buka <xliff:g id="TERMS_AND_CONDITIONS_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Imigomo Nemibandela<xliff:g id="TERMS_AND_CONDITIONS_LINK_END">&lt;/a&gt;</xliff:g>."</string>
-    <string name="restrict_device_if_owner_doesnt_make_payment" msgid="3841412765931627895">"I-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ingakhawula le divayisi uma umnikazi engakhokhi"</string>
+    <string name="contact_provider_for_help" msgid="3872028089834808884">"Ukuthola usizo, <xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>xhumana no-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>."</string>
     <string name="previous" msgid="5241891780917802570">"Okudlule"</string>
     <string name="next" msgid="8248291863254324326">"Okulandelayo"</string>
     <string name="start" msgid="2842214844667658537">"Qala"</string>
@@ -61,7 +60,7 @@
     <string name="header_icon_content_description" msgid="6069602031334473195">"Ulwazi"</string>
     <string name="provision_info_item_icon_content_description" msgid="2306298178610632507">"Ulwazi lwelungiselelo"</string>
     <string name="enroll_your_device_header" msgid="2226305405591945098">"Bhalisa idivayisi yakho"</string>
-    <string name="enroll_your_device_financing_subheader" msgid="7378414469334757425">"Usungakwazi ubhalisa idivayisi ohlelweni lokuxhasa lwe-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
+    <string name="enroll_your_device_financing_subheader" msgid="8810608106273097451">"Usungakwazi manje ukubhalisa idivayisi yakho ohlelweni lwezezimali lwe-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="enroll_your_device_subsidy_subheader" msgid="8598730780370624995">"Usungakwazi manje ukubhalisa idivayisi yakho ohlelweni losizo lwe-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="subsidy_program_header" msgid="2321508488856303554">"Usohlelweni losizo lwe-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
     <string name="device_enrollment_header_text" msgid="5283341102404741658">"Ukubhaliswa kwedivayisa"</string>
@@ -82,7 +81,8 @@
     <string name="settings_banner_body" msgid="5814902066260202824">"I-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ingashintsha amasetingi kule divayisi"</string>
     <string name="settings_banner_button" msgid="1831020849782670907">"Funda kabanzi"</string>
     <string name="settings_screen_title" msgid="721470080648091035">"Ulwazi lwedivayisi oluhlinzekwe ngezezimali"</string>
-    <string name="settings_intro" msgid="5809531331925309396">"Umhlinzeki wakho wekhredithi angashintsha amasethingi futhi afake i-app ye-Kiosk kudivayisi.\n\nI-<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> ingase ikhawule le divayisi uma ungayenzi inkokhelo edingekayo noma uyeka ukusebenzisa i-SIM ye-<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g>.\n\nUkuze ufunde kabanzi, thinta <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_financing" msgid="2548476558131048133">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> angashintsha amasethingi bese efaka i-app ye-Kiosk kudivayisi.\n\nUma uphuthwa ukukhokha, <xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> angavimbela idivayisi yakho.\n\nUkuze ufunde kabanzi, xhumana <xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>."</string>
+    <string name="settings_intro_device_subsidy" msgid="4274945644204818702">"<xliff:g id="PROVIDER_NAME_0">%1$s</xliff:g> angashintsha amasethingi bese efaka i-app ye-Kiosk kudivayisi.\n\n<xliff:g id="PROVIDER_NAME_1">%1$s</xliff:g> kungenzeka futhi avimbele le divayisi uma uphuthwa ukukhokha noma uyeka ukusebenzisa i-SIM ye-<xliff:g id="PROVIDER_NAME_2">%1$s</xliff:g>.\n\nUkuze ufunde okwengeziwe, xhumana <xliff:g id="PROVIDER_NAME_3">%1$s</xliff:g>."</string>
     <string name="settings_intro_preference_key" msgid="6610461073400554162">"settings_intro_preference_key"</string>
     <string name="settings_restrictions_category" msgid="5746868117342406677">"Kuze kube yilapho usukhokhele idivayisi yakho, awukwazi:"</string>
     <string name="settings_restrictions_category_preference_key" msgid="88318147152676512">"settings_restrictions_category_preference_key"</string>
@@ -90,8 +90,6 @@
     <string name="settings_install_apps_preference_key" msgid="27542314345238427">"settings_install_apps_preference_key"</string>
     <string name="settings_safe_mode" msgid="3035228015586375153">"Qalisa idivayisi yakho kumodi ephephile"</string>
     <string name="settings_safe_mode_preference_key" msgid="2106617747358027424">"settings_safe_mode_preference_key"</string>
-    <string name="settings_config_date_time" msgid="3406612829802458778">"Shintsha ilanga, isikhathi, nezoni yesikhathi"</string>
-    <string name="settings_config_date_time_preference_key" msgid="1838160765185598823">"settings_config_date_time_preference_key"</string>
     <string name="settings_developer_options" msgid="880701002025216672">"Sebenzisa okungakhwethwa konjiniyela"</string>
     <string name="settings_developer_options_preference_key" msgid="6807036808722582954">"settings_developer_options_preference_key"</string>
     <string name="settings_credit_provider_capabilities_category" msgid="1274440595211820868">"Uma okuthile kungahambi kahle ngedivayisi yakho, i-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g> ingakwazi:"</string>
@@ -118,8 +116,16 @@
     <string name="settings_restrictions_removed_preference_key" msgid="7741933477145197391">"settings_restrictions_removed_preference_key"</string>
     <string name="settings_uninstall_kiosk_app" msgid="2611134364295637875">"Ungakwazi ukukhipha i-app ye-<xliff:g id="KIOSK_APP">%1$s</xliff:g>"</string>
     <string name="settings_uninstall_kiosk_app_preference_key" msgid="5578103644009268125">"settings_uninstall_kiosk_app_preference_key"</string>
+    <string name="settings_support_category" msgid="7210906871924935770">"Ukuthola usizo:"</string>
+    <string name="settings_support_category_preference_key" msgid="1818953199283261021">"settings_support_category_preference_key"</string>
+    <string name="settings_contact_provider" msgid="2481819956474692039">"<xliff:g id="SUPPORT_LINK_START">&lt;a href=%2$s&gt;</xliff:g>Xhumana ne-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g><xliff:g id="SUPPORT_LINK_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="settings_contact_provider_preference_key" msgid="2703619536229342624">"settings_contact_provider_preference_key"</string>
     <string name="provision_notification_channel_name" msgid="6123500714047647805">"Ilungiselelo"</string>
     <string name="device_reset_in_days_notification_title" msgid="920859483535317727">"{count,plural, =1{Idivayisi izosethwa kabusha osukwini olungu-1}one{Idivayisi izosethwa kabusha ezinsukwini ezingu-#}other{Idivayisi izosethwa kabusha ezinsukwini ezingu-#}}"</string>
+    <string name="device_reset_timer_notification_title" msgid="301978346002711614">"Idivayisi izosethwa kabusha ngo-<xliff:g id="TIMER">%s</xliff:g>"</string>
     <string name="device_reset_notification_content" msgid="7642367488663440437">"Yonke idatha yedivayisi izosulwa. Ukuze uthole usizo lokubhalisa idivayisi yakho, thinta i-<xliff:g id="PROVIDER_NAME">%1$s</xliff:g>"</string>
-    <string name="toast_message_grant_notification_permission" msgid="1902770796685661160">"Sicela uvumele isaziso esisuka ku-DeviceLock ukuze uqhubeke nokudlulisa ukubhaliswa kwedivayisi."</string>
+    <string name="provisioning_failed" msgid="5350252817004028300">"Ukuxhaswa kwelungiselelo kuhlulekile"</string>
+    <string name="click_to_contact_financier" msgid="9107827438262930445">"Sicela uchofoze lapha ukuze uthole izindlela zokuthinta umxhasi wakho wezezimali. <xliff:g id="SUPPORT_URL_START">&lt;a href=%1$s&gt;</xliff:g>Funda kabanzi<xliff:g id="SUPPORT_URL_END">&lt;/a&gt;</xliff:g>"</string>
+    <string name="exit" msgid="645084771882733921">"Phuma"</string>
+    <string name="retry" msgid="7497287909193345356">"Zama futhi"</string>
 </resources>
diff --git a/DeviceLockController/res/values/colors.xml b/DeviceLockController/res/values/colors.xml
index 3c0858b..2d37b0a 100644
--- a/DeviceLockController/res/values/colors.xml
+++ b/DeviceLockController/res/values/colors.xml
@@ -17,4 +17,5 @@
 
 <resources>
     <color name="divider_color">#E4E4E4</color>
+    <color name="notification_background_color">#82ABFB</color>
 </resources>
diff --git a/DeviceLockController/res/values/config.xml b/DeviceLockController/res/values/config.xml
index f2e4edc..5245bca 100644
--- a/DeviceLockController/res/values/config.xml
+++ b/DeviceLockController/res/values/config.xml
@@ -16,11 +16,9 @@
 
 <resources>
     <!-- Allowed device identifiers bitmap -->
-    <integer name="device_id_type_bitmap">3</integer>
+    <integer name="device_id_type_bitmap">0</integer>
     <!-- Packages allow-listed in locked mode -->
-    <array name="lock_task_allowlist">
-        <item>com.android.devicelockcontroller</item>
-    </array>
+    <array name="lock_task_allowlist"/>
 
     <!-- Port number of the check in server -->
     <integer name="check_in_server_port_number">8843</integer>
@@ -47,4 +45,4 @@
     <string name="device_finalize_client_class_name">
         com.android.devicelockcontroller.provision.grpc.impl.DeviceFinalizeClientImpl
     </string>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/DeviceLockController/res/values/dimens.xml b/DeviceLockController/res/values/dimens.xml
new file mode 100644
index 0000000..2a5500e
--- /dev/null
+++ b/DeviceLockController/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 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.
+  -->
+
+<resources>
+    <dimen name="provision_screen_sub_header_text_size">16sp</dimen>
+</resources>
diff --git a/DeviceLockController/res/values/strings.xml b/DeviceLockController/res/values/strings.xml
index d74c683..e79807c 100644
--- a/DeviceLockController/res/values/strings.xml
+++ b/DeviceLockController/res/values/strings.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
   Copyright (c) 2022, The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
@@ -74,8 +73,6 @@
     <string name="exposure_disable_dlc_text">If the <xliff:g id="creditor_app">%1$s</xliff:g> app isn\'t available</string>
     <!-- Overflow menu describing open source licenses. [CHAR_LIMIT=80] -->
     <string name="open_source_licenses">Open-source licenses</string>
-    <!-- Informational text at the bottom of a screen. This text lets a user know that the info listed in the "Managed device info" section in Settings doesn't apply to their device. [CHAR_LIMIT=200] -->
-    <string name="footer_notice">The other management capabilities in <b>Settings > Security > Managed device info</b> don\'t apply to this device</string>
     <!-- Accessibility text for the footer notice. [CHAR_LIMIT=NONE] -->
     <string name="footer_notice_content_description">The management capabilities in the financed device section of Security settings don\'t apply to this device.</string>
     <!-- Text explaining that this device is provided by the device provider. [CHAR_LIMIT=80] -->
@@ -85,11 +82,11 @@
     <!-- Text explaining that the kiosk app will be installed for this newly created secondary user. [CHAR_LIMIT=NONE] -->
     <string name="install_kiosk_app_secondary_user">The Kiosk app will be installed for this user</string>
     <!-- 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>
+    <string name="restrict_device_if_missing_payment"><xliff:g id="provider name">%1$s</xliff:g> can restrict the device if you miss a payment. For details, view the <xliff:g id="terms_and_conditions_link_start">&lt;a href="%2$s"></xliff:g>Terms &amp; Conditions<xliff:g id="terms_and_conditions_link_end">&lt;/a&gt;</xliff:g>.</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 <xliff:g id="terms_and_conditions_link_start">&lt;a href="%2$s"></xliff:g>Terms &amp; Conditions<xliff:g id="terms_and_conditions_link_end">&lt;/a&gt;</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>
+    <!-- Text explaining that user can reach out to the device provider for help. [CHAR_LIMIT=NONE] -->
+    <string name="contact_provider_for_help">For help, <xliff:g id="support_link_start">&lt;a href="%2$s"></xliff:g>contact <xliff:g id="provider name">%1$s</xliff:g><xliff:g id="support_link_end">&lt;/a&gt;</xliff:g>.</string>
     <!-- Button text. This button lets a user go back to previous screen. [CHAR_LIMIT=20] -->
     <string name="previous">Previous</string>
     <!-- Button text. This button lets a user go to the next screen. [CHAR_LIMIT=20] -->
@@ -109,7 +106,7 @@
     <!-- Screen header text explaining that the user can now enroll this device into device financing program. [CHAR_LIMIT=40] -->
     <string name="enroll_your_device_header">Enroll your device</string>
     <!-- Screen subheader text explaining that the user can now enroll this device into device provider's device financing program. [CHAR_LIMIT=80] -->
-    <string name="enroll_your_device_financing_subheader">You can now enroll your device in <xliff:g id="provider name">%1$s</xliff:g>\'s financing program</string>
+    <string name="enroll_your_device_financing_subheader">You can now enroll your device in <xliff:g id="provider name">%1$s</xliff:g>\'s finance program</string>
     <!-- Screen subheader text explaining that the user can now enroll this device into device provider's device subsidy program. [CHAR_LIMIT=80]-->
     <string name="enroll_your_device_subsidy_subheader">You can now enroll your device in <xliff:g id="provider name">%1$s</xliff:g>\'s subsidy program</string>
     <!-- Screen header text explaining that the user is on a device subsidy program. [CHAR_LIMIT=40] -->
@@ -151,8 +148,10 @@
     <string name="settings_banner_button">Learn more</string>
     <!-- Title of the settings screen. This screen summarize what would happen on the device under a finance program. [CHAR_LIMIT=40]-->
     <string name="settings_screen_title">Financed device info</string>
-    <!-- Top introduction on the Settings screen, summarizing the changes a device provider can make to this device. [CHAR LIMIT=NONE] -->
-    <string name="settings_intro">Your credit provider can change settings and install the Kiosk app on the device.\n\n<xliff:g id="provider name">%1$s</xliff:g> may restrict this device if you don\u2019t make the necessary payments or stop using <xliff:g id="provider name">%1$s</xliff:g>\u2019s SIM.\n\nTo learn more, contact <xliff:g id="provider name">%1$s</xliff:g>.</string>
+    <!-- Top introduction on the Settings screen for device financing use case, summarizing the changes a device provider can make to this device. [CHAR LIMIT=NONE] -->
+    <string name="settings_intro_device_financing"><xliff:g id="provider name">%1$s</xliff:g> can change settings and install the Kiosk app on the device.\n\nIf you miss a payment, <xliff:g id="provider name">%1$s</xliff:g> can restrict your device.\n\nTo learn more, contact <xliff:g id="provider name">%1$s</xliff:g>.</string>
+    <!-- Top introduction on the Settings screen for device subsidy use case, summarizing the changes a credit provider can make to this device. [CHAR LIMIT=NONE] -->
+    <string name="settings_intro_device_subsidy"><xliff:g id="provider name">%1$s</xliff:g> can change settings and install the Kiosk app on the device.\n\n<xliff:g id="provider name">%1$s</xliff:g> may also restrict this device if you miss a payment or stop using <xliff:g id="provider name">%1$s</xliff:g>\u2019s SIM.\n\nTo learn more, contact <xliff:g id="provider name">%1$s</xliff:g>.</string>
     <!-- Key of the settings_intro Preference. translatable="false" -->
     <string name="settings_intro_preference_key">settings_intro_preference_key</string>
     <!-- Section header. This section shows what restrictions will be enforced on the device when it is financed / subsidized. [CHAR LIMIT=60] -->
@@ -167,10 +166,6 @@
     <string name="settings_safe_mode">Reboot your device into safe mode</string>
     <!-- Key of the settings_safe_mode Preference. translatable="false" -->
     <string name="settings_safe_mode_preference_key">settings_safe_mode_preference_key</string>
-    <!-- Label explaining that updating the date and time on the device. [CHAR LIMIT=60] -->
-    <string name="settings_config_date_time">Change date, time, and time zones</string>
-    <!-- Key of the settings_config_date_time Preference. translatable="false" -->
-    <string name="settings_config_date_time_preference_key">settings_config_date_time_preference_key</string>
     <!-- Label explaining that turning on the developer options on the device. [CHAR LIMIT=40]-->
     <string name="settings_developer_options">Use developer options</string>
     <!-- Key of the settings_developer_options Preference. translatable="false" -->
@@ -223,6 +218,14 @@
     <string name="settings_uninstall_kiosk_app">You can uninstall the <xliff:g id="kiosk_app">%1$s</xliff:g> app</string>
     <!-- Key of the settings_uninstall_kiosk_app Preference. translatable="false" -->
     <string name="settings_uninstall_kiosk_app_preference_key">settings_uninstall_kiosk_app_preference_key</string>
+    <!-- Section header. This sections shows what users can do if they need help. [CHAR LIMIT=60] -->
+    <string name="settings_support_category">To get help:</string>
+    <!-- Key of the settings_support_category preference. translatable="false" -->
+    <string name="settings_support_category_preference_key">settings_support_category_preference_key</string>
+    <!-- Label of a clickable URL text to let user to contact the device provider. [CHAR LIMIT=60] -->
+    <string name="settings_contact_provider"><xliff:g id="support_link_start">&lt;a href="%2$s"></xliff:g>Contact <xliff:g id="provider name">%1$s</xliff:g><xliff:g id="support_link_end">&lt;/a&gt;</xliff:g></string>
+    <!-- Key of the settings_contact_provider preference. translatable="false" -->
+    <string name="settings_contact_provider_preference_key">settings_contact_provider_preference_key</string>
     <!-- Name of a notification channel, the channel will be used to send provision related notifications. [CHAR LIMIT=40] -->
     <string name="provision_notification_channel_name">Provision</string>
     <!-- Title of the notification that device will be reset in days. [CHAR LIMIT=40] -->
@@ -232,9 +235,16 @@
             other {Device will reset in # days}
         }
     </string>
+    <!-- Title of the notification that device will be reset with a count down timer. [CHAR LIMIT=40] -->
+    <string name="device_reset_timer_notification_title">Device will reset in <xliff:g id="timer">%s</xliff:g></string>
     <!-- Content text of the notification that device will be reset. [CHAR LIMIT=NONE] -->
     <string name="device_reset_notification_content">All device data will be deleted. For help enrolling your device, contact <xliff:g id="provider name">%1$s</xliff:g></string>
-    <!-- TODO(b/279608060): Review this message with akintola@ -->
-    <!-- Toast message explaining why the user needs to grant permission to send notification. [CHAR LIMIT=NONE] -->
-    <string name="toast_message_grant_notification_permission">Please allow notification from DeviceLock to continue deferring the enrollment of the device.</string>
+    <!-- Title text of the provisioning failed screen, this tells the user provisioning of their device failed. [CHAR LIMIT=60] -->
+    <string name="provisioning_failed">Financing provisioning has failed</string>
+    <!-- Subheader of the provisioning failed screen, this tells the user to click the link to contact their financier for help. [CHAR LIMIT=NONE] -->
+    <string name="click_to_contact_financier">Please click here for ways to contact your financier. <xliff:g id="support_url_start">&lt;a href="%1$s"></xliff:g>Learn more<xliff:g id="support_url_end">&lt;/a&gt;</xliff:g></string>
+    <!-- Button text used to let the user exit the Device lock controller app. [CHAR LIMIT=20] -->
+    <string name="exit">Exit</string>
+    <!-- Button text used to let the user try provisioning one more time. [CHAR LIMIT=20] -->
+    <string name="retry">Retry</string>
 </resources>
diff --git a/DeviceLockController/res/xml/device_info_settings.xml b/DeviceLockController/res/xml/device_info_settings.xml
index dff92bc..c5ccaa4 100644
--- a/DeviceLockController/res/xml/device_info_settings.xml
+++ b/DeviceLockController/res/xml/device_info_settings.xml
@@ -18,8 +18,7 @@
                   android:title="@string/settings_screen_title">
 
     <com.android.settingslib.widget.TopIntroPreference
-        android:key="@string/settings_intro_preference_key"
-        android:title="@string/settings_intro"/>
+        android:key="@string/settings_intro_preference_key"/>
 
     <PreferenceCategory android:key="@string/settings_restrictions_category_preference_key"
                         android:order="100"
@@ -35,11 +34,6 @@
                     android:layout_height="wrap_content"
                     android:title="@string/settings_safe_mode"
                     android:selectable="false" />
-        <Preference android:key="@string/settings_config_date_time_preference_key"
-                    android:order="130"
-                    android:layout_height="wrap_content"
-                    android:title="@string/settings_config_date_time"
-                    android:selectable="false" />
         <Preference android:key="@string/settings_developer_options_preference_key"
                     android:order="140"
                     android:layout_height="wrap_content"
@@ -109,4 +103,17 @@
                     android:title="@string/settings_uninstall_kiosk_app"
                     android:selectable="false" />
     </PreferenceCategory>
+
+    <PreferenceCategory
+        android:key="@string/settings_support_category_preference_key"
+        android:order="500"
+        android:title="@string/settings_support_category"
+        android:contentDescription="@string/settings_support_category">
+        <com.android.devicelockcontroller.activities.UrlTextPreference
+            android:key="@string/settings_contact_provider_preference_key"
+            android:order="510"
+            android:layout_height="wrap_content"
+            android:title="@string/settings_contact_provider"
+            android:selectable="false" />
+    </PreferenceCategory>
 </PreferenceScreen>
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerApplication.java b/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerApplication.java
index 4af3c15..e4a89cd 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerApplication.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerApplication.java
@@ -18,86 +18,107 @@
 
 import android.app.Application;
 import android.content.Context;
-import android.os.UserManager;
 
-import androidx.annotation.MainThread;
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.work.Configuration;
 import androidx.work.DelegatingWorkerFactory;
 import androidx.work.ListenableWorker;
 
 import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.DevicePolicyControllerImpl;
 import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.policy.DeviceStateControllerImpl;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
-import com.android.devicelockcontroller.policy.SetupController;
-import com.android.devicelockcontroller.policy.SetupControllerImpl;
-import com.android.devicelockcontroller.policy.TaskWorkerFactory;
+import com.android.devicelockcontroller.policy.FinalizationController;
+import com.android.devicelockcontroller.policy.FinalizationControllerImpl;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.policy.ProvisionStateControllerImpl;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerImpl;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerImpl;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
 import com.android.devicelockcontroller.util.LogUtil;
 
-import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 
 /**
  * Application class for Device Lock Controller.
  */
 public class DeviceLockControllerApplication extends Application implements
-        PolicyObjectsInterface, Configuration.Provider {
+        PolicyObjectsProvider,
+        Configuration.Provider,
+        DeviceLockControllerSchedulerProvider,
+        FcmRegistrationTokenProvider,
+        PlayInstallPackageTaskClassProvider,
+        StatsLoggerProvider {
     private static final String TAG = "DeviceLockControllerApplication";
 
-    private DevicePolicyController mPolicyController;
-
     private static Context sApplicationContext;
-    private SetupController mSetupController;
+    @GuardedBy("this")
+    private ProvisionStateController mProvisionStateController;
+    @GuardedBy("this")
+    private FinalizationController mFinalizationController;
+    @GuardedBy("this")
+    private DeviceLockControllerScheduler mDeviceLockControllerScheduler;
+    @GuardedBy("this")
+    private StatsLogger mStatsLogger;
+
+    private WorkManagerExceptionHandler mWorkManagerExceptionHandler;
+
+    public DeviceLockControllerApplication() {
+        super();
+
+        mWorkManagerExceptionHandler = WorkManagerExceptionHandler.getInstance(this);
+    }
 
     @Override
     public void onCreate() {
         super.onCreate();
         sApplicationContext = getApplicationContext();
         LogUtil.i(TAG, "onCreate");
+    }
 
-        final boolean isUserProfile =
-                sApplicationContext.getSystemService(UserManager.class).isProfile();
+    @Override
+    public DeviceStateController getDeviceStateController() {
+        return getProvisionStateController().getDeviceStateController();
+    }
 
-        if (isUserProfile) {
-            return;
+    @Override
+    public synchronized ProvisionStateController getProvisionStateController() {
+        if (mProvisionStateController == null) {
+            mProvisionStateController = new ProvisionStateControllerImpl(this);
         }
-
-        // Make sure policies are enforced when the controller is started.
-        getStateController().enforcePoliciesForCurrentState().addListener(
-                () -> LogUtil.i(TAG, "Policies enforced"), MoreExecutors.directExecutor());
+        return mProvisionStateController;
     }
 
     @Override
-    @MainThread
-    public DeviceStateController getStateController() {
-        return getPolicyController().getStateController();
-    }
-
-    @Override
-    @MainThread
     public DevicePolicyController getPolicyController() {
-        if (mPolicyController == null) {
-            mPolicyController = new DevicePolicyControllerImpl(this,
-                    new DeviceStateControllerImpl(this));
-        }
-
-        return mPolicyController;
+        return getProvisionStateController().getDevicePolicyController();
     }
 
     @Override
-    public SetupController getSetupController() {
-        if (mSetupController == null) {
-            mSetupController = new SetupControllerImpl(this, getStateController(),
-                    getPolicyController());
+    public synchronized FinalizationController getFinalizationController() {
+        if (mFinalizationController == null) {
+            mFinalizationController = new FinalizationControllerImpl(this);
         }
-        return mSetupController;
+        return mFinalizationController;
     }
 
     @Override
-    public void destroyObjects() {
-        mPolicyController = null;
-        mSetupController = null;
+    public synchronized StatsLogger getStatsLogger() {
+        if (null == mStatsLogger) {
+            mStatsLogger = new StatsLoggerImpl();
+        }
+        return mStatsLogger;
+    }
+
+    @Override
+    public synchronized void destroyObjects() {
+        mProvisionStateController = null;
+        mFinalizationController = null;
     }
 
     public static Context getAppContext() {
@@ -108,15 +129,35 @@
     @Override
     public Configuration getWorkManagerConfiguration() {
         final DelegatingWorkerFactory factory = new DelegatingWorkerFactory();
-        factory.addFactory(new TaskWorkerFactory());
+        factory.addFactory(new DeviceLockControllerWorkerFactory());
         return new Configuration.Builder()
                 .setWorkerFactory(factory)
                 .setMinimumLoggingLevel(android.util.Log.INFO)
+                .setInitializationExceptionHandler(
+                        (t) -> mWorkManagerExceptionHandler
+                                .initializationExceptionHandler(this, t))
+                .setTaskExecutor(mWorkManagerExceptionHandler.getWorkManagerTaskExecutor())
                 .build();
     }
 
+    @Override
     @Nullable
     public Class<? extends ListenableWorker> getPlayInstallPackageTaskClass() {
         return null;
     }
+
+    @Override
+    @NonNull
+    public ListenableFuture<String> getFcmRegistrationToken() {
+        return Futures.immediateFuture(null);
+    }
+
+    @Override
+    public synchronized DeviceLockControllerScheduler getDeviceLockControllerScheduler() {
+        if (mDeviceLockControllerScheduler == null) {
+            mDeviceLockControllerScheduler = new DeviceLockControllerSchedulerImpl(this,
+                    getProvisionStateController());
+        }
+        return mDeviceLockControllerScheduler;
+    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerService.java b/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerService.java
index e9fd685..cf73709 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerService.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerService.java
@@ -16,94 +16,154 @@
 
 package com.android.devicelockcontroller;
 
-import static com.android.devicelockcontroller.IDeviceLockControllerService.KEY_HARDWARE_ID_RESULT;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.CLEAR;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.LOCK_DEVICE;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.UNLOCK_DEVICE;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_LOCKED;
-
 import android.app.Service;
+import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.devicelock.ParcelableException;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteCallback;
 
 import androidx.annotation.NonNull;
-import androidx.work.WorkManager;
+import androidx.annotation.Nullable;
 
 import com.android.devicelockcontroller.policy.DevicePolicyController;
 import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
-import com.android.devicelockcontroller.provision.worker.ReportDeviceLockProgramCompleteWorker;
+import com.android.devicelockcontroller.policy.FinalizationController;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
 import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.util.LogUtil;
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
+import java.util.List;
+import java.util.Objects;
+
 /**
  * Device Lock Controller Service. This is hosted in an APK and is bound
  * by the Device Lock System Service.
  */
 public final class DeviceLockControllerService extends Service {
     private static final String TAG = "DeviceLockControllerService";
+    private DeviceStateController mDeviceStateController;
     private DevicePolicyController mPolicyController;
-    private DeviceStateController mStateController;
+    private FinalizationController mFinalizationController;
+    private PackageManager mPackageManager;
+    private StatsLogger mStatsLogger;
 
     private final IDeviceLockControllerService.Stub mBinder =
             new IDeviceLockControllerService.Stub() {
                 @Override
                 public void lockDevice(RemoteCallback remoteCallback) {
-                    Futures.addCallback(
-                            Futures.transformAsync(
-                                    mStateController.setNextStateForEvent(LOCK_DEVICE),
-                                    (Void unused) -> mStateController.getState() == PSEUDO_LOCKED
-                                            ? Futures.immediateFuture(true)
-                                            : mPolicyController.launchActivityInLockedMode(),
-                                    DeviceLockControllerService.this.getMainExecutor()),
-                            remoteCallbackWrapper(remoteCallback, KEY_LOCK_DEVICE_RESULT),
+                    logKioskAppRequest();
+                    ListenableFuture<Void> lockDeviceFuture = mDeviceStateController.lockDevice();
+                    Futures.addCallback(lockDeviceFuture,
+                            remoteCallbackWrapper(remoteCallback),
+                            MoreExecutors.directExecutor());
+                    Futures.addCallback(lockDeviceFuture,
+                            logLockUnlockDeviceCallback(/* isLockDevice = */ true),
                             MoreExecutors.directExecutor());
                 }
 
                 @Override
                 public void unlockDevice(RemoteCallback remoteCallback) {
-                    Futures.addCallback(
-                            Futures.transform(
-                                    mStateController.setNextStateForEvent(UNLOCK_DEVICE),
-                                    (Void unused) -> true, MoreExecutors.directExecutor()),
-                            remoteCallbackWrapper(remoteCallback, KEY_UNLOCK_DEVICE_RESULT),
+                    logKioskAppRequest();
+                    ListenableFuture<Void> unlockDeviceFuture =
+                            mDeviceStateController.unlockDevice();
+                    Futures.addCallback(unlockDeviceFuture,
+                            remoteCallbackWrapper(remoteCallback),
                             MoreExecutors.directExecutor());
-
+                    Futures.addCallback(unlockDeviceFuture,
+                            logLockUnlockDeviceCallback(/* isLockDevice = */ false),
+                            MoreExecutors.directExecutor());
                 }
 
                 @Override
                 public void isDeviceLocked(RemoteCallback remoteCallback) {
-                    final boolean isLocked = mStateController.isLocked();
-                    sendResult(IDeviceLockControllerService.KEY_IS_DEVICE_LOCKED_RESULT,
-                            remoteCallback, isLocked);
+                    logKioskAppRequest();
+                    Futures.addCallback(mDeviceStateController.isLocked(),
+                            remoteCallbackWrapper(remoteCallback, KEY_RESULT),
+                            MoreExecutors.directExecutor());
                 }
 
                 @Override
                 public void getDeviceIdentifier(RemoteCallback remoteCallback) {
+                    logKioskAppRequest();
                     Futures.addCallback(
                             GlobalParametersClient.getInstance().getRegisteredDeviceId(),
-                            remoteCallbackWrapper(remoteCallback, KEY_HARDWARE_ID_RESULT),
+                            remoteCallbackWrapper(remoteCallback, KEY_RESULT),
                             MoreExecutors.directExecutor());
                 }
 
                 @Override
                 public void clearDeviceRestrictions(RemoteCallback remoteCallback) {
+                    logKioskAppRequest();
                     Futures.addCallback(
-                            Futures.transform(mStateController.setNextStateForEvent(CLEAR),
-                                    (Void unused) -> {
-                                        WorkManager workManager =
-                                                WorkManager.getInstance(getApplicationContext());
-                                        ReportDeviceLockProgramCompleteWorker
-                                                .reportDeviceLockProgramComplete(workManager);
-                                        return true;
-                                    }, MoreExecutors.directExecutor()),
-                            remoteCallbackWrapper(remoteCallback, KEY_CLEAR_DEVICE_RESULT),
+                            Futures.transformAsync(mDeviceStateController.clearDevice(),
+                                    unused -> mFinalizationController.notifyRestrictionsCleared(),
+                                    MoreExecutors.directExecutor()),
+                            remoteCallbackWrapper(remoteCallback),
+                            MoreExecutors.directExecutor());
+                }
+
+                @Override
+                public void onUserSwitching(RemoteCallback remoteCallback) {
+                    Futures.addCallback(mPolicyController.enforceCurrentPolicies(),
+                            remoteCallbackWrapper(remoteCallback),
+                            MoreExecutors.directExecutor());
+                }
+
+                @Override
+                public void onUserUnlocked(RemoteCallback remoteCallback) {
+                    DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
+                    Objects.requireNonNull(dpm).setUserControlDisabledPackages(
+                            /* admin= */ null,
+                            List.of(getPackageName()));
+                    Futures.addCallback(mPolicyController.onUserUnlocked(),
+                            remoteCallbackWrapper(remoteCallback),
+                            MoreExecutors.directExecutor());
+                }
+
+                @Override
+                public void onUserSetupCompleted(RemoteCallback remoteCallback) {
+                    Futures.addCallback(mPolicyController.onUserSetupCompleted(),
+                            remoteCallbackWrapper(remoteCallback),
+                            MoreExecutors.directExecutor());
+                }
+
+                @Override
+                public void onAppCrashed(boolean isKiosk, RemoteCallback remoteCallback) {
+                    Futures.addCallback(mPolicyController.onAppCrashed(isKiosk),
+                            remoteCallbackWrapper(remoteCallback),
+                            MoreExecutors.directExecutor());
+                }
+
+                private void logKioskAppRequest() {
+                    Futures.addCallback(SetupParametersClient.getInstance().getKioskPackage(),
+                            new FutureCallback<>() {
+                                @Override
+                                public void onSuccess(String result) {
+                                    try {
+                                        final int uid = mPackageManager.getPackageUid(
+                                                result, /* flags= */ 0);
+                                        mStatsLogger.logKioskAppRequest(uid);
+                                    } catch (PackageManager.NameNotFoundException e) {
+                                        LogUtil.e(TAG, "Kiosk App package name not found", e);
+                                    }
+                                }
+
+                                @Override
+                                public void onFailure(Throwable t) {
+                                    LogUtil.e(TAG, "Failed to get Kiosk app package name", t);
+                                }
+                            },
                             MoreExecutors.directExecutor());
 
                 }
@@ -111,7 +171,7 @@
 
     @NonNull
     private static FutureCallback<Object> remoteCallbackWrapper(RemoteCallback remoteCallback,
-            final String key) {
+            @Nullable final String key) {
         return new FutureCallback<>() {
             @Override
             public void onSuccess(Object result) {
@@ -121,28 +181,106 @@
             @Override
             public void onFailure(Throwable t) {
                 LogUtil.e(TAG, "Failed to perform the request", t);
-                sendResult(key, remoteCallback, null);
+                sendFailure(t, remoteCallback);
             }
         };
     }
 
-    private static void sendResult(String key, RemoteCallback remoteCallback, Object result) {
+    @NonNull
+    private static FutureCallback<Object> remoteCallbackWrapper(RemoteCallback remoteCallback) {
+        return remoteCallbackWrapper(remoteCallback, /* key= */ null);
+    }
+
+    /**
+     * Send result to caller.
+     *
+     * @param key Key to use in bundle for result. null if no result is needed
+     * @param remoteCallback remote callback used to send the result.
+     * @param result Value to return in bundle.
+     */
+    private static void sendResult(@Nullable String key, RemoteCallback remoteCallback,
+            Object result) {
         final Bundle bundle = new Bundle();
-        if (result instanceof Boolean) {
-            bundle.putBoolean(key, (Boolean) result);
-        } else if (result instanceof String) {
-            bundle.putString(key, (String) result);
+        if (key != null) {
+            if (result instanceof Boolean) {
+                bundle.putBoolean(key, (Boolean) result);
+            } else if (result instanceof String) {
+                bundle.putString(key, (String) result);
+            }
         }
         remoteCallback.sendResult(bundle);
     }
 
+    private static void sendFailure(Throwable t, RemoteCallback remoteCallback) {
+        final Bundle bundle = new Bundle();
+        bundle.putParcelable(IDeviceLockControllerService.KEY_PARCELABLE_EXCEPTION,
+                new ParcelableException(t instanceof Exception ? (Exception) t : new Exception(t)));
+        remoteCallback.sendResult(bundle);
+    }
+
+    private FutureCallback<Void> logLockUnlockDeviceCallback(boolean isLockDevice) {
+        return new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(Void result) {
+                if (isLockDevice) {
+                    mStatsLogger.logSuccessfulLockingDevice();
+                } else {
+                    mStatsLogger.logSuccessfulUnlockingDevice();
+                }
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                Futures.addCallback(mDeviceStateController.getDeviceState(),
+                        new FutureCallback<Integer>() {
+                            @Override
+                            public void onSuccess(Integer result) {
+                                int deviceStatePostCommand;
+                                switch (result) {
+                                    case DeviceStateController.DeviceState.UNLOCKED ->
+                                            deviceStatePostCommand =
+                                                    StatsLogger.DeviceStateStats.UNLOCKED;
+                                    case DeviceStateController.DeviceState.LOCKED ->
+                                            deviceStatePostCommand =
+                                                    StatsLogger.DeviceStateStats.LOCKED;
+                                    case DeviceStateController.DeviceState.CLEARED ->
+                                            deviceStatePostCommand =
+                                                    StatsLogger.DeviceStateStats.CLEARED;
+                                    case DeviceStateController.DeviceState.UNDEFINED ->
+                                            deviceStatePostCommand =
+                                                    StatsLogger.DeviceStateStats.UNDEFINED;
+                                    default -> deviceStatePostCommand =
+                                            StatsLogger.DeviceStateStats.UNDEFINED;
+                                }
+                                if (isLockDevice) {
+                                    mStatsLogger.logLockDeviceFailure(deviceStatePostCommand);
+                                } else {
+                                    mStatsLogger.logUnlockDeviceFailure(deviceStatePostCommand);
+                                }
+                            }
+
+                            // We don't expect this to be reached
+                            @Override
+                            public void onFailure(Throwable t) {
+                                LogUtil.e(TAG, "Failed to get device State", t);
+                                throw new RuntimeException(t);
+                            }
+                        }, MoreExecutors.directExecutor());
+            }
+        };
+    }
+
     @Override
     public void onCreate() {
         LogUtil.d(TAG, "onCreate");
 
-        final PolicyObjectsInterface policyObjects = (PolicyObjectsInterface) getApplication();
-        mStateController = policyObjects.getStateController();
+        final PolicyObjectsProvider policyObjects = (PolicyObjectsProvider) getApplication();
+        final StatsLoggerProvider statsLoggerProvider = (StatsLoggerProvider) getApplication();
+        mDeviceStateController = policyObjects.getDeviceStateController();
         mPolicyController = policyObjects.getPolicyController();
+        mFinalizationController = policyObjects.getFinalizationController();
+        mPackageManager = getPackageManager();
+        mStatsLogger = statsLoggerProvider.getStatsLogger();
     }
 
     @Override
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerWorkerFactory.java b/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerWorkerFactory.java
new file mode 100644
index 0000000..69ebf18
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/DeviceLockControllerWorkerFactory.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.work.ListenableWorker;
+import androidx.work.WorkerFactory;
+import androidx.work.WorkerParameters;
+
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.Executors;
+
+/** A factory which produces {@link ListenableWorker}s with parameters. */
+public final class DeviceLockControllerWorkerFactory extends WorkerFactory {
+    private static final String TAG = "DeviceLockControllerWorkerFactory";
+
+    private static final ListeningExecutorService sExecutorService =
+            MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
+
+    @Nullable
+    @Override
+    public ListenableWorker createWorker(
+            @NonNull Context context,
+            @NonNull String workerClassName,
+            @NonNull WorkerParameters workerParameters) {
+        ListenableWorker worker = null;
+        Class<?> clazz = null;
+        try {
+            clazz = Class.forName(workerClassName);
+        } catch (ClassNotFoundException e) {
+            LogUtil.e(TAG, "Can not find class for name: " + workerClassName, e);
+        }
+
+        if (clazz != null) {
+            try {
+                worker = (ListenableWorker) clazz.getConstructor(
+                                Context.class,
+                                WorkerParameters.class,
+                                ListeningExecutorService.class)
+                        .newInstance(context, workerParameters, sExecutorService);
+            } catch (InstantiationException | IllegalAccessException
+                     | InvocationTargetException | NoSuchMethodException e) {
+                // Unable to create the instance by this WorkerFactory
+                LogUtil.i(TAG, "Delegating to default WorkerFactory to create: " + workerClassName,
+                        e);
+            }
+        }
+        return worker;
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/FcmRegistrationTokenProvider.java b/DeviceLockController/src/com/android/devicelockcontroller/FcmRegistrationTokenProvider.java
new file mode 100644
index 0000000..af2062a
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/FcmRegistrationTokenProvider.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller;
+
+import androidx.annotation.NonNull;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Interface to retrieve FCM registration token.
+ */
+public interface FcmRegistrationTokenProvider {
+
+    /**
+     * Returns the FCM registration token.
+     */
+    @NonNull
+    ListenableFuture<String> getFcmRegistrationToken();
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/IDeviceLockControllerService.aidl b/DeviceLockController/src/com/android/devicelockcontroller/IDeviceLockControllerService.aidl
index 28431bf..bbc8cff 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/IDeviceLockControllerService.aidl
+++ b/DeviceLockController/src/com/android/devicelockcontroller/IDeviceLockControllerService.aidl
@@ -23,18 +23,64 @@
  * {@hide}
  */
 oneway interface IDeviceLockControllerService {
-    const String KEY_LOCK_DEVICE_RESULT = "KEY_LOCK_DEVICE_RESULT";
+    /**
+     * Key used to store the result (return value) of a call.
+     */
+    const String KEY_RESULT = "KEY_RESULT";
+
+    /**
+     * Key used to store a ParcelableException.
+     */
+    const String KEY_PARCELABLE_EXCEPTION = "KEY_PARCELABLE_EXCEPTION";
+
+    /**
+     * Locks the device.
+     */
     void lockDevice(in RemoteCallback callback);
 
-    const String KEY_UNLOCK_DEVICE_RESULT = "KEY_UNLOCK_DEVICE_RESULT";
+    /**
+     * Unlocks the device.
+     */
     void unlockDevice(in RemoteCallback callback);
 
-    const String KEY_IS_DEVICE_LOCKED_RESULT = "KEY_IS_DEVICE_LOCKED_RESULT";
+    /**
+     * Outputs true result if device is locked.
+     */
     void isDeviceLocked(in RemoteCallback callback);
 
-    const String KEY_HARDWARE_ID_RESULT = "KEY_HARDWARE_ID_RESULT";
+    /**
+     * Gets the device identifier.
+     */
     void getDeviceIdentifier(in RemoteCallback callback);
 
-    const String KEY_CLEAR_DEVICE_RESULT = "KEY_CLEAR_DEVICE_RESULT";
+    /**
+     * Clears all device restrictions which removes the device from further policy management.
+     */
     void clearDeviceRestrictions(in RemoteCallback callback);
+
+    /**
+     * Called when a user has just been switched to.
+     *
+     * Unlike the system service equivalent, this is NOT guaranteed to called in order with other
+     * lifecycle events (e.g. before onUserUnlocked).
+     */
+    void onUserSwitching(in RemoteCallback callback);
+
+    /**
+     * Called when a user has been unlocked and credential encrypted storage is available.
+     *
+     * Unlike the system service equivalent, this is NOT guaranteed to called in order with other
+     * lifecycle events (e.g. after onUserSwitching).
+     */
+    void onUserUnlocked(in RemoteCallback callback);
+
+    /**
+     * Called when a user has completed set-up wizard.
+     */
+    void onUserSetupCompleted(in RemoteCallback callback);
+
+    /**
+     * Called when the controller or kiosk app has crashed.
+     */
+    void onAppCrashed(in boolean isKiosk, in RemoteCallback callback);
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/PlayInstallPackageTaskClassProvider.java b/DeviceLockController/src/com/android/devicelockcontroller/PlayInstallPackageTaskClassProvider.java
new file mode 100644
index 0000000..3cbb892
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/PlayInstallPackageTaskClassProvider.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller;
+
+import androidx.annotation.Nullable;
+import androidx.work.ListenableWorker;
+
+/**
+ * Interface to provide the PlayInstallPackageTaskClass.
+ */
+public interface PlayInstallPackageTaskClassProvider {
+
+    /**
+     * Returns PlayInstallPackageTaskClass.
+     */
+    @Nullable
+    Class<? extends ListenableWorker> getPlayInstallPackageTaskClass();
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/SystemDeviceLockManager.java b/DeviceLockController/src/com/android/devicelockcontroller/SystemDeviceLockManager.java
index e77168d..e664c49 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/SystemDeviceLockManager.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/SystemDeviceLockManager.java
@@ -17,6 +17,7 @@
 package com.android.devicelockcontroller;
 
 import android.annotation.CallbackExecutor;
+import android.annotation.RequiresPermission;
 import android.os.OutcomeReceiver;
 
 import androidx.annotation.NonNull;
@@ -28,13 +29,18 @@
  * Stopgap: these should have been SystemApis on DeviceLockManager.
  */
 public interface SystemDeviceLockManager {
+    String MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER =
+            "com.android.devicelockcontroller.permission."
+                    + "MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER";
+
     /**
      * Add the FINANCED_DEVICE_KIOSK role to the specified package.
      *
      * @param packageName package for the financed device kiosk app.
-     * @param executor the {@link Executor} on which to invoke the callback.
-     * @param callback this returns either success or an exception.
+     * @param executor    the {@link Executor} on which to invoke the callback.
+     * @param callback    this returns either success or an exception.
      */
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
     void addFinancedDeviceKioskRole(@NonNull String packageName,
             @CallbackExecutor Executor executor,
             @NonNull OutcomeReceiver<Void, Exception> callback);
@@ -43,34 +49,113 @@
      * Remove the FINANCED_DEVICE_KIOSK role from the specified package.
      *
      * @param packageName package for the financed device kiosk app.
-     * @param executor the {@link Executor} on which to invoke the callback.
-     * @param callback this returns either success or an exception.
+     * @param executor    the {@link Executor} on which to invoke the callback.
+     * @param callback    this returns either success or an exception.
      */
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
     void removeFinancedDeviceKioskRole(@NonNull String packageName,
             @CallbackExecutor Executor executor,
             @NonNull OutcomeReceiver<Void, Exception> callback);
 
     /**
-     * Set the Device Lock Controller exempt from restrictions about starting activities
-     * from the background (for the calling user).
+     * Set the exemption state for activity background start restriction for dlc.
      *
-     * @param exempt true if the Controller should be exempt from the restriction.
-     * @param executor the {@link Executor} on which to invoke the callback.
-     * @param callback callback this returns either success or an exception.
+     * @param exempt if true, dlc will be set to exempt from activity background start
+     *               restriction; false, the exemption state will be set to default.
      */
-    void setExemptFromActivityBackgroundStartRestriction(boolean exempt,
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
+    void setDlcExemptFromActivityBgStartRestrictionState(boolean exempt,
             @CallbackExecutor Executor executor,
             @NonNull OutcomeReceiver<Void, Exception> callback);
 
     /**
-     * Set the kiosk app exempt from hibernation (for the calling user).
+     * Set whether the dlc should be allowed to send undismissible notifications
+     *
+     * @param allowed if true, dlc can send undimissible notifications
+     */
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
+    void setDlcAllowedToSendUndismissibleNotifications(boolean allowed,
+            @CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback);
+
+    /**
+     * Set the exemption state of app restrictions (e.g. hibernation, battery and data usage) for
+     * kiosk app.
      *
      * @param packageName kiosk app package name.
-     * @param exempt true if the Controller should be exempt from hibernation.
+     * @param exempt      if true, the given uid will be set to exempt from app restrictions (e.g.
+     *                    hibernation, battery and data usage restriction); false, the exemption
+     *                    state will be set to default.
+     * @param executor    the {@link Executor} on which to invoke the callback.
+     * @param callback    callback this returns either success or an exception.
+     */
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
+    void setKioskAppExemptFromRestrictionsState(String packageName, boolean exempt,
+            @CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback);
+
+    /**
+     * Enable kiosk keepalive, making sure the kiosk app is restarted on crash.
+     *
+     * @param packageName kiosk app package name.
+     * @param executor    the {@link Executor} on which to invoke the callback.
+     * @param callback    callback this returns either success or an exception.
+     */
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
+    void enableKioskKeepalive(String packageName, @CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback);
+
+    /**
+     * Disable kiosk keepalive.
+     *
      * @param executor the {@link Executor} on which to invoke the callback.
      * @param callback callback this returns either success or an exception.
      */
-    void setExemptFromHibernation(String packageName, boolean exempt,
-            @CallbackExecutor Executor executor,
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
+    void disableKioskKeepalive(@CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback);
+
+    /**
+     * Enable controller keepalive, making sure DLC is restarted on crash.
+     *
+     * @param executor the {@link Executor} on which to invoke the callback.
+     * @param callback callback this returns either success or an exception.
+     */
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
+    void enableControllerKeepalive(@CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback);
+
+    /**
+     * Disable controller keepalive.
+     *
+     * @param executor the {@link Executor} on which to invoke the callback.
+     * @param callback callback this returns either success or an exception.
+     */
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
+    void disableControllerKeepalive(@CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback);
+
+    /**
+     * Set whether device is finalized so that system service knows when to keep the Device Lock
+     * Controller enabled.
+     *
+     * @param finalized true if device is finalized and DLC should not be enabled.
+     * @param executor  the {@link Executor} on which to invoke the callback.
+     * @param callback  callback this returns either success or an exception.
+     */
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
+    void setDeviceFinalized(boolean finalized, @CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback);
+
+    /**
+     * Set or clear the POST_NOTIFICATIONS permission as SYSTEM_FIXED, so it cannot be revoked
+     * in Settings.
+     *
+     * @param systemFixed true if POST_NOTIFICATIONS should be SYSTEM_FIXED.
+     * @param executor    the {@link Executor} on which to invoke the callback.
+     * @param callback    callback this returns either success or an exception.
+     */
+    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
+    void setPostNotificationsSystemFixed(boolean systemFixed, Executor executor,
             @NonNull OutcomeReceiver<Void, Exception> callback);
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/SystemDeviceLockManagerImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/SystemDeviceLockManagerImpl.java
index 9bde80b..93540ae 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/SystemDeviceLockManagerImpl.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/SystemDeviceLockManagerImpl.java
@@ -17,10 +17,12 @@
 package com.android.devicelockcontroller;
 
 import android.annotation.CallbackExecutor;
-import android.annotation.RequiresPermission;
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.PackageInfoFlags;
 import android.devicelock.DeviceLockManager;
 import android.devicelock.IDeviceLockService;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.OutcomeReceiver;
@@ -39,14 +41,12 @@
     private static final String TAG = "SystemDeviceLockManagerImpl";
 
     private final IDeviceLockService mIDeviceLockService;
-
-    private static final String MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER =
-            "com.android.devicelockcontroller.permission."
-                    + "MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER";
+    private final Context mContext;
 
     private SystemDeviceLockManagerImpl(Context context) {
-        final DeviceLockManager deviceLockManager =
-                context.getSystemService(DeviceLockManager.class);
+        mContext = context;
+        final DeviceLockManager deviceLockManager = context.getSystemService(
+                DeviceLockManager.class);
 
         mIDeviceLockService = deviceLockManager.getService();
     }
@@ -69,7 +69,6 @@
     }
 
     @Override
-    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
     public void addFinancedDeviceKioskRole(@NonNull String packageName,
             @CallbackExecutor Executor executor,
             @NonNull OutcomeReceiver<Void, Exception> callback) {
@@ -79,14 +78,8 @@
         try {
             mIDeviceLockService.addFinancedDeviceKioskRole(packageName,
                     new RemoteCallback(result -> executor.execute(() -> {
-                        final boolean roleAdded = result.getBoolean(
-                                IDeviceLockService.KEY_REMOTE_CALLBACK_RESULT);
-                        if (roleAdded) {
-                            callback.onResult(null /* result */);
-                        } else {
-                            callback.onError(new Exception("Failed to add financed role to: "
-                                    + packageName));
-                        }
+                        processResult(result, callback,
+                                "Failed to add financed role to: " + packageName);
                     }), new Handler(Looper.getMainLooper())));
         } catch (RemoteException e) {
             executor.execute(() -> callback.onError(new RuntimeException(e)));
@@ -94,7 +87,6 @@
     }
 
     @Override
-    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
     public void removeFinancedDeviceKioskRole(@NonNull String packageName,
             @CallbackExecutor Executor executor,
             @NonNull OutcomeReceiver<Void, Exception> callback) {
@@ -104,14 +96,8 @@
         try {
             mIDeviceLockService.removeFinancedDeviceKioskRole(packageName,
                     new RemoteCallback(result -> executor.execute(() -> {
-                        final boolean roleRemoved = result.getBoolean(
-                                IDeviceLockService.KEY_REMOTE_CALLBACK_RESULT);
-                        if (roleRemoved) {
-                            callback.onResult(null /* result */);
-                        } else {
-                            callback.onError(new Exception("Failed to remove financed role from: "
-                                    + packageName));
-                        }
+                        processResult(result, callback,
+                                "Failed to remove financed role from: " + packageName);
                     }), new Handler(Looper.getMainLooper())));
         } catch (RemoteException e) {
             executor.execute(() -> callback.onError(new RuntimeException(e)));
@@ -119,25 +105,18 @@
     }
 
     @Override
-    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
-    public void setExemptFromActivityBackgroundStartRestriction(boolean exempt,
+    public void setDlcExemptFromActivityBgStartRestrictionState(boolean exempt,
             @CallbackExecutor Executor executor,
             @NonNull OutcomeReceiver<Void, Exception> callback) {
         Objects.requireNonNull(executor);
         Objects.requireNonNull(callback);
 
         try {
-            mIDeviceLockService.setExemptFromActivityBackgroundStartRestriction(exempt,
+            mIDeviceLockService.setCallerExemptFromActivityBgStartRestrictionState(exempt,
                     new RemoteCallback(result -> executor.execute(() -> {
-                        final boolean restrictionChanged = result.getBoolean(
-                                IDeviceLockService.KEY_REMOTE_CALLBACK_RESULT);
-                        if (restrictionChanged) {
-                            callback.onResult(null /* result */);
-                        } else {
-                            callback.onError(new Exception("Failed to change exempt from "
-                                    + "activity background start to: "
-                                    + (exempt ? "exempt" : "non exempt")));
-                        }
+                        processResult(result, callback,
+                                "Failed to change exempt from activity background start to: "
+                                        + (exempt ? "exempt" : "non exempt"));
                     }), new Handler(Looper.getMainLooper())));
         } catch (RemoteException e) {
             executor.execute(() -> callback.onError(new RuntimeException(e)));
@@ -145,30 +124,150 @@
     }
 
     @Override
-    @RequiresPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER)
-    public void setExemptFromHibernation(String packageName, boolean exempt,
+    public void setDlcAllowedToSendUndismissibleNotifications(boolean allowed,
             @CallbackExecutor Executor executor,
             @NonNull OutcomeReceiver<Void, Exception> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            mIDeviceLockService.setCallerAllowedToSendUndismissibleNotifications(allowed,
+                    new RemoteCallback(result -> executor.execute(() -> {
+                        processResult(result, callback,
+                                "Failed to change undismissible notifs allowed to: "
+                                        + (allowed ? "allowed" : "not allowed"));
+                    }), new Handler(Looper.getMainLooper())));
+        } catch (RemoteException e) {
+            executor.execute(() -> callback.onError(new RuntimeException(e)));
+        }
+    }
+
+    @Override
+    public void setKioskAppExemptFromRestrictionsState(String packageName, boolean exempt,
+            Executor executor, @NonNull OutcomeReceiver<Void, Exception> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            int kioskUid = mContext.getPackageManager().getPackageUid(packageName,
+                    PackageInfoFlags.of(0));
+            mIDeviceLockService.setUidExemptFromRestrictionsState(kioskUid, exempt,
+                    new RemoteCallback(result -> executor.execute(() -> {
+                        processResult(result, callback, "Failed to exempt for UID: " + kioskUid);
+                    }), new Handler(Looper.getMainLooper())));
+        } catch (RemoteException | PackageManager.NameNotFoundException e) {
+            executor.execute(() -> callback.onError(new RuntimeException(e)));
+        }
+    }
+
+    @Override
+    public void enableKioskKeepalive(String packageName, Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback) {
         Objects.requireNonNull(packageName);
         Objects.requireNonNull(executor);
         Objects.requireNonNull(callback);
 
         try {
-            mIDeviceLockService.setExemptFromHibernation(packageName, exempt,
+            mIDeviceLockService.enableKioskKeepalive(packageName,
                     new RemoteCallback(result -> executor.execute(() -> {
-                        final boolean restrictionChanged = result.getBoolean(
-                                IDeviceLockService.KEY_REMOTE_CALLBACK_RESULT);
-                        if (restrictionChanged) {
-                            callback.onResult(null /* result */);
-                        } else {
-                            callback.onError(new Exception("Failed to change exempt from "
-                                    + "hibernation to: "
-                                    + (exempt ? "exempt" : "non exempt") + " for package: "
-                                    + packageName));
-                        }
+                        processResult(result, callback,
+                                "Failed to enable kiosk keep-alive for package: "
+                                        + packageName);
                     }), new Handler(Looper.getMainLooper())));
         } catch (RemoteException e) {
             executor.execute(() -> callback.onError(new RuntimeException(e)));
         }
     }
+
+    @Override
+    public void disableKioskKeepalive(Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            mIDeviceLockService.disableKioskKeepalive(
+                    new RemoteCallback(result -> executor.execute(() -> {
+                        processResult(result, callback, "Failed to disable kiosk keep-alive");
+                    }), new Handler(Looper.getMainLooper())));
+        } catch (RemoteException e) {
+            executor.execute(() -> callback.onError(new RuntimeException(e)));
+        }
+    }
+
+    @Override
+    public void enableControllerKeepalive(Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            mIDeviceLockService.enableControllerKeepalive(
+                    new RemoteCallback(result -> executor.execute(() -> {
+                        processResult(result, callback, "Failed to enable controller keep-alive");
+                    }), new Handler(Looper.getMainLooper())));
+        } catch (RemoteException e) {
+            executor.execute(() -> callback.onError(new RuntimeException(e)));
+        }
+    }
+
+    @Override
+    public void disableControllerKeepalive(Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            mIDeviceLockService.disableControllerKeepalive(
+                    new RemoteCallback(result -> executor.execute(() -> {
+                        processResult(result, callback, "Failed to disable controller keep-alive");
+                    }), new Handler(Looper.getMainLooper())));
+        } catch (RemoteException e) {
+            executor.execute(() -> callback.onError(new RuntimeException(e)));
+        }
+    }
+
+    @Override
+    public void setDeviceFinalized(boolean finalized, Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            mIDeviceLockService.setDeviceFinalized(finalized,
+                    new RemoteCallback(result -> executor.execute(() -> {
+                        processResult(result, callback, "Failed to set device finalized");
+                    }), new Handler(Looper.getMainLooper())));
+        } catch (RemoteException e) {
+            executor.execute(() -> callback.onError(new RuntimeException(e)));
+        }
+    }
+
+    @Override
+    public void setPostNotificationsSystemFixed(boolean systemFixed, Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            mIDeviceLockService.setPostNotificationsSystemFixed(systemFixed,
+                    new RemoteCallback(result -> executor.execute(() -> {
+                        processResult(result, callback, "Failed to change POST_NOTIFICATIONS "
+                                + "SYSTEM_FIXED flag to: " + systemFixed);
+                    }), new Handler(Looper.getMainLooper())));
+        } catch (RemoteException e) {
+            executor.execute(() -> callback.onError(new RuntimeException(e)));
+        }
+    }
+
+    private static void processResult(Bundle result,
+            @NonNull OutcomeReceiver<Void, Exception> callback, String message) {
+        final boolean remoteCallbackResult = result.getBoolean(
+                IDeviceLockService.KEY_REMOTE_CALLBACK_RESULT);
+        if (remoteCallbackResult) {
+            callback.onResult(null /* result */);
+        } else {
+            callback.onError(new Exception(message));
+        }
+    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/WorkManagerExceptionHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/WorkManagerExceptionHandler.java
new file mode 100644
index 0000000..da5b4ec
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/WorkManagerExceptionHandler.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller;
+
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED;
+
+import android.annotation.IntDef;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.sqlite.SQLiteException;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.devicelockcontroller.policy.DevicePolicyController;
+import com.android.devicelockcontroller.policy.DeviceStateController;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.time.Duration;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Attempt to recover from failed check ins due to disk full.
+ */
+public final class WorkManagerExceptionHandler implements Thread.UncaughtExceptionHandler {
+    private static final String TAG = "WorkManagerExceptionHandler";
+
+    private static final long RETRY_ALARM_MILLISECONDS = Duration.ofHours(1).toMillis();
+
+    @VisibleForTesting
+    public static final String ALARM_REASON = "ALARM_REASON";
+
+    private final Executor mWorkManagerTaskExecutor;
+    private final Runnable mTerminateRunnable;
+    private static volatile WorkManagerExceptionHandler sWorkManagerExceptionHandler;
+
+    /** Alarm reason definitions. */
+    @Target(ElementType.TYPE_USE)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            AlarmReason.INITIAL_CHECK_IN,
+            AlarmReason.RETRY_CHECK_IN,
+            AlarmReason.RESCHEDULE_CHECK_IN,
+            AlarmReason.INITIALIZATION,
+    })
+    public @interface AlarmReason {
+        int INITIAL_CHECK_IN = 0;
+        int RETRY_CHECK_IN = 1;
+        int RESCHEDULE_CHECK_IN = 2;
+        int INITIALIZATION = 3;
+    }
+
+    /**
+     * Receiver to handle alarms scheduled upon failure to enqueue check-in work due to
+     * SQLite exceptions, or WorkManager initialization failures.
+     * This receiver tries to recover the check-in process, if still needed.
+     */
+    public static final class WorkFailureAlarmReceiver extends BroadcastReceiver {
+        private final Executor mExecutor = Executors.newSingleThreadExecutor();
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (!WorkFailureAlarmReceiver.class.getName().equals(intent.getComponent()
+                    .getClassName())) {
+                throw new IllegalArgumentException("Can not handle implicit intent!");
+            }
+
+            final Bundle bundle = intent.getExtras();
+            if (bundle == null) {
+                throw new IllegalArgumentException("Intent has no bundle");
+            }
+
+            final @AlarmReason int alarmReason = bundle.getInt(ALARM_REASON, -1 /* undefined */);
+            if (alarmReason < 0) {
+                throw new IllegalArgumentException("Missing alarm reason");
+            }
+
+            LogUtil.i(TAG, "Received alarm to recover from WorkManager exception with reason: "
+                    + alarmReason);
+
+            final PendingResult pendingResult = goAsync();
+
+            final ListenableFuture<Void> checkInIfNotYetProvisioned =
+                    Futures.transformAsync(GlobalParametersClient.getInstance().isProvisionReady(),
+                            isProvisionReady -> {
+                                if (isProvisionReady) {
+                                    // Already provisioned, no need to check in
+                                    return Futures.immediateVoidFuture();
+                                } else {
+                                    return getCheckInFuture(context, alarmReason);
+                                }
+                            }, mExecutor);
+
+            Futures.addCallback(checkInIfNotYetProvisioned, new FutureCallback<>() {
+                @Override
+                public void onSuccess(Void result) {
+                    LogUtil.i(TAG, "Successfully scheduled check in after WorkManager exception");
+                    pendingResult.finish();
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                    LogUtil.e(TAG, "Failed to schedule check in after WorkManager exception", t);
+                    pendingResult.finish();
+                }
+            }, mExecutor);
+        }
+
+        private ListenableFuture<Void> getCheckInFuture(Context context,
+                @AlarmReason int alarmReason) {
+            final DeviceLockControllerSchedulerProvider schedulerProvider =
+                    (DeviceLockControllerSchedulerProvider) context.getApplicationContext();
+            final DeviceLockControllerScheduler scheduler =
+                    schedulerProvider.getDeviceLockControllerScheduler();
+
+            ListenableFuture<Void> checkInOperation;
+
+            switch (alarmReason) {
+                case AlarmReason.INITIAL_CHECK_IN:
+                case AlarmReason.INITIALIZATION:
+                    checkInOperation = scheduler.maybeScheduleInitialCheckIn();
+                    break;
+                case AlarmReason.RETRY_CHECK_IN:
+                    // Use zero as delay since this is a corner case. We will eventually get the
+                    // proper value from the server.
+                    checkInOperation = scheduler.scheduleRetryCheckInWork(Duration.ZERO);
+                    break;
+                case AlarmReason.RESCHEDULE_CHECK_IN:
+                    checkInOperation = scheduler.notifyNeedRescheduleCheckIn();
+                    break;
+                default:
+                    throw new IllegalArgumentException("Invalid alarm reason");
+            }
+
+            return checkInOperation;
+        }
+    }
+
+    private Executor createWorkManagerTaskExecutor(Context context) {
+        final ThreadFactory threadFactory = new ThreadFactory() {
+            private final AtomicInteger mThreadCount = new AtomicInteger(0);
+            @Override
+            public Thread newThread(Runnable r) {
+                Thread thread = new DlcWmThread(context, r,
+                        "DLC.WorkManager.task-" + mThreadCount.incrementAndGet());
+                thread.setUncaughtExceptionHandler(WorkManagerExceptionHandler.this);
+                return thread;
+            }
+        };
+        // Same as the one used by WorkManager internally.
+        return Executors.newFixedThreadPool(Math.max(2,
+                Math.min(Runtime.getRuntime().availableProcessors() - 1, 4)), threadFactory);
+    }
+
+    private static final class DlcWmThread extends Thread {
+        private final Thread.UncaughtExceptionHandler mOriginalUncaughtExceptionHandler;
+        private final Context mContext;
+
+        DlcWmThread(Context context, Runnable target, String name) {
+            super(target, name);
+            mContext = context;
+            mOriginalUncaughtExceptionHandler = getUncaughtExceptionHandler();
+        }
+
+        UncaughtExceptionHandler getOriginalUncaughtExceptionHandler() {
+            return mOriginalUncaughtExceptionHandler;
+        }
+
+        Context getContext() {
+            return mContext;
+        }
+    }
+
+    /**
+     * Schedule an alarm to restart the check in process in case of critical failures.
+     * This is called if we failed to enqueue the check in work.
+     */
+    public static void scheduleAlarm(Context context, @AlarmReason int alarmReason) {
+        final AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
+        final Intent intent = new Intent(context, WorkFailureAlarmReceiver.class);
+        final Bundle bundle = new Bundle();
+        bundle.putInt(ALARM_REASON, alarmReason);
+        intent.putExtras(bundle);
+        final PendingIntent alarmIntent =
+                PendingIntent.getBroadcast(context, /* requestCode = */ 0, intent,
+                        PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
+
+        alarmManager.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()
+                + RETRY_ALARM_MILLISECONDS, alarmIntent);
+        LogUtil.i(TAG, "Alarm scheduled, reason: " + alarmReason);
+    }
+
+    /**
+     * Schedule an alarm to restart the app in case of critical failures.
+     * This is called if we failed to initialize WorkManager.
+     */
+    public void scheduleAlarmAndTerminate(Context context, @AlarmReason int alarmReason) {
+        scheduleAlarm(context, alarmReason);
+        // Terminate the process without calling the original uncaught exception handler,
+        // otherwise the alarm may be canceled if there are several crashes in a short period
+        // of time (similar to what happens in the force stopped case).
+        LogUtil.i(TAG, "Terminating Device Lock Controller because of a critical failure.");
+        mTerminateRunnable.run();
+    }
+
+    @VisibleForTesting
+    WorkManagerExceptionHandler(Context context, Runnable terminateRunnable) {
+        mWorkManagerTaskExecutor = createWorkManagerTaskExecutor(context);
+        mTerminateRunnable = terminateRunnable;
+    }
+
+    /**
+     * Get the only instance of WorkManagerExceptionHandler.
+     */
+    public static WorkManagerExceptionHandler getInstance(Context context) {
+        if (sWorkManagerExceptionHandler == null) {
+            synchronized (WorkManagerExceptionHandler.class) {
+                if (sWorkManagerExceptionHandler == null) {
+                    sWorkManagerExceptionHandler = new WorkManagerExceptionHandler(context,
+                            () -> System.exit(0));
+                }
+            }
+        }
+
+        return sWorkManagerExceptionHandler;
+    }
+
+    Executor getWorkManagerTaskExecutor() {
+        return mWorkManagerTaskExecutor;
+    }
+
+    // Called when one of the internal task threads of WorkManager throws an exception.
+    // We're interested in some exceptions subclass of SQLiteException (like SQLiteFullException)
+    // since it's not handled in initializationExceptionHandler.
+    @Override
+    public void uncaughtException(Thread t, Throwable e) {
+        LogUtil.e(TAG, "Uncaught exception in WorkManager task", e);
+        if (!(t instanceof DlcWmThread)) {
+            throw new RuntimeException("Thread is not a DlcWmThread", e);
+        }
+
+        if (e instanceof SQLiteException) {
+            handleWorkManagerException(((DlcWmThread) t).getContext(), e);
+        } else {
+            final Thread.UncaughtExceptionHandler originalExceptionHandler =
+                    ((DlcWmThread) t).getOriginalUncaughtExceptionHandler();
+
+            originalExceptionHandler.uncaughtException(t, e);
+        }
+    }
+
+    private void handleWorkManagerException(Context context, Throwable t) {
+        Futures.addCallback(handleException(context, t), new FutureCallback<>() {
+            @Override
+            public void onSuccess(Void result) {
+                // No-op
+            }
+
+            @Override
+            public void onFailure(Throwable e) {
+                LogUtil.e(TAG, "Error handling WorkManager exception", e);
+            }
+        }, mWorkManagerTaskExecutor);
+    }
+
+    // This is setup in WM configuration and is called when initialization fails. It does not
+    // include the SQLiteFullException case.
+    void initializationExceptionHandler(Context context, Throwable t) {
+        LogUtil.e(TAG, "WorkManager initialization error", t);
+
+        handleWorkManagerException(context, t);
+    }
+
+    @VisibleForTesting
+    ListenableFuture<Void> handleException(Context context, Throwable t) {
+        final Context applicationContext = context.getApplicationContext();
+        final PolicyObjectsProvider policyObjectsProvider =
+                (PolicyObjectsProvider) applicationContext;
+        final ProvisionStateController provisionStateController =
+                policyObjectsProvider.getProvisionStateController();
+        final DeviceStateController deviceStateController =
+                policyObjectsProvider.getDeviceStateController();
+        final ListenableFuture<@ProvisionState Integer> provisionStateFuture =
+                provisionStateController.getState();
+        final ListenableFuture<Boolean> isClearedFuture = deviceStateController.isCleared();
+
+        return Futures.whenAllSucceed(provisionStateFuture, isClearedFuture).call(() -> {
+            final @ProvisionState Integer provisionState = Futures.getDone(provisionStateFuture);
+            if (provisionState == UNPROVISIONED) {
+                scheduleAlarmAndTerminate(context, AlarmReason.INITIALIZATION);
+            } else if (!Futures.getDone(isClearedFuture)) {
+                LogUtil.e(TAG, "Resetting device, current provisioning state: "
+                        + provisionState, t);
+                final DevicePolicyController devicePolicyController =
+                        policyObjectsProvider.getPolicyController();
+                devicePolicyController.wipeDevice();
+            } else {
+                LogUtil.w(TAG, "Device won't be reset (restrictions cleared)");
+            }
+            return null;
+        }, mWorkManagerTaskExecutor);
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceEnrollmentActivity.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceEnrollmentActivity.java
deleted file mode 100644
index ee1a44d..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceEnrollmentActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import android.os.Bundle;
-
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
-
-import com.android.devicelockcontroller.R;
-
-/**
- * A screen that tells the user their device will be enrolled.
- */
-public final class DeviceEnrollmentActivity extends AppCompatActivity {
-
-    @Override
-    protected void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_device_enrollment);
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceEnrollmentInfoFragment.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceEnrollmentInfoFragment.java
deleted file mode 100644
index f1deeb9..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceEnrollmentInfoFragment.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_DEFERRED_PROVISIONING;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_ENROLLMENT;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_SUBSIDY_DEFERRED_PROVISIONING;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_SUBSIDY_ENROLLMENT;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.lifecycle.ViewModelProvider;
-
-import com.android.devicelockcontroller.R;
-import com.android.devicelockcontroller.util.LogUtil;
-
-import java.util.Objects;
-
-/**
- * A fragment which tells the user the details of the device enrollment.
- */
-public final class DeviceEnrollmentInfoFragment extends Fragment {
-
-    private static final String TAG = "DeviceEnrollmentInfoFragment";
-
-    @Nullable
-    @Override
-    public View onCreateView(
-            @NonNull LayoutInflater inflater,
-            @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.fragment_device_enrollment_info, container, false);
-    }
-
-    @Override
-    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-
-        DeviceEnrollmentInfoViewModel viewModel;
-        switch (Objects.requireNonNull(getActivity()).getIntent().getAction()) {
-            case ACTION_START_DEVICE_FINANCING_ENROLLMENT:
-                viewModel = new ViewModelProvider(this).get(
-                        DeviceFinancingEnrollmentInfoViewModel.class);
-                break;
-            case ACTION_START_DEVICE_SUBSIDY_ENROLLMENT:
-                viewModel = new ViewModelProvider(this).get(
-                        DeviceSubsidyEnrollmentInfoViewModel.class);
-                break;
-            default:
-                LogUtil.e(TAG, "Unknown action is received, exiting");
-                return;
-        }
-        ImageView imageView = view.findViewById(R.id.header_icon);
-        checkNotNull(imageView);
-        viewModel.mHeaderDrawableIdLiveData.observe(getViewLifecycleOwner(),
-                imageView::setImageResource);
-
-        TextView headerTextView = view.findViewById(R.id.header_text);
-        checkNotNull(headerTextView);
-        viewModel.mHeaderTextLiveData.observe(getViewLifecycleOwner(),
-                pair -> {
-                    if (pair.first > 0 && !TextUtils.isEmpty(pair.second)) {
-                        headerTextView.setText(getString(pair.first, pair.second));
-                    }
-                });
-
-        TextView bodyTextView = view.findViewById(R.id.body_text);
-        checkNotNull(bodyTextView);
-        viewModel.mBodyTextLiveData.observe(getViewLifecycleOwner(),
-                pair -> {
-                    if (pair.first > 0 && !TextUtils.isEmpty(pair.second)) {
-                        bodyTextView.setText(getString(pair.first, pair.second));
-                    }
-                });
-
-        Button button = view.findViewById(R.id.button_ok);
-        checkNotNull(button);
-        button.setOnClickListener(
-                v -> {
-                    // TODO(b/279445733): Ideally OK button should finish the activity, and the
-                    //  LandingActivity should be pop up automatically when enrollment is due. Hook
-                    //  them together for now to facilitate UI / A11Y verification test.
-                    Intent intent = new Intent();
-                    if (viewModel instanceof DeviceFinancingEnrollmentInfoViewModel) {
-                        intent.setAction(ACTION_START_DEVICE_FINANCING_DEFERRED_PROVISIONING);
-                    } else {
-                        intent.setAction(ACTION_START_DEVICE_SUBSIDY_DEFERRED_PROVISIONING);
-                    }
-                    intent.setComponent(
-                            new ComponentName(requireContext(), LandingActivity.class));
-                    startActivity(intent);
-                });
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceEnrollmentInfoViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceEnrollmentInfoViewModel.java
deleted file mode 100644
index 1aa180d..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceEnrollmentInfoViewModel.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import android.text.TextUtils;
-import android.util.Pair;
-
-import androidx.lifecycle.MediatorLiveData;
-import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.ViewModel;
-
-import com.android.devicelockcontroller.storage.SetupParametersClient;
-import com.android.devicelockcontroller.util.LogUtil;
-
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.MoreExecutors;
-
-/**
- * Generic abstract ViewModel for device enrollment info data.
- */
-abstract class DeviceEnrollmentInfoViewModel extends ViewModel {
-
-    private static final String TAG = "DeviceEnrollmentInfoViewModel";
-    private static final String PROVIDER_NAME_PLACEHOLDER = "";
-    private static final int TEXT_ID_PLACEHOLDER = -1;
-    final MutableLiveData<Integer> mHeaderDrawableIdLiveData;
-    final MutableLiveData<Integer> mHeaderTextIdLiveData;
-    final MutableLiveData<String> mProviderNameLiveData;
-    final MediatorLiveData<Pair<Integer, String>> mHeaderTextLiveData;
-    final MutableLiveData<Integer> mBodyTextIdLiveData;
-    final MediatorLiveData<Pair<Integer, String>> mBodyTextLiveData;
-
-    DeviceEnrollmentInfoViewModel() {
-        mHeaderDrawableIdLiveData = new MutableLiveData<>();
-        mHeaderTextIdLiveData = new MutableLiveData<>();
-
-        mProviderNameLiveData = new MutableLiveData<>();
-        mHeaderTextLiveData = new MediatorLiveData<>();
-        mHeaderTextLiveData.addSource(mHeaderTextIdLiveData,
-                id -> {
-                    Pair<Integer, String> oldValue = mHeaderTextLiveData.getValue();
-                    mHeaderTextLiveData.setValue(oldValue == null
-                            ? new Pair<>(id, PROVIDER_NAME_PLACEHOLDER)
-                            : new Pair<>(id, oldValue.second));
-                });
-        mHeaderTextLiveData.addSource(mProviderNameLiveData,
-                providerName -> {
-                    Pair<Integer, String> oldValue = mHeaderTextLiveData.getValue();
-                    mHeaderTextLiveData.setValue(oldValue == null
-                            ? new Pair<>(TEXT_ID_PLACEHOLDER, providerName)
-                            : new Pair<>(oldValue.first, providerName));
-
-                });
-        mBodyTextIdLiveData = new MutableLiveData<>();
-        mBodyTextLiveData = new MediatorLiveData<>();
-        mBodyTextLiveData.addSource(mBodyTextIdLiveData,
-                id -> {
-                    Pair<Integer, String> oldValue = mBodyTextLiveData.getValue();
-                    mBodyTextLiveData.setValue(oldValue == null
-                            ? new Pair<>(id, PROVIDER_NAME_PLACEHOLDER)
-                            : new Pair<>(id, oldValue.second));
-                });
-        mBodyTextLiveData.addSource(mProviderNameLiveData,
-                providerName -> {
-                    Pair<Integer, String> oldValue = mBodyTextLiveData.getValue();
-                    mBodyTextLiveData.setValue(oldValue == null
-                            ? new Pair<>(TEXT_ID_PLACEHOLDER, providerName)
-                            : new Pair<>(oldValue.first, providerName));
-                });
-        Futures.addCallback(SetupParametersClient.getInstance().getKioskAppProviderName(),
-                new FutureCallback<>() {
-                    @Override
-                    public void onSuccess(String providerName) {
-                        if (TextUtils.isEmpty(providerName)) {
-                            LogUtil.e(TAG, "Device provider name is empty, should not reach here.");
-                            return;
-                        }
-                        mProviderNameLiveData.postValue(providerName);
-                    }
-
-                    @Override
-                    public void onFailure(Throwable t) {
-                        LogUtil.e(TAG, "Failed to get Kiosk app provider name", t);
-                    }
-                }, MoreExecutors.directExecutor());
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingDeferredProvisionInfoViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingDeferredProvisionInfoViewModel.java
deleted file mode 100644
index 0ee14af..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingDeferredProvisionInfoViewModel.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import com.android.devicelockcontroller.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class provides resources and data used for the deferred provisioning flow of the device
- * financing use case.
- */
-public final class DeviceFinancingDeferredProvisionInfoViewModel extends ProvisionInfoViewModel {
-
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_info_24px;
-
-    private static final int HEADER_TEXT_ID = R.string.enroll_your_device_header;
-
-    private static final int SUBHEADER_TEXT_ID = R.string.enroll_your_device_financing_subheader;
-
-    private static final Integer[] DRAWABLE_IDS = new Integer[]{
-            R.drawable.ic_file_download_24px, R.drawable.ic_lock_outline_24px,
-    };
-
-    private static final Integer[] TEXT_IDS = new Integer[]{
-            R.string.download_kiosk_app, R.string.restrict_device_if_missing_payment,
-    };
-
-    public DeviceFinancingDeferredProvisionInfoViewModel() {
-        super();
-
-        mHeaderDrawableIdLiveData.setValue(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData.setValue(HEADER_TEXT_ID);
-        mSubheaderTextIdLiveData.setValue(SUBHEADER_TEXT_ID);
-        List<ProvisionInfo> provisionInfoList = new ArrayList<>();
-        for (int i = 0, size = DRAWABLE_IDS.length; i < size; ++i) {
-            provisionInfoList.add(new ProvisionInfo(DRAWABLE_IDS[i], TEXT_IDS[i]));
-        }
-        mProvisionInfoListLiveData.setValue(provisionInfoList);
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingEnrollmentInfoViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingEnrollmentInfoViewModel.java
deleted file mode 100644
index f254fd8..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingEnrollmentInfoViewModel.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import com.android.devicelockcontroller.R;
-
-/**
- * This class provides data about the device enrollment in the device financing use case.
- */
-public final class DeviceFinancingEnrollmentInfoViewModel extends DeviceEnrollmentInfoViewModel {
-
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_calendar_today_24px;
-
-    private static final int HEADER_TEXT_ID = R.string.device_enrollment_header_text;
-
-    private static final int BODY_TEXT_ID = R.string.device_financing_enrollment_body_text;
-
-    DeviceFinancingEnrollmentInfoViewModel() {
-        super();
-        mHeaderDrawableIdLiveData.setValue(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData.setValue(HEADER_TEXT_ID);
-        mBodyTextIdLiveData.setValue(BODY_TEXT_ID);
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingProvisionInfoViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingProvisionInfoViewModel.java
index 5914a21..248bb9d 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingProvisionInfoViewModel.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingProvisionInfoViewModel.java
@@ -16,9 +16,11 @@
 
 package com.android.devicelockcontroller.activities;
 
-import com.android.devicelockcontroller.R;
+import androidx.annotation.VisibleForTesting;
 
-import java.util.ArrayList;
+import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.activities.ProvisionInfo.ProvisionInfoType;
+
 import java.util.List;
 
 /**
@@ -26,28 +28,25 @@
  */
 public class DeviceFinancingProvisionInfoViewModel extends ProvisionInfoViewModel {
 
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_info_24px;
+    private static final int MANDATORY_HEADER_TEXT_ID = R.string.device_provided_by_provider;
+    private static final int SUB_HEADER_TEXT_ID = R.string.enroll_your_device_financing_subheader;
 
-    private static final int HEADER_TEXT_ID = R.string.device_provided_by_provider;
-
-    private static final Integer[] DRAWABLE_IDS = new Integer[]{
-            R.drawable.ic_file_download_24px, R.drawable.ic_lock_outline_24px,
-    };
-
-    private static final Integer[] TEXT_IDS = new Integer[]{
-            R.string.download_kiosk_app, R.string.restrict_device_if_missing_payment,
-    };
+    @VisibleForTesting
+    static final ProvisionInfo[] PROVISION_INFOS = new ProvisionInfo[]{
+            new ProvisionInfo(R.drawable.ic_file_download_24px,
+                    R.string.download_kiosk_app,
+                    ProvisionInfoType.REGULAR),
+            new ProvisionInfo(R.drawable.ic_lock_outline_24px,
+                    R.string.restrict_device_if_missing_payment,
+                    ProvisionInfoType.TERMS_AND_CONDITIONS),
+            new ProvisionInfo(R.drawable.ic_help_24px,
+                    R.string.contact_provider_for_help,
+                    ProvisionInfoType.SUPPORT)};
 
     public DeviceFinancingProvisionInfoViewModel() {
-        super();
-
-        mHeaderDrawableIdLiveData.setValue(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData.setValue(HEADER_TEXT_ID);
-
-        List<ProvisionInfo> provisionInfoList = new ArrayList<>();
-        for (int i = 0, size = DRAWABLE_IDS.length; i < size; ++i) {
-            provisionInfoList.add(new ProvisionInfo(DRAWABLE_IDS[i], TEXT_IDS[i]));
-        }
-        mProvisionInfoListLiveData.setValue(provisionInfoList);
+        mMandatoryHeaderTextId = MANDATORY_HEADER_TEXT_ID;
+        mSubHeaderTextId = SUB_HEADER_TEXT_ID;
+        mProvisionInfoList = List.of(PROVISION_INFOS);
+        retrieveData();
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingProvisionNotRequiredViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingProvisionNotRequiredViewModel.java
deleted file mode 100644
index 9cc4d42..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingProvisionNotRequiredViewModel.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import com.android.devicelockcontroller.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class provides resources and data used for the use case where device financing is not
- * required any more.
- */
-public final class DeviceFinancingProvisionNotRequiredViewModel extends
-        ProvisionInfoViewModel {
-
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_check_circle_24px;
-
-    private static final int HEADER_TEXT_ID = R.string.device_paid;
-
-    private static final Integer[] DRAWABLE_IDS = new Integer[]{
-            R.drawable.ic_block_24px, R.drawable.ic_lock_open_24px,
-    };
-
-    private static final Integer[] TEXT_IDS = new Integer[]{
-            R.string.device_removed_from_finance_program, R.string.restrictions_lifted,
-    };
-
-    DeviceFinancingProvisionNotRequiredViewModel() {
-        super();
-
-        mHeaderDrawableIdLiveData.setValue(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData.setValue(HEADER_TEXT_ID);
-
-        List<ProvisionInfo> provisionInfoList = new ArrayList<>();
-        for (int i = 0, size = DRAWABLE_IDS.length; i < size; ++i) {
-            provisionInfoList.add(new ProvisionInfo(DRAWABLE_IDS[i], TEXT_IDS[i]));
-        }
-        mProvisionInfoListLiveData.setValue(provisionInfoList);
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingSecondaryUserProvisionInfoViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingSecondaryUserProvisionInfoViewModel.java
deleted file mode 100644
index dd5074b..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceFinancingSecondaryUserProvisionInfoViewModel.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import com.android.devicelockcontroller.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class provides resources and data used to be displayed for secondary users for the device
- * financing use case.
- */
-public final class DeviceFinancingSecondaryUserProvisionInfoViewModel extends
-        ProvisionInfoViewModel {
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_info_24px;
-
-    private static final int HEADER_TEXT_ID = R.string.device_provided_by_provider;
-
-    private static final Integer[] DRAWABLE_IDS = new Integer[]{
-            R.drawable.ic_file_download_24px, R.drawable.ic_lock_outline_24px,
-    };
-
-    private static final Integer[] TEXT_IDS = new Integer[]{
-            R.string.install_kiosk_app_secondary_user,
-            R.string.restrict_device_if_owner_doesnt_make_payment,
-    };
-
-    public DeviceFinancingSecondaryUserProvisionInfoViewModel() {
-        super();
-
-        mHeaderDrawableIdLiveData.setValue(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData.setValue(HEADER_TEXT_ID);
-
-        List<ProvisionInfo> provisionInfoList = new ArrayList<>();
-        for (int i = 0, size = DRAWABLE_IDS.length; i < size; ++i) {
-            provisionInfoList.add(new ProvisionInfo(DRAWABLE_IDS[i], TEXT_IDS[i]));
-        }
-        mProvisionInfoListLiveData.setValue(provisionInfoList);
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceInfoSettingsFragment.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceInfoSettingsFragment.java
index f9d82a9..f15baa6 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceInfoSettingsFragment.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceInfoSettingsFragment.java
@@ -24,6 +24,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.lifecycle.LifecycleOwner;
 import androidx.lifecycle.ViewModelProvider;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceFragmentCompat;
@@ -45,20 +46,37 @@
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        requireActivity().setTitle(getString(R.string.settings_screen_title));
 
         DeviceInfoSettingsViewModel viewModel = new ViewModelProvider(this).get(
                 DeviceInfoSettingsViewModel.class);
-        viewModel.mProviderNameLiveData.observe(getViewLifecycleOwner(), providerName -> {
-            PreferenceManager preferenceManager = getPreferenceManager();
+        PreferenceManager preferenceManager = getPreferenceManager();
+        LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
+        viewModel.getProviderNameLiveData().observe(lifecycleOwner, providerName -> {
+            requireActivity().setTitle(
+                    getString(R.string.device_provided_by_provider, providerName));
+
             hideIconView(preferenceManager.getPreferenceScreen());
-            for (Pair<Integer, Integer> keyTitlePair : viewModel.mPreferenceKeyTitlePairs) {
+            for (Pair<Integer, Integer> keyTitlePair :
+                    viewModel.getPreferenceWithProviderNameKeyTitlePairs()) {
                 Preference preference = preferenceManager.findPreference(
                         getString(keyTitlePair.first));
                 checkNotNull(preference);
                 preference.setTitle(getString(keyTitlePair.second, providerName));
             }
+            Preference supportUrlPreference = preferenceManager.findPreference(
+                    getString(R.string.settings_contact_provider_preference_key));
+            checkNotNull(supportUrlPreference);
+            supportUrlPreference.setTitle(
+                    String.format(getString(R.string.settings_contact_provider), providerName,
+                            viewModel.getSupportUrl()));
         });
+        viewModel.getInstallFromUnknownSourcesDisallowedLiveData().observe(lifecycleOwner,
+                disallowed -> {
+                    Preference preference = preferenceManager.findPreference(
+                            getString(R.string.settings_install_apps_preference_key));
+                    checkNotNull(preference);
+                    preference.setVisible(disallowed);
+                });
     }
 
     /**
@@ -66,8 +84,7 @@
      */
     private static void hideIconView(Preference preference) {
         preference.setIconSpaceReserved(false);
-        if (preference instanceof PreferenceGroup) {
-            PreferenceGroup preferenceGroup = (PreferenceGroup) preference;
+        if (preference instanceof PreferenceGroup preferenceGroup) {
             for (int i = 0; i < preferenceGroup.getPreferenceCount(); i++) {
                 hideIconView(preferenceGroup.getPreference(i));
             }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceInfoSettingsViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceInfoSettingsViewModel.java
index 6110c72..1fb6093 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceInfoSettingsViewModel.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceInfoSettingsViewModel.java
@@ -16,7 +16,9 @@
 
 package com.android.devicelockcontroller.activities;
 
-import android.text.TextUtils;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType.TYPE_FINANCED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType.TYPE_SUBSIDY;
+
 import android.util.Pair;
 
 import androidx.lifecycle.MutableLiveData;
@@ -28,8 +30,10 @@
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -39,46 +43,103 @@
 public final class DeviceInfoSettingsViewModel extends ViewModel {
 
     private static final String TAG = "DeviceInfoSettingsViewModel";
+    private final List<Pair<Integer, Integer>> mPreferenceWithProviderNameKeyTitlePairs =
+            new ArrayList<>(Arrays.asList(
+                    new Pair<>(
+                            R.string.settings_credit_provider_capabilities_category_preference_key,
+                            R.string.settings_credit_provider_capabilities_category),
+                    new Pair<>(R.string.settings_allowlisted_apps_preference_key,
+                            R.string.settings_allowlisted_apps),
+                    new Pair<>(R.string.settings_restrictions_removed_preference_key,
+                            R.string.settings_restrictions_removed),
+                    new Pair<>(R.string.settings_uninstall_kiosk_app_preference_key,
+                            R.string.settings_uninstall_kiosk_app)));
 
-    // Preferences that need to be updated with provider name
-    private static final List<Pair<Integer, Integer>> PREFERENCE_KEY_TITLE_PAIRS = Arrays.asList(
-            new Pair<>(R.string.settings_intro_preference_key,
-                    R.string.settings_intro),
-            new Pair<>(R.string.settings_credit_provider_capabilities_category_preference_key,
-                    R.string.settings_credit_provider_capabilities_category),
-            new Pair<>(R.string.settings_allowlisted_apps_preference_key,
-                    R.string.settings_allowlisted_apps),
-            new Pair<>(R.string.settings_restrictions_removed_preference_key,
-                    R.string.settings_restrictions_removed),
-            new Pair<>(R.string.settings_uninstall_kiosk_app_preference_key,
-                    R.string.settings_uninstall_kiosk_app));
-
-    final List<Pair<Integer, Integer>> mPreferenceKeyTitlePairs;
-
-    final MutableLiveData<String> mProviderNameLiveData;
+    private String mSupportUrl;
+    private final MutableLiveData<String> mProviderNameLiveData = new MutableLiveData<>();
+    private final MutableLiveData<Boolean> mInstallFromUnknownSourcesDisallowedLiveData =
+            new MutableLiveData<>();
 
     public DeviceInfoSettingsViewModel() {
-        mPreferenceKeyTitlePairs = PREFERENCE_KEY_TITLE_PAIRS;
-        mProviderNameLiveData = new MutableLiveData<>();
 
-        Futures.addCallback(
-                SetupParametersClient.getInstance().getKioskAppProviderName(),
+        SetupParametersClient setupParametersClient = SetupParametersClient.getInstance();
+        ListenableFuture<Integer> getProvisioningTypeFuture =
+                setupParametersClient.getProvisioningType();
+        ListenableFuture<String> getKioskAppProviderNameFuture =
+                setupParametersClient.getKioskAppProviderName();
+        ListenableFuture<Boolean> isInstallFromUnknownSourcesDisallowedFuture =
+                setupParametersClient.isInstallingFromUnknownSourcesDisallowed();
+        ListenableFuture<String> getSupportUrlFuture = setupParametersClient.getSupportUrl();
+        Futures.addCallback(isInstallFromUnknownSourcesDisallowedFuture,
                 new FutureCallback<>() {
                     @Override
-                    public void onSuccess(String providerName) {
-                        if (TextUtils.isEmpty(providerName)) {
-                            LogUtil.e(TAG, "Device provider name is empty, should not reach here.");
-                            return;
-                        }
-                        mProviderNameLiveData.postValue(providerName);
+                    public void onSuccess(Boolean result) {
+                        mInstallFromUnknownSourcesDisallowedLiveData.postValue(result);
                     }
 
                     @Override
                     public void onFailure(Throwable t) {
-                        LogUtil.e(TAG, "Failed to get Kiosk app provider name", t);
+                        LogUtil.e(TAG,
+                                "Failed to get isInstallingFromUnknownSourcesDisallowed from "
+                                        + "setup parameters",
+                                t);
+                    }
+                }, MoreExecutors.directExecutor());
+
+        Futures.addCallback(
+                Futures.whenAllSucceed(getProvisioningTypeFuture, getKioskAppProviderNameFuture,
+                                getSupportUrlFuture)
+                        .call(() -> {
+                            Integer provisioningType = Futures.getDone(
+                                    getProvisioningTypeFuture);
+                            switch (provisioningType) {
+                                case TYPE_FINANCED:
+                                    mPreferenceWithProviderNameKeyTitlePairs.add(
+                                            new Pair<>(
+                                                    R.string.settings_intro_preference_key,
+                                                    R.string.settings_intro_device_financing));
+                                    break;
+                                case TYPE_SUBSIDY:
+                                    mPreferenceWithProviderNameKeyTitlePairs.add(
+                                            new Pair<>(
+                                                    R.string.settings_intro_preference_key,
+                                                    R.string.settings_intro_device_subsidy));
+                                    break;
+                                default:
+                                    throw new IllegalStateException(
+                                            "Invalid provisioning type");
+                            }
+                            mSupportUrl = Futures.getDone(getSupportUrlFuture);
+                            mProviderNameLiveData.postValue(
+                                    Futures.getDone(getKioskAppProviderNameFuture));
+                            return null;
+                        }, MoreExecutors.directExecutor()),
+                new FutureCallback<Void>() {
+                    @Override
+                    public void onSuccess(Void result) {
+                        LogUtil.d(TAG, "Successfully retrieved setup parameters");
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        LogUtil.e(TAG, "Failed to retrieve setup parameters", t);
                     }
                 }, MoreExecutors.directExecutor());
     }
 
+    public MutableLiveData<String> getProviderNameLiveData() {
+        return mProviderNameLiveData;
+    }
 
+    public MutableLiveData<Boolean> getInstallFromUnknownSourcesDisallowedLiveData() {
+        return mInstallFromUnknownSourcesDisallowedLiveData;
+    }
+
+    public String getSupportUrl() {
+        return mSupportUrl;
+    }
+
+    public List<Pair<Integer, Integer>> getPreferenceWithProviderNameKeyTitlePairs() {
+        return mPreferenceWithProviderNameKeyTitlePairs;
+    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceLockNotificationManager.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceLockNotificationManager.java
index 23e365b..b5d5d33 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceLockNotificationManager.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceLockNotificationManager.java
@@ -16,6 +16,8 @@
 
 package com.android.devicelockcontroller.activities;
 
+import static com.android.devicelockcontroller.activities.ProvisioningActivity.EXTRA_SHOW_PROVISION_FAILED_UI_ON_START;
+
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import android.annotation.SuppressLint;
@@ -24,22 +26,31 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.widget.RemoteViews;
 
 import androidx.core.app.NotificationCompat;
 import androidx.core.app.NotificationManagerCompat;
 
+import com.android.devicelockcontroller.DeviceLockControllerApplication;
 import com.android.devicelockcontroller.R;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
+import com.android.devicelockcontroller.storage.UserParameters;
 import com.android.devicelockcontroller.util.LogUtil;
 import com.android.devicelockcontroller.util.StringUtil;
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 
-import java.time.Instant;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.FormatStyle;
+import java.util.UUID;
+import java.util.concurrent.Executors;
 
 /**
  * A utility class used to send notification.
@@ -48,10 +59,13 @@
 
     private static final String TAG = "DeviceLockNotificationManager";
 
-    private static final String PROVISION_NOTIFICATION_CHANNEL_ID = "devicelock-provision";
+    private static final String PROVISION_NOTIFICATION_CHANNEL_ID_BASE = "devicelock-provision";
     private static final String DEVICE_RESET_NOTIFICATION_TAG = "devicelock-device-reset";
     private static final int DEVICE_RESET_NOTIFICATION_ID = 0;
-    private static final int DEFER_ENROLLMENT_NOTIFICATION_ID = 1;
+    private static final int DEFER_PROVISIONING_NOTIFICATION_ID = 1;
+
+    private static final ListeningExecutorService sListeningExecutorService =
+            MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
 
     /**
      * Similar to {@link #sendDeviceResetNotification(Context, int)}, except that:
@@ -73,17 +87,88 @@
         sendDeviceResetNotification(context, days, /* ongoing= */ false);
     }
 
+    /**
+     * Send the device reset timer notification.
+     *
+     * @param context       the context where the notification will be sent out
+     * @param countDownBase the time when device will be reset in
+     *                      {@link SystemClock#elapsedRealtime()}.
+     */
+    public static void sendDeviceResetTimerNotification(Context context, long countDownBase) {
+        ListenableFuture<String> channelIdFuture = createNotificationChannel(context);
+        ListenableFuture<String> kioskAppProviderNameFuture =
+                SetupParametersClient.getInstance().getKioskAppProviderName();
+        ListenableFuture<Void> result =
+                Futures.whenAllSucceed(channelIdFuture, kioskAppProviderNameFuture).call(() -> {
+                    String channelId = Futures.getDone(channelIdFuture);
+                    String providerName = Futures.getDone(kioskAppProviderNameFuture);
+                    Notification notification =
+                            new NotificationCompat.Builder(context,
+                                    channelId)
+                                    .setSmallIcon(R.drawable.ic_action_lock)
+                                    .setColor(context.getResources()
+                                            .getColor(R.color.notification_background_color,
+                                                    context.getTheme()))
+                                    .setOngoing(true)
+                                    .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
+                                    .setCustomContentView(
+                                            buildResetTimerNotif(countDownBase,
+                                                    providerName,
+                                                    false))
+                                    .setCustomBigContentView(
+                                            buildResetTimerNotif(countDownBase, providerName,
+                                                    true))
+                                    .build();
+                    NotificationManagerCompat notificationManager =
+                            NotificationManagerCompat.from(context);
+                    notificationManager.notify(DEVICE_RESET_NOTIFICATION_TAG,
+                            DEVICE_RESET_NOTIFICATION_ID, notification);
+                    return null;
+                }, sListeningExecutorService);
+
+        Futures.addCallback(result, new FutureCallback<>() {
+            @Override
+            public void onSuccess(Void result) {
+                LogUtil.d(TAG, "send device reset notification");
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LogUtil.e(TAG, "Failed to create device reset notification", t);
+            }
+        }, sListeningExecutorService);
+    }
+
+    private static RemoteViews buildResetTimerNotif(long countDownBase, String providerName,
+            boolean isExpanded) {
+        Context appContext = DeviceLockControllerApplication.getAppContext();
+        RemoteViews content = new RemoteViews(appContext.getPackageName(),
+                isExpanded ? R.layout.reset_timer_notif_large : R.layout.reset_timer_notif_small);
+        content.setChronometer(R.id.reset_timer_title, countDownBase,
+                appContext.getString(R.string.device_reset_timer_notification_title),
+                /* started= */ true);
+        if (isExpanded) {
+            content.setCharSequence(R.id.reset_content, "setText",
+                    appContext.getString(R.string.device_reset_notification_content, providerName));
+        }
+        return content;
+    }
+
     private static void sendDeviceResetNotification(Context context, int days, boolean ongoing) {
         // TODO: check/request permission first
 
         // re-creating the same notification channel is essentially no-op
-        createNotificationChannel(context);
-        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
-        Futures.addCallback(createDeviceResetNotification(context, days, ongoing),
+        ListenableFuture<String> channelIdFuture = createNotificationChannel(context);
+        ListenableFuture<Notification> notificationFuture = Futures.transformAsync(channelIdFuture,
+                channelId -> createDeviceResetNotification(context, days, ongoing, channelId),
+                sListeningExecutorService);
+        Futures.addCallback(notificationFuture,
                 new FutureCallback<>() {
                     @Override
                     public void onSuccess(Notification notification) {
                         LogUtil.d(TAG, "send device reset notification");
+                        NotificationManagerCompat notificationManager =
+                                NotificationManagerCompat.from(context);
                         notificationManager.notify(DEVICE_RESET_NOTIFICATION_TAG,
                                 DEVICE_RESET_NOTIFICATION_ID, notification);
                     }
@@ -92,53 +177,129 @@
                     public void onFailure(Throwable t) {
                         LogUtil.e(TAG, "Failed to create device reset notification", t);
                     }
-                }, context.getMainExecutor());
+                }, sListeningExecutorService);
     }
 
-    // Already requested POST_NOTIFICATION permission in ProvisionInfoFragment
+    /**
+     * Send the device deferred provisioning notification.
+     * (POST_NOTIFICATION already requested permission in ProvisionInfoFragment).
+     *
+     * @param context        the context where the notification will be sent out
+     * @param resumeDateTime the time when device will show the notification
+     * @Param pendingIntent  pending intent for the notification
+     */
     @SuppressLint("MissingPermission")
-    public static void sendDeferredEnrollmentNotification(Context context,
-            Instant resumeTime, PendingIntent pendingIntent) {
-        createNotificationChannel(context);
-        DateTimeFormatter timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
-        String enrollmentResumeTime = timeFormatter.format(resumeTime);
-        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
-                context, PROVISION_NOTIFICATION_CHANNEL_ID)
-                .setContentTitle(context.getString(R.string.device_enrollment_header_text))
-                .setContentText(context.getString(R.string.device_enrollment_notification_body_text,
-                        enrollmentResumeTime))
-                .setSmallIcon(R.drawable.ic_action_lock)
-                .setContentIntent(pendingIntent)
-                .setOngoing(true);
-        NotificationManagerCompat notificationManager =
-                NotificationManagerCompat.from(context);
-        notificationManager.notify(DEFER_ENROLLMENT_NOTIFICATION_ID, notificationBuilder.build());
+    public static void sendDeferredProvisioningNotification(Context context,
+            LocalDateTime resumeDateTime, PendingIntent pendingIntent) {
+        ListenableFuture<String> channelIdFuture = createNotificationChannel(context);
+
+        Futures.addCallback(channelIdFuture, new FutureCallback<String>() {
+            @Override
+            public void onSuccess(String channelId) {
+                DateTimeFormatter timeFormatter =
+                        DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
+                String enrollmentResumeTime = timeFormatter.format(resumeDateTime);
+                NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
+                        context, channelId)
+                        .setContentTitle(context.getString(R.string.device_enrollment_header_text))
+                        .setContentText(context
+                                .getString(R.string.device_enrollment_notification_body_text,
+                                        enrollmentResumeTime))
+                        .setSmallIcon(R.drawable.ic_action_lock)
+                        .setColor(context.getResources()
+                                .getColor(R.color.notification_background_color,
+                                        context.getTheme()))
+                        .setContentIntent(pendingIntent)
+                        .setAutoCancel(true)
+                        .setOngoing(true);
+                NotificationManagerCompat notificationManager =
+                        NotificationManagerCompat.from(context);
+                notificationManager.notify(DEFER_PROVISIONING_NOTIFICATION_ID,
+                        notificationBuilder.build());
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LogUtil.e(TAG, "Failed to create deferred provisioning notification", t);
+            }
+        }, sListeningExecutorService);
+
+    }
+
+    static void cancelDeferredProvisioningNotification(Context context) {
+        LogUtil.d(TAG, "cancelDeferredEnrollmentNotification");
+        NotificationManagerCompat.from(context).cancel(DEFER_PROVISIONING_NOTIFICATION_ID);
     }
 
     private static ListenableFuture<Notification> createDeviceResetNotification(Context context,
-            int days, boolean onging) {
+            int days, boolean ongoing, String channelId) {
         return Futures.transform(SetupParametersClient.getInstance().getKioskAppProviderName(),
                 providerName ->
-                        // TODO: update the icon
-                        new NotificationCompat.Builder(context, PROVISION_NOTIFICATION_CHANNEL_ID)
+                        new NotificationCompat.Builder(context,
+                                channelId)
                                 .setSmallIcon(R.drawable.ic_action_lock)
-                                .setOngoing(onging)
+                                .setColor(context.getResources()
+                                        .getColor(R.color.notification_background_color,
+                                                context.getTheme()))
+                                .setOngoing(ongoing)
                                 .setContentTitle(StringUtil.getPluralString(context, days,
                                         R.string.device_reset_in_days_notification_title))
                                 .setContentText(context.getString(
                                         R.string.device_reset_notification_content,
-                                        providerName)).build(),
+                                        providerName))
+                                .setContentIntent(
+                                        PendingIntent.getActivity(context, /* requestCode= */0,
+                                                new Intent(context,
+                                                        ProvisioningActivity.class).putExtra(
+                                                        EXTRA_SHOW_PROVISION_FAILED_UI_ON_START,
+                                                        true),
+                                                PendingIntent.FLAG_IMMUTABLE)).build(),
                 context.getMainExecutor());
     }
 
-    private static void createNotificationChannel(Context context) {
-        NotificationManager notificationManager = context.getSystemService(
-                NotificationManager.class);
-        checkNotNull(notificationManager);
-        NotificationChannel notificationChannel = new NotificationChannel(
-                PROVISION_NOTIFICATION_CHANNEL_ID,
-                context.getString(R.string.provision_notification_channel_name),
-                NotificationManager.IMPORTANCE_HIGH);
-        notificationManager.createNotificationChannel(notificationChannel);
+    private static String getProvisionNotificationChannelId(Context context) {
+        return PROVISION_NOTIFICATION_CHANNEL_ID_BASE + "-"
+                + UserParameters.getNotificationChannelIdSuffix(context);
+    }
+
+    private static String createProvisionNotificationChannelId(Context context) {
+        String notificationChannelIdSuffix = UUID.randomUUID().toString();
+        String provisioningChannelId = PROVISION_NOTIFICATION_CHANNEL_ID_BASE
+                + "-" + notificationChannelIdSuffix;
+        UserParameters.setNotificationChannelIdSuffix(context, notificationChannelIdSuffix);
+
+        return provisioningChannelId;
+    }
+
+    // Create a notification channel and return a future with its ID.
+    private static ListenableFuture<String> createNotificationChannel(Context context) {
+        return sListeningExecutorService.submit(() -> {
+            String provisioningChannelId = getProvisionNotificationChannelId(context);
+            NotificationManager notificationManager =
+                    context.getSystemService(NotificationManager.class);
+            checkNotNull(notificationManager);
+            NotificationChannel notificationChannel =
+                    notificationManager.getNotificationChannel(provisioningChannelId);
+            if (notificationChannel != null
+                    && notificationChannel.getImportance() != NotificationManager.IMPORTANCE_HIGH) {
+                // Channel importance has been changed by user
+                LogUtil.w(TAG, "Channel " + provisioningChannelId
+                        + " importance changed by user, deleting it");
+                notificationManager.deleteNotificationChannel(provisioningChannelId);
+                notificationChannel = null;
+            }
+
+            if (notificationChannel == null) {
+                provisioningChannelId = createProvisionNotificationChannelId(context);
+                notificationChannel = new NotificationChannel(
+                        provisioningChannelId,
+                        context.getString(R.string.provision_notification_channel_name),
+                        NotificationManager.IMPORTANCE_HIGH);
+                LogUtil.i(TAG, "New notification channel: " + provisioningChannelId);
+            }
+            notificationManager.createNotificationChannel(notificationChannel);
+
+            return provisioningChannelId;
+        });
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceLockSettingsActivity.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceLockSettingsActivity.java
index 42f873b..e7f90ab 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceLockSettingsActivity.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceLockSettingsActivity.java
@@ -18,8 +18,8 @@
 
 import android.os.Bundle;
 
-import com.android.devicelockcontroller.R;
 import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
+import com.android.settingslib.collapsingtoolbar.R;
 
 /**
  * Activity used in Settings.
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesFragment.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesFragment.java
index e290375..11b7757 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesFragment.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesFragment.java
@@ -16,8 +16,12 @@
 
 package com.android.devicelockcontroller.activities;
 
+import static com.android.devicelockcontroller.activities.DevicePoliciesViewModel.HEADER_DRAWABLE_ID;
+import static com.android.devicelockcontroller.activities.DevicePoliciesViewModel.HEADER_TEXT_ID;
+
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import android.content.Context;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -33,13 +37,9 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.devicelockcontroller.R;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
-import com.android.devicelockcontroller.policy.SetupController;
-import com.android.devicelockcontroller.util.LogUtil;
-
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.MoreExecutors;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionHelper;
+import com.android.devicelockcontroller.policy.ProvisionHelperImpl;
 
 /**
  * A screen which lists the polies enforced on the device by the device provider.
@@ -76,65 +76,29 @@
 
         ImageView imageView = view.findViewById(R.id.header_icon);
         checkNotNull(imageView);
-        viewModel.mHeaderDrawableIdLiveData.observe(getViewLifecycleOwner(),
-                imageView::setImageResource);
+        imageView.setImageResource(HEADER_DRAWABLE_ID);
 
         TextView headerTextView = view.findViewById(R.id.header_text);
         checkNotNull(headerTextView);
         viewModel.mProviderNameLiveData.observe(getViewLifecycleOwner(),
                 providerName -> headerTextView.setText(
-                        getString(viewModel.mHeaderTextIdLiveData.getValue(), providerName)));
-        viewModel.mHeaderTextIdLiveData.observe(getViewLifecycleOwner(),
-                textId -> headerTextView.setText(
-                        getString(textId, viewModel.mProviderNameLiveData.getValue())));
+                        getString(HEADER_TEXT_ID, providerName)));
 
-        TextView footerTextView = view.findViewById(R.id.footer_text);
-        checkNotNull(footerTextView);
-        viewModel.mFooterTextIdLiveData.observe(getViewLifecycleOwner(), footerTextView::setText);
-
-        SetupController setupController =
-                ((PolicyObjectsInterface) getActivity().getApplicationContext())
-                        .getSetupController();
+        Context context = requireContext().getApplicationContext();
+        ProvisionHelper provisionHelper = new ProvisionHelperImpl(context,
+                ((PolicyObjectsProvider) context).getProvisionStateController());
 
         ProvisioningProgressViewModel provisioningProgressViewModel =
                 new ViewModelProvider(requireActivity()).get(ProvisioningProgressViewModel.class);
         Button button = view.findViewById(R.id.button_next);
         checkNotNull(button);
-        button.setOnClickListener(
-                v -> {
-                    provisioningProgressViewModel.setProvisioningProgress(
-                            ProvisioningProgress.GETTING_DEVICE_READY);
-                    Futures.addCallback(
-                            setupController.startSetupFlow(getActivity()),
-                            new FutureCallback<>() {
-                                @Override
-                                public void onSuccess(Void result) {
-                                    LogUtil.i(TAG, "Setup flow has started installing kiosk app");
-                                    provisioningProgressViewModel.setProvisioningProgress(
-                                            ProvisioningProgress.INSTALLING_KIOSK_APP);
-                                }
-
-                                @Override
-                                public void onFailure(Throwable t) {
-                                    LogUtil.e(TAG, "Failed to start setup flow!", t);
-                                    // TODO(b/279969959): show setup failure UI
-                                }
-                            }, MoreExecutors.directExecutor());
+        viewModel.getIsMandatoryLiveData().observe(this,
+                isMandatory -> {
+                    button.setOnClickListener(
+                            v -> provisionHelper.scheduleKioskAppInstallation(requireActivity(),
+                                    provisioningProgressViewModel,
+                                    isMandatory));
+                    button.setVisibility(View.VISIBLE);
                 });
-
-        setupController.addListener(new SetupController.SetupUpdatesCallbacks() {
-            @Override
-            public void setupFailed(int reason) {
-                LogUtil.e(TAG, "Failed to finish setup flow!");
-                // TODO(b/279969959): show setup failure UI
-            }
-
-            @Override
-            public void setupCompleted() {
-                LogUtil.i(TAG, "Successfully finished setup flow!");
-                provisioningProgressViewModel.setProvisioningProgress(
-                        ProvisioningProgress.OPENING_KIOSK_APP);
-            }
-        });
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesViewModel.java
index a2cf529..03ccee4 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesViewModel.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesViewModel.java
@@ -16,6 +16,7 @@
 
 package com.android.devicelockcontroller.activities;
 
+import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MediatorLiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.ViewModel;
@@ -37,11 +38,9 @@
  */
 public final class DevicePoliciesViewModel extends ViewModel {
 
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_info_24px;
+    static final int HEADER_DRAWABLE_ID = R.drawable.ic_info_24px;
 
-    private static final int HEADER_TEXT_ID = R.string.setup_info_title_text;
-
-    private static final int FOOTER_TEXT_ID = R.string.footer_notice;
+    static final int HEADER_TEXT_ID = R.string.setup_info_title_text;
 
     private static final DevicePolicyGroup CONTROL_POLICY_GROUP =
             new DevicePolicyGroup.Builder()
@@ -83,10 +82,13 @@
     public static final String TAG = "DevicePoliciesViewModel";
 
     final MutableLiveData<String> mProviderNameLiveData;
-    final MutableLiveData<Integer> mHeaderDrawableIdLiveData;
-    final MutableLiveData<Integer> mHeaderTextIdLiveData;
     final MediatorLiveData<List<DevicePolicyGroup>> mDevicePolicyGroupListLiveData;
-    final MutableLiveData<Integer> mFooterTextIdLiveData;
+
+    public LiveData<Boolean> getIsMandatoryLiveData() {
+        return mIsMandatoryLiveData;
+    }
+
+    private final MutableLiveData<Boolean> mIsMandatoryLiveData = new MutableLiveData<>();
 
     public DevicePoliciesViewModel() {
         mProviderNameLiveData = new MutableLiveData<>();
@@ -102,11 +104,21 @@
                         LogUtil.e(TAG, "Failed to get Device Provider name!", t);
                     }
                 }, MoreExecutors.directExecutor());
-        mHeaderDrawableIdLiveData = new MutableLiveData<>(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData = new MutableLiveData<>(HEADER_TEXT_ID);
+
+        Futures.addCallback(SetupParametersClient.getInstance().isProvisionMandatory(),
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Boolean result) {
+                        mIsMandatoryLiveData.postValue(result);
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        LogUtil.e(TAG, "Failed to know if provision is mandatory!", t);
+                    }
+                }, MoreExecutors.directExecutor());
         mDevicePolicyGroupListLiveData = new MediatorLiveData<>();
         mDevicePolicyGroupListLiveData.addSource(mProviderNameLiveData,
                 unused -> mDevicePolicyGroupListLiveData.setValue(DEVICE_POLICY_GROUPS));
-        mFooterTextIdLiveData = new MutableLiveData<>(FOOTER_TEXT_ID);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePolicyGroupViewHolder.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePolicyGroupViewHolder.java
index 7a67ac2..58d499a 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePolicyGroupViewHolder.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePolicyGroupViewHolder.java
@@ -17,21 +17,14 @@
 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.method.LinkMovementMethod;
-import android.text.style.ClickableSpan;
-import android.text.style.URLSpan;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.activities.util.UrlUtils;
 
 /**
  * A {@link androidx.recyclerview.widget.RecyclerView.ViewHolder} class which describes the item
@@ -58,12 +51,7 @@
             TextView devicePolicyItemView = (TextView) mDevicePolicyItems.getChildAt(i);
             DevicePolicy devicePolicy = devicePolicyGroup.getDevicePolicyList().get(i);
             String policyText = context.getString(devicePolicy.getTextId(), providerName);
-            SpannableString text =
-                    new SpannableString(Html.fromHtml(policyText, Html.FROM_HTML_MODE_COMPACT));
-            if (handleUrlSpan(text)) {
-                devicePolicyItemView.setMovementMethod(LinkMovementMethod.getInstance());
-            }
-            devicePolicyItemView.setText(text);
+            UrlUtils.setUrlText(devicePolicyItemView, policyText);
             devicePolicyItemView.setCompoundDrawablesRelativeWithIntrinsicBounds(
                     devicePolicy.getDrawableId(),
                     /* top=*/ 0,
@@ -77,37 +65,4 @@
             devicePolicyItemView.setVisibility(View.GONE);
         }
     }
-
-    private boolean handleUrlSpan(SpannableString text) {
-        boolean hasUrl = false;
-        URLSpan[] spans = text.getSpans(0, text.length(), URLSpan.class);
-        for (URLSpan span : spans) {
-            int start = text.getSpanStart(span);
-            int end = text.getSpanEnd(span);
-            ClickableSpan clickableSpan = new CustomClickableSpan(span.getURL());
-            text.removeSpan(span);
-            text.setSpan(clickableSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            hasUrl = true;
-        }
-        return hasUrl;
-    }
-
-    /**
-     * A custom clickable span to open URL as a web intent.
-     */
-    private static final class CustomClickableSpan extends ClickableSpan {
-        final String mUrl;
-
-        CustomClickableSpan(String url) {
-            mUrl = url;
-        }
-
-        @Override
-        public void onClick(@NonNull View view) {
-            Context context = view.getContext();
-            Intent webIntent = new Intent(context, HelpActivity.class);
-            webIntent.putExtra(HelpActivity.EXTRA_URL_PARAM, mUrl);
-            context.startActivity(webIntent);
-        }
-    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyDeferredProvisionInfoViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyDeferredProvisionInfoViewModel.java
deleted file mode 100644
index cdc61d7..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyDeferredProvisionInfoViewModel.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import com.android.devicelockcontroller.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class provides resources and data used for the deferred provisioning flow of the device
- * subsidy use case.
- */
-public final class DeviceSubsidyDeferredProvisionInfoViewModel extends ProvisionInfoViewModel {
-
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_info_24px;
-
-    private static final int HEADER_TEXT_ID = R.string.enroll_your_device_header;
-
-    private static final int SUBHEADER_TEXT_ID = R.string.enroll_your_device_subsidy_subheader;
-
-    private static final Integer[] DRAWABLE_IDS = new Integer[]{
-            R.drawable.ic_file_download_24px, R.drawable.ic_lock_outline_24px,
-    };
-
-    private static final Integer[] TEXT_IDS = new Integer[]{
-            R.string.download_kiosk_app, R.string.restrict_device_if_dont_make_payment,
-    };
-
-    public DeviceSubsidyDeferredProvisionInfoViewModel() {
-        super();
-
-        mHeaderDrawableIdLiveData.setValue(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData.setValue(HEADER_TEXT_ID);
-        mSubheaderTextIdLiveData.setValue(SUBHEADER_TEXT_ID);
-        List<ProvisionInfo> provisionInfoList = new ArrayList<>();
-        for (int i = 0, size = DRAWABLE_IDS.length; i < size; ++i) {
-            provisionInfoList.add(new ProvisionInfo(DRAWABLE_IDS[i], TEXT_IDS[i]));
-        }
-        mProvisionInfoListLiveData.setValue(provisionInfoList);
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyEnrollmentInfoViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyEnrollmentInfoViewModel.java
deleted file mode 100644
index 9ed1b9f..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyEnrollmentInfoViewModel.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import com.android.devicelockcontroller.R;
-
-/**
- *This class provides data about the device enrollment in the device subsidy use case.
- */
-public final class DeviceSubsidyEnrollmentInfoViewModel extends DeviceEnrollmentInfoViewModel {
-
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_calendar_today_24px;
-
-    private static final int HEADER_TEXT_ID = R.string.device_enrollment_header_text;
-
-    private static final int BODY_TEXT_ID = R.string.device_subsidy_enrollment_body_text;
-
-    DeviceSubsidyEnrollmentInfoViewModel() {
-        super();
-        mHeaderDrawableIdLiveData.setValue(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData.setValue(HEADER_TEXT_ID);
-        mBodyTextIdLiveData.setValue(BODY_TEXT_ID);
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyProvisionInfoViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyProvisionInfoViewModel.java
index 85d65bc..5d535ad 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyProvisionInfoViewModel.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyProvisionInfoViewModel.java
@@ -18,7 +18,6 @@
 
 import com.android.devicelockcontroller.R;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -26,27 +25,24 @@
  */
 public final class DeviceSubsidyProvisionInfoViewModel extends ProvisionInfoViewModel {
 
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_info_24px;
+    private static final int MANDATORY_HEADER_TEXT_ID = R.string.subsidy_program_header;
+    private static final int SUB_HEADER_TEXT_ID = R.string.enroll_your_device_subsidy_subheader;
 
-    private static final int HEADER_TEXT_ID = R.string.subsidy_program_header;
-
-    private static final Integer[] DRAWABLE_IDS = new Integer[]{
-            R.drawable.ic_file_download_24px, R.drawable.ic_lock_outline_24px,
-    };
-
-    private static final Integer[] TEXT_IDS = new Integer[]{
-            R.string.download_kiosk_app, R.string.restrict_device_if_dont_make_payment,
-    };
+    private static final ProvisionInfo[] PROVISION_INFOS = new ProvisionInfo[]{
+            new ProvisionInfo(R.drawable.ic_file_download_24px,
+                    R.string.download_kiosk_app,
+                    ProvisionInfo.ProvisionInfoType.REGULAR),
+            new ProvisionInfo(R.drawable.ic_lock_outline_24px,
+                    R.string.restrict_device_if_dont_make_payment,
+                    ProvisionInfo.ProvisionInfoType.TERMS_AND_CONDITIONS),
+            new ProvisionInfo(R.drawable.ic_help_24px,
+                    R.string.contact_provider_for_help,
+                    ProvisionInfo.ProvisionInfoType.SUPPORT)};
 
     public DeviceSubsidyProvisionInfoViewModel() {
-        super();
-
-        mHeaderDrawableIdLiveData.setValue(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData.setValue(HEADER_TEXT_ID);
-        List<ProvisionInfo> provisionInfoList = new ArrayList<>();
-        for (int i = 0, size = DRAWABLE_IDS.length; i < size; ++i) {
-            provisionInfoList.add(new ProvisionInfo(DRAWABLE_IDS[i], TEXT_IDS[i]));
-        }
-        mProvisionInfoListLiveData.setValue(provisionInfoList);
+        mSubHeaderTextId = SUB_HEADER_TEXT_ID;
+        mMandatoryHeaderTextId = MANDATORY_HEADER_TEXT_ID;
+        mProvisionInfoList = List.of(PROVISION_INFOS);
+        retrieveData();
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyProvisionNotRequiredViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyProvisionNotRequiredViewModel.java
deleted file mode 100644
index f1cc666..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DeviceSubsidyProvisionNotRequiredViewModel.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import com.android.devicelockcontroller.R;
-
-/**
- * This class provides resources and data used for the use case where device subsidy is not
- * required any more.
- */
-public final class DeviceSubsidyProvisionNotRequiredViewModel extends ProvisionInfoViewModel {
-
-    private static final int HEADER_DRAWABLE_ID = R.drawable.ic_check_circle_24px;
-
-    private static final int HEADER_TEXT_ID = R.string.device_removed_from_subsidy_program;
-
-    private static final int SUBHEADER_TEXT_ID = R.string.restrictions_lifted;
-
-    DeviceSubsidyProvisionNotRequiredViewModel() {
-        super();
-
-        mHeaderDrawableIdLiveData.setValue(HEADER_DRAWABLE_ID);
-        mHeaderTextIdLiveData.setValue(HEADER_TEXT_ID);
-        mSubheaderTextIdLiveData.setValue(SUBHEADER_TEXT_ID);
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/HelpActivity.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/HelpActivity.java
index 29982b0..a68ff7b 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/HelpActivity.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/HelpActivity.java
@@ -42,7 +42,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.help_activity);
 
-        mWebView = (WebView) findViewById(R.id.webview);
+        mWebView = findViewById(R.id.webview);
         Bundle extras = getIntent().getExtras();
         if (extras == null) {
             LogUtil.e(TAG, "No extras present in the launch intent");
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/LandingActivity.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/LandingActivity.java
index 71acf35..2a59a49 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/LandingActivity.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/LandingActivity.java
@@ -22,7 +22,6 @@
 
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.AppCompatActivity;
-import androidx.fragment.app.Fragment;
 
 import com.android.devicelockcontroller.R;
 
@@ -41,10 +40,9 @@
             controller.hide(WindowInsets.Type.systemBars());
         }
         if (savedInstanceState == null) {
-            Fragment fragment = new ProvisionInfoFragment();
             getSupportFragmentManager()
                     .beginTransaction()
-                    .add(R.id.fragment_container, fragment)
+                    .add(R.id.fragment_container, new ProvisionInfoFragment())
                     .commit();
         }
     }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProgressFragment.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProgressFragment.java
index c66aa5a..1bc6100 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProgressFragment.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProgressFragment.java
@@ -16,33 +16,62 @@
 
 package com.android.devicelockcontroller.activities;
 
+import static com.android.devicelockcontroller.common.DeviceLockConstants.MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_FAILURE;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_FAILED;
+
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import android.content.Context;
 import android.os.Bundle;
+import android.os.SystemClock;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.Chronometer;
 import android.widget.ImageView;
+import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
 import androidx.lifecycle.ViewModelProvider;
+import androidx.work.WorkManager;
 
 import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.activities.util.UrlUtils;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionHelper;
+import com.android.devicelockcontroller.policy.ProvisionHelperImpl;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+import java.util.concurrent.TimeUnit;
 
 /**
  * A screen which always displays a progress bar.
  */
 public final class ProgressFragment extends Fragment {
 
-    /** The Bundle key for the resource id of the icon. */
-    private static final String KEY_ICON_ID = "key_icon_id";
+    private static final String TAG = ProgressFragment.class.getSimpleName();
 
-    /** The Bundle key for the resource id of the header text. */
-    private static final String KEY_HEADER_TEXT_ID = "key_header_text_id";
+    private ProvisionHelper mProvisionHelper;
 
-    private static final String KEY_SUBHEADER_TEXT_ID = "key_subheader_text_id";
+    public ProgressFragment() {
+        super();
+    }
+
+    @VisibleForTesting
+    ProgressFragment(ProvisionHelper provisionHelper) {
+        super();
+        mProvisionHelper = provisionHelper;
+    }
 
     @Nullable
     @Override
@@ -61,6 +90,15 @@
         TextView subheaderTextView = v.findViewById(R.id.subheader_text);
         checkNotNull(subheaderTextView);
 
+        ProgressBar progressBar = v.findViewById(R.id.progress_bar);
+        checkNotNull(progressBar);
+
+        View bottomView = v.findViewById(R.id.bottom);
+        checkNotNull(bottomView);
+
+        Chronometer countDownTimeView = v.findViewById(R.id.countdown_text);
+        checkNotNull(countDownTimeView);
+
         ProvisioningProgressViewModel provisioningProgressViewModel =
                 new ViewModelProvider(requireActivity()).get(ProvisioningProgressViewModel.class);
         provisioningProgressViewModel.getProvisioningProgressLiveData().observe(
@@ -68,35 +106,84 @@
                     if (provisioningProgress.mIconId != 0) {
                         headerIconImageView.setImageResource(provisioningProgress.mIconId);
                     }
+                    Context context = requireContext();
                     if (provisioningProgress.mHeaderId != 0) {
                         headerTextView.setText(
-                                requireContext().getString(provisioningProgress.mHeaderId,
+                                context.getString(provisioningProgress.mHeaderId,
                                         provisioningProgressViewModel
                                                 .mProviderNameLiveData.getValue()));
                     }
                     if (provisioningProgress.mSubheaderId != 0) {
-                        subheaderTextView.setText(
-                                requireContext().getString(provisioningProgress.mSubheaderId));
+                        UrlUtils.setUrlText(subheaderTextView,
+                                context.getString(provisioningProgress.mSubheaderId,
+                                        provisioningProgressViewModel
+                                                .mSupportUrlLiveData
+                                                .getValue()));
+                    }
+                    if (provisioningProgress.mProgressBarVisible) {
+                        progressBar.setVisibility(View.VISIBLE);
+                    } else {
+                        progressBar.setVisibility(View.GONE);
+                    }
+                    if (provisioningProgress.mBottomViewVisible) {
+                        bottomView.setVisibility(View.VISIBLE);
+                        Button retryButton = bottomView.findViewById(R.id.button_retry);
+                        checkNotNull(retryButton);
+                        PolicyObjectsProvider policyObjects =
+                                (PolicyObjectsProvider) context.getApplicationContext();
+                        ProvisionStateController provisionStateController =
+                                policyObjects.getProvisionStateController();
+                        if (mProvisionHelper == null) {
+                            mProvisionHelper = new ProvisionHelperImpl(
+                                    context,
+                                    provisionStateController);
+                        }
+                        retryButton.setOnClickListener(
+                                view -> mProvisionHelper.scheduleKioskAppInstallation(
+                                        requireActivity(),
+                                        provisioningProgressViewModel,
+                                        /* isProvisionMandatory= */ false));
+
+                        Button exitButton = bottomView.findViewById(R.id.button_exit);
+                        checkNotNull(exitButton);
+                        FutureCallback<Integer> getProvisionStateCallback =
+                                new FutureCallback<>() {
+                                    @Override
+                                    public void onSuccess(Integer result) {
+                                        if (result == PROVISION_FAILED) {
+                                            // Already reported set up failure. Finish normally
+                                            getActivity().finish();
+                                            return;
+                                        }
+                                        ReportDeviceProvisionStateWorker.reportSetupFailed(
+                                                WorkManager.getInstance(requireContext()),
+                                                provisioningProgress.mFailureReason);
+                                        provisionStateController.postSetNextStateForEventRequest(
+                                                PROVISION_FAILURE);
+                                    }
+
+                                    @Override
+                                    public void onFailure(Throwable t) {
+                                        LogUtil.e(TAG, "Failed to get provision state", t);
+                                    }
+                                };
+                        exitButton.setOnClickListener(
+                                view -> Futures.addCallback(provisionStateController.getState(),
+                                        getProvisionStateCallback,
+                                        context.getMainExecutor()));
+                    } else {
+                        bottomView.setVisibility(View.GONE);
+                    }
+                    if (provisioningProgress.mCountDownTimerVisible) {
+                        countDownTimeView.setBase(
+                                SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(
+                                        MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE));
+                        countDownTimeView.start();
+                        countDownTimeView.setVisibility(View.VISIBLE);
+                    } else {
+                        countDownTimeView.setVisibility(View.GONE);
                     }
                 });
-
         return v;
     }
-
-    static ProgressFragment create(int iconId, int headerTextId, int subheaderTextId) {
-        ProgressFragment progressFragment = new ProgressFragment();
-        Bundle bundle = new Bundle();
-        if (iconId != 0) {
-            bundle.putInt(KEY_ICON_ID, iconId);
-        }
-        if (headerTextId != 0) {
-            bundle.putInt(KEY_HEADER_TEXT_ID, headerTextId);
-        }
-        if (subheaderTextId != 0) {
-            bundle.putInt(KEY_SUBHEADER_TEXT_ID, subheaderTextId);
-        }
-        progressFragment.setArguments(bundle);
-        return progressFragment;
-    }
-
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfo.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfo.java
index f5b39a1..a523749 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfo.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfo.java
@@ -16,20 +16,40 @@
 
 package com.android.devicelockcontroller.activities;
 
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 /**
  * A data model class which is used to hold the data needed to render the RecyclerView.
  */
 public final class ProvisionInfo {
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {ProvisionInfoType.REGULAR, ProvisionInfoType.TERMS_AND_CONDITIONS,
+            ProvisionInfoType.SUPPORT})
+    public @interface ProvisionInfoType {
+        // The general type of provision info without any link
+        int REGULAR = 0;
+        // The type of provision info with a link for terms and conditions.
+        int TERMS_AND_CONDITIONS = 1;
+        // The type of provision info with a link for custom support.
+        int SUPPORT = 2;
+    }
 
+    @ProvisionInfoType
+    private final int mType;
     private final int mDrawableId;
-
     private final int mTextId;
 
-    public ProvisionInfo(int drawableId, int textId) {
+    private String mProviderName;
+    private String mUrl;
+
+    public ProvisionInfo(int drawableId, int textId, @ProvisionInfoType int type) {
         mDrawableId = drawableId;
         mTextId = textId;
+        mType = type;
     }
 
     public int getDrawableId() {
@@ -40,20 +60,41 @@
         return mTextId;
     }
 
+    @ProvisionInfoType
+    public int getType() {
+        return mType;
+    }
+
+    public String getProviderName() {
+        return mProviderName;
+    }
+
+    public void setProviderName(String providerName) {
+        mProviderName = providerName;
+    }
+
+    public String getUrl() {
+        return mUrl;
+    }
+
+    public void setUrl(String url) {
+        mUrl = url;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (this == obj) {
             return true;
         }
-        if (!(obj instanceof ProvisionInfo)) {
+        if (!(obj instanceof ProvisionInfo that)) {
             return false;
         }
-        ProvisionInfo that = (ProvisionInfo) obj;
-        return this.mDrawableId == that.mDrawableId && this.mTextId == that.mTextId;
+        return this.mDrawableId == that.mDrawableId && this.mTextId == that.mTextId
+                && this.mType == that.mType;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mDrawableId, mTextId);
+        return Objects.hash(mDrawableId, mTextId, mType);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoFragment.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoFragment.java
index a093fd4..abb4162 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoFragment.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoFragment.java
@@ -16,16 +16,13 @@
 
 package com.android.devicelockcontroller.activities;
 
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_DEFERRED_PROVISIONING;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_PROVISIONING;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_SECONDARY_USER_PROVISIONING;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_SUBSIDY_DEFERRED_PROVISIONING;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_SUBSIDY_PROVISIONING;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import android.Manifest;
-import android.app.PendingIntent;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
@@ -36,7 +33,6 @@
 import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.TextView;
-import android.widget.Toast;
 
 import androidx.activity.result.ActivityResultLauncher;
 import androidx.activity.result.contract.ActivityResultContracts;
@@ -46,14 +42,13 @@
 import androidx.fragment.app.Fragment;
 import androidx.lifecycle.ViewModelProvider;
 import androidx.recyclerview.widget.RecyclerView;
-import androidx.work.WorkManager;
 
 import com.android.devicelockcontroller.R;
-import com.android.devicelockcontroller.provision.worker.PauseProvisioningWorker;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionHelper;
+import com.android.devicelockcontroller.policy.ProvisionHelperImpl;
 import com.android.devicelockcontroller.util.LogUtil;
 
-import java.time.Duration;
-import java.time.Instant;
 import java.util.Objects;
 
 /**
@@ -62,19 +57,7 @@
 public final class ProvisionInfoFragment extends Fragment {
 
     private static final String TAG = "ProvisionInfoFragment";
-
-    private ActivityResultLauncher<String> requestPermissionLauncher =
-            registerForActivityResult(new ActivityResultContracts.RequestPermission(),
-                    isGranted -> {
-                            if (isGranted) {
-                                createNotificationAndCloseActivity();
-                            } else {
-                                Toast.makeText(getActivity(),
-                                        R.string.toast_message_grant_notification_permission,
-                                        Toast.LENGTH_LONG).show();
-                            }
-                    }
-            );
+    private ActivityResultLauncher<String> mResultLauncher;
 
     @Nullable
     @Override
@@ -89,29 +72,13 @@
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         ProvisionInfoViewModel viewModel;
-        boolean isDeferredProvisioning = false;
+        ViewModelProvider viewModelProvider = new ViewModelProvider(this);
         switch (Objects.requireNonNull(getActivity()).getIntent().getAction()) {
             case ACTION_START_DEVICE_FINANCING_PROVISIONING:
-                viewModel = new ViewModelProvider(this).get(
-                        DeviceFinancingProvisionInfoViewModel.class);
-                break;
-            case ACTION_START_DEVICE_FINANCING_DEFERRED_PROVISIONING:
-                viewModel = new ViewModelProvider(this).get(
-                        DeviceFinancingDeferredProvisionInfoViewModel.class);
-                isDeferredProvisioning = true;
-                break;
-            case ACTION_START_DEVICE_FINANCING_SECONDARY_USER_PROVISIONING:
-                viewModel = new ViewModelProvider(this).get(
-                        DeviceFinancingSecondaryUserProvisionInfoViewModel.class);
+                viewModel = viewModelProvider.get(DeviceFinancingProvisionInfoViewModel.class);
                 break;
             case ACTION_START_DEVICE_SUBSIDY_PROVISIONING:
-                viewModel = new ViewModelProvider(this).get(
-                        DeviceSubsidyProvisionInfoViewModel.class);
-                break;
-            case ACTION_START_DEVICE_SUBSIDY_DEFERRED_PROVISIONING:
-                viewModel = new ViewModelProvider(this).get(
-                        DeviceSubsidyDeferredProvisionInfoViewModel.class);
-                isDeferredProvisioning = true;
+                viewModel = viewModelProvider.get(DeviceSubsidyProvisionInfoViewModel.class);
                 break;
             default:
                 LogUtil.e(TAG, "Unknown action is received, exiting");
@@ -123,8 +90,7 @@
             LogUtil.e(TAG, "Could not find provision info RecyclerView, should not reach here.");
             return;
         }
-        ProvisionInfoListAdapter adapter = new ProvisionInfoListAdapter(viewModel,
-                getViewLifecycleOwner());
+        ProvisionInfoListAdapter adapter = new ProvisionInfoListAdapter();
         viewModel.mProvisionInfoListLiveData.observe(getViewLifecycleOwner(),
                 adapter::submitList);
         recyclerView.setAdapter(adapter);
@@ -133,8 +99,7 @@
             LogUtil.e(TAG, "Could not find header ImageView, should not reach here.");
             return;
         }
-        viewModel.mHeaderDrawableIdLiveData.observe(getViewLifecycleOwner(),
-                imageView::setImageResource);
+        imageView.setImageResource(ProvisionInfoViewModel.HEADER_DRAWABLE_ID);
 
         TextView headerTextView = view.findViewById(R.id.header_text);
         if (headerTextView == null) {
@@ -156,64 +121,62 @@
         viewModel.mSubHeaderTextLiveData.observe(getViewLifecycleOwner(),
                 pair -> {
                     if (pair.first > 0 && !TextUtils.isEmpty(pair.second)) {
-                        headerTextView.setText(getString(pair.first, pair.second));
+                        subheaderTextView.setText(getString(pair.first, pair.second));
                     }
                 });
         Button next = view.findViewById(R.id.button_next);
         checkNotNull(next);
-        if (isDeferredProvisioning) {
-            next.setText(R.string.start);
-        }
+        Context context = requireContext().getApplicationContext();
+        viewModel.mIsMandatoryLiveData.observe(this,
+                isMandatory -> {
+                    if (!isMandatory) {
+                        next.setText(R.string.start);
+                        DeviceLockNotificationManager.cancelDeferredProvisioningNotification(
+                                context);
+                    }
+                    next.setVisibility(View.VISIBLE);
+                });
         next.setOnClickListener(
-                v -> startActivity(new Intent(getContext(), ProvisioningActivity.class)));
+                v -> startActivity(new Intent(context, ProvisioningActivity.class)));
+
+        ProvisionHelper provisionHelper = new ProvisionHelperImpl(context,
+                ((PolicyObjectsProvider) context).getProvisionStateController());
+        mResultLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(),
+                isGranted -> provisionHelper.pauseProvision());
         updatePreviousButton(checkNotNull(view.findViewById(R.id.button_previous)), viewModel,
-                isDeferredProvisioning);
+                provisionHelper);
     }
 
     private void updatePreviousButton(Button previous, ProvisionInfoViewModel viewModel,
-            boolean isDeferredProvisioning) {
-        if (!isDeferredProvisioning) {
-            previous.setVisibility(View.GONE);
-            return;
-        }
-        previous.setText(R.string.do_it_in_one_hour);
-        previous.setVisibility(View.VISIBLE);
+            ProvisionHelper provisionHelper) {
+        viewModel.mIsMandatoryLiveData.observe(this,
+                isMandatory -> {
+                    if (!isMandatory) {
+                        previous.setText(R.string.do_it_in_one_hour);
+                        previous.setVisibility(View.VISIBLE);
+                    }
+                });
+
 
         viewModel.mIsProvisionForcedLiveData.observe(getViewLifecycleOwner(),
                 isProvisionForced -> {
-                    previous.setEnabled(!isProvisionForced);
                     // Allow the user to defer provisioning only when provisioning is not forced.
+                    previous.setEnabled(!isProvisionForced);
                     if (!isProvisionForced) {
                         previous.setOnClickListener(
                                 v -> {
-                                    WorkManager workManager =
-                                            WorkManager.getInstance(requireContext());
-                                    PauseProvisioningWorker
-                                            .reportProvisionPausedByUser(workManager);
-                                    int notificationPermission = ContextCompat.checkSelfPermission(
-                                            requireContext(),
-                                            Manifest.permission.POST_NOTIFICATIONS);
+                                    int notificationPermission =
+                                            ContextCompat.checkSelfPermission(requireContext(),
+                                                    Manifest.permission.POST_NOTIFICATIONS);
                                     if (PackageManager.PERMISSION_GRANTED
                                             == notificationPermission) {
-                                        createNotificationAndCloseActivity();
+                                        provisionHelper.pauseProvision();
                                     } else {
-                                        requestPermissionLauncher.launch(
+                                        mResultLauncher.launch(
                                                 Manifest.permission.POST_NOTIFICATIONS);
                                     }
                                 });
                     }
                 });
     }
-
-    private void createNotificationAndCloseActivity() {
-        PendingIntent intent = PendingIntent.getActivity(
-                requireContext(),
-                /* requestCode= */ 0,
-                getActivity().getIntent(),
-                PendingIntent.FLAG_IMMUTABLE);
-        Instant resumeTime = Instant.now().plus(Duration.ofHours(1));
-        DeviceLockNotificationManager.sendDeferredEnrollmentNotification(requireContext(),
-                resumeTime, intent);
-        getActivity().finish();
-    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapter.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapter.java
index 7f4debb..207e6b3 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapter.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapter.java
@@ -16,29 +16,31 @@
 
 package com.android.devicelockcontroller.activities;
 
+import android.content.Context;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.TextView;
 
 import androidx.annotation.NonNull;
-import androidx.lifecycle.LifecycleOwner;
 import androidx.recyclerview.widget.DiffUtil;
 import androidx.recyclerview.widget.ListAdapter;
+import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.activities.ProvisionInfo.ProvisionInfoType;
+import com.android.devicelockcontroller.activities.util.UrlUtils;
+import com.android.devicelockcontroller.util.LogUtil;
 
 /**
  * An Adapter which provides the binding between {@link ProvisionInfo} and the
  * {@link androidx.recyclerview.widget.RecyclerView}.
  */
 public final class ProvisionInfoListAdapter extends
-        ListAdapter<ProvisionInfo, ProvisionInfoViewHolder> {
+        ListAdapter<ProvisionInfo, ProvisionInfoListAdapter.ProvisionInfoViewHolder> {
 
-    private final ProvisionInfoViewModel mViewModel;
-    private final LifecycleOwner mLifecycleOwner;
-
-    ProvisionInfoListAdapter(ProvisionInfoViewModel viewModel, LifecycleOwner lifecycleOwner) {
+    ProvisionInfoListAdapter() {
         super(new DiffUtil.ItemCallback<>() {
             @Override
             public boolean areItemsTheSame(@NonNull ProvisionInfo oldItem,
@@ -52,31 +54,59 @@
                 return oldItem.equals(newItem);
             }
         });
-        mViewModel = viewModel;
-        mLifecycleOwner = lifecycleOwner;
     }
 
     @NonNull
     @Override
     public ProvisionInfoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
-        View view = LayoutInflater.from(parent.getContext())
-                .inflate(R.layout.item_provision_info, parent, false);
+        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_provision_info,
+                parent, false);
         return new ProvisionInfoViewHolder(view);
     }
 
     @Override
     public void onBindViewHolder(@NonNull ProvisionInfoViewHolder provisionInfoViewHolder,
             int position) {
-        String providerName = mViewModel.mProviderNameLiveData.getValue();
-        if (TextUtils.isEmpty(providerName)) {
-            mViewModel.mProviderNameLiveData.observe(mLifecycleOwner,
-                    newValue -> notifyItemChanged(position));
-            return;
+        provisionInfoViewHolder.bindProvisionInfo(getItem(position));
+    }
+
+    /**
+     * A {@link androidx.recyclerview.widget.RecyclerView.ViewHolder} class which describes the item
+     * views used in the {@link RecyclerView}
+     */
+    static final class ProvisionInfoViewHolder extends RecyclerView.ViewHolder {
+
+        private static final String TAG = ProvisionInfoViewHolder.class.getSimpleName();
+
+        private final TextView mTextView;
+
+        ProvisionInfoViewHolder(@NonNull View itemView) {
+            super(itemView);
+            mTextView = itemView.findViewById(R.id.text_view_item_provision_info);
         }
 
-        // TODO(b/282248521): Refactor ProvisionInfoList, ProviderName, and TermsAndConditionsUrl
-        //  Live Data.
-        provisionInfoViewHolder.bind(getItem(position), providerName,
-                mViewModel.mTermsAndConditionsUrlLiveData.getValue());
+        /**
+         * Bind the item view with url.
+         *
+         * @param provisionInfo The {@link ProvisionInfo} data to bind to the held view.
+         */
+        void bindProvisionInfo(ProvisionInfo provisionInfo) {
+            Context context = mTextView.getContext();
+            String providerName = provisionInfo.getProviderName();
+            if (TextUtils.isEmpty(providerName)) {
+                LogUtil.w(TAG, "Provider name is not provided!");
+                mTextView.setText("");
+            } else if (provisionInfo.getType() == ProvisionInfoType.REGULAR) {
+                mTextView.setText(context.getString(provisionInfo.getTextId(), providerName));
+            } else {
+                UrlUtils.setUrlText(mTextView,
+                        String.format(context.getString(provisionInfo.getTextId()), providerName,
+                                provisionInfo.getUrl()));
+            }
+            mTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(provisionInfo.getDrawableId(),
+                    /* top=*/ 0,
+                    /* end=*/ 0,
+                    /* bottom=*/ 0);
+        }
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewHolder.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewHolder.java
deleted file mode 100644
index 3695d21..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewHolder.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2023 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 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;
-import com.android.devicelockcontroller.util.LogUtil;
-
-/**
- * A {@link androidx.recyclerview.widget.RecyclerView.ViewHolder} class which describes the item
- * views used in the {@link RecyclerView}
- */
-public final class ProvisionInfoViewHolder extends RecyclerView.ViewHolder {
-
-    private static final String TAG = "ProvisionInfoViewHolder";
-
-    private final TextView mTextView;
-
-    public ProvisionInfoViewHolder(@NonNull View itemView) {
-        super(itemView);
-        mTextView = itemView.findViewById(R.id.text_view_item_provision_info);
-    }
-
-    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;
-        }
-
-        // 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 85e0fbf..f6796e1 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewModel.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionInfoViewModel.java
@@ -16,129 +16,94 @@
 
 package com.android.devicelockcontroller.activities;
 
-import android.text.TextUtils;
 import android.util.Pair;
 
-import androidx.lifecycle.MediatorLiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.ViewModel;
 
+import com.android.devicelockcontroller.R;
 import com.android.devicelockcontroller.storage.GlobalParametersClient;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.util.LogUtil;
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
 import java.util.List;
 
 /**
  * This class provides the resources and {@link ProvisionInfo} to render the
- * {@link ProvisionInfoFragment} and/or {@link ProvisionNotRequiredFragment}.
+ * {@link ProvisionInfoFragment}.
  */
 public abstract class ProvisionInfoViewModel extends ViewModel {
 
-    public static final String TAG = "ProvisionInfoViewModel";
-    public static final String PROVIDER_NAME_PLACEHOLDER = "";
-    public static final int TEXT_ID_PLACEHOLDER = -1;
-    final MutableLiveData<Integer> mHeaderDrawableIdLiveData;
-    final MutableLiveData<Integer> mHeaderTextIdLiveData;
-    final MutableLiveData<Integer> mSubheaderTextIdLiveData;
-    final MutableLiveData<List<ProvisionInfo>> mProvisionInfoListLiveData;
-    final MutableLiveData<String> mProviderNameLiveData;
-    final MutableLiveData<String> mTermsAndConditionsUrlLiveData;
-    final MutableLiveData<Boolean> mIsProvisionForcedLiveData;
-    final MediatorLiveData<Pair<Integer, String>> mHeaderTextLiveData;
-    final MediatorLiveData<Pair<Integer, String>> mSubHeaderTextLiveData;
+    private static final String TAG = "ProvisionInfoViewModel";
+    static final int HEADER_DRAWABLE_ID = R.drawable.ic_info_24px;
+    static final int HEADER_TEXT_ID = R.string.enroll_your_device_header;
+    int mMandatoryHeaderTextId;
+    int mSubHeaderTextId;
+    List<ProvisionInfo> mProvisionInfoList;
+    final MutableLiveData<Boolean> mIsMandatoryLiveData = new MutableLiveData<>();
+    final MutableLiveData<Boolean> mIsProvisionForcedLiveData = new MutableLiveData<>();
+    final MutableLiveData<Pair<Integer, String>> mHeaderTextLiveData = new MutableLiveData<>();
+    final MutableLiveData<Pair<Integer, String>> mSubHeaderTextLiveData = new MutableLiveData<>();
+    final MutableLiveData<List<ProvisionInfo>> mProvisionInfoListLiveData = new MutableLiveData<>();
 
-    public ProvisionInfoViewModel() {
-        mProvisionInfoListLiveData = new MutableLiveData<>();
-        mHeaderDrawableIdLiveData = new MutableLiveData<>();
-        mHeaderTextIdLiveData = new MutableLiveData<>();
-        mSubheaderTextIdLiveData = new MutableLiveData<>();
-        mProviderNameLiveData = new MutableLiveData<>();
-        mTermsAndConditionsUrlLiveData = new MutableLiveData<>();
-        mIsProvisionForcedLiveData = new MutableLiveData<>();
-        mHeaderTextLiveData = new MediatorLiveData<>();
-        mHeaderTextLiveData.addSource(mHeaderTextIdLiveData,
-                id -> {
-                    Pair<Integer, String> oldValue = mHeaderTextLiveData.getValue();
-                    mHeaderTextLiveData.setValue(oldValue == null
-                            ? new Pair<>(id, PROVIDER_NAME_PLACEHOLDER)
-                            : new Pair<>(id, oldValue.second));
-                });
-        mHeaderTextLiveData.addSource(mProviderNameLiveData,
-                providerName -> {
-                    Pair<Integer, String> oldValue = mHeaderTextLiveData.getValue();
-                    mHeaderTextLiveData.setValue(oldValue == null
-                            ? new Pair<>(TEXT_ID_PLACEHOLDER, providerName)
-                            : new Pair<>(oldValue.first, providerName));
-                });
-        mSubHeaderTextLiveData = new MediatorLiveData<>();
-        mSubHeaderTextLiveData.addSource(mSubheaderTextIdLiveData,
-                id -> {
-                    Pair<Integer, String> oldValue = mSubHeaderTextLiveData.getValue();
-                    mSubHeaderTextLiveData.setValue(oldValue == null
-                            ? new Pair<>(id, PROVIDER_NAME_PLACEHOLDER)
-                            : new Pair<>(id, oldValue.second));
-                });
-        mSubHeaderTextLiveData.addSource(mProviderNameLiveData,
-                providerName -> {
-                    Pair<Integer, String> oldValue = mSubHeaderTextLiveData.getValue();
-                    mSubHeaderTextLiveData.setValue(oldValue == null
-                            ? new Pair<>(TEXT_ID_PLACEHOLDER, providerName)
-                            : new Pair<>(oldValue.first, providerName));
-                });
-
-        Futures.addCallback(
-                SetupParametersClient.getInstance().getKioskAppProviderName(),
-                new FutureCallback<>() {
-                    @Override
-                    public void onSuccess(String providerName) {
-                        if (TextUtils.isEmpty(providerName)) {
-                            LogUtil.e(TAG, "Device provider name is empty, should not reach here.");
-                            return;
+    void retrieveData() {
+        SetupParametersClient setupParametersClient = SetupParametersClient.getInstance();
+        ListenableFuture<String> kioskAppProviderNameFuture =
+                setupParametersClient.getKioskAppProviderName();
+        ListenableFuture<Boolean> isMandatoryFuture = setupParametersClient.isProvisionMandatory();
+        ListenableFuture<String> termsAndConditionsUrlFuture =
+                setupParametersClient.getTermsAndConditionsUrl();
+        ListenableFuture<String> supportUrlFuture = setupParametersClient.getSupportUrl();
+        ListenableFuture<Boolean> isProvisionForcedFuture =
+                GlobalParametersClient.getInstance().isProvisionForced();
+        ListenableFuture<Void> result = Futures.whenAllSucceed(isMandatoryFuture,
+                        kioskAppProviderNameFuture, termsAndConditionsUrlFuture, supportUrlFuture,
+                        isProvisionForcedFuture)
+                .call(() -> {
+                    boolean isMandatory = Futures.getDone(isMandatoryFuture);
+                    String providerName = Futures.getDone(kioskAppProviderNameFuture);
+                    String termsAndConditionUrl = Futures.getDone(termsAndConditionsUrlFuture);
+                    String supportUrl = Futures.getDone(supportUrlFuture);
+                    for (int i = 0, size = mProvisionInfoList.size(); i < size; ++i) {
+                        ProvisionInfo provisionInfo = mProvisionInfoList.get(i);
+                        switch (provisionInfo.getType()) {
+                            case ProvisionInfo.ProvisionInfoType.REGULAR -> provisionInfo.setUrl(
+                                    "");
+                            case ProvisionInfo.ProvisionInfoType.TERMS_AND_CONDITIONS ->
+                                    provisionInfo.setUrl(termsAndConditionUrl);
+                            case ProvisionInfo.ProvisionInfoType.SUPPORT -> provisionInfo.setUrl(
+                                    supportUrl);
+                            default -> throw new IllegalStateException(
+                                    "Unexpected value: " + provisionInfo.getType());
                         }
-                        mProviderNameLiveData.postValue(providerName);
+                        provisionInfo.setProviderName(providerName);
                     }
-
-                    @Override
-                    public void onFailure(Throwable t) {
-                        LogUtil.e(TAG, "Failed to get Kiosk app provider name", t);
-                    }
+                    mProvisionInfoListLiveData.postValue(mProvisionInfoList);
+                    mIsMandatoryLiveData.postValue(isMandatory);
+                    mHeaderTextLiveData.postValue(
+                            new Pair<>(isMandatory ? mMandatoryHeaderTextId : HEADER_TEXT_ID,
+                                    providerName));
+                    mSubHeaderTextLiveData.postValue(
+                            new Pair<>(isMandatory ? 0 : mSubHeaderTextId,
+                                    providerName));
+                    mIsProvisionForcedLiveData.postValue(Futures.getDone(isProvisionForcedFuture));
+                    return null;
                 }, MoreExecutors.directExecutor());
+        Futures.addCallback(result, new FutureCallback<>() {
+            @Override
+            public void onSuccess(Void result) {
+                LogUtil.i(TAG, "Successfully updated live data");
+            }
 
-        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());
-
-        Futures.addCallback(GlobalParametersClient.getInstance().isProvisionForced(),
-                new FutureCallback<>() {
-                    @Override
-                    public void onSuccess(Boolean isProvisionForced) {
-                        mIsProvisionForcedLiveData.postValue(isProvisionForced);
-                    }
-
-                    @Override
-                    public void onFailure(Throwable t) {
-                        LogUtil.e(TAG, "Failed to get if provision should be forced", t);
-                    }
-                }, MoreExecutors.directExecutor());
+            @Override
+            public void onFailure(Throwable t) {
+                throw new RuntimeException(t);
+            }
+        }, MoreExecutors.directExecutor());
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionNotRequiredFragment.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionNotRequiredFragment.java
deleted file mode 100644
index 664fa5d..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisionNotRequiredFragment.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
-
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_DEVICE_FINANCING_PROVISION_NOT_REQUIRED;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_DEVICE_SUBSIDY_PROVISION_NOT_REQUIRED;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.lifecycle.ViewModelProvider;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.devicelockcontroller.R;
-import com.android.devicelockcontroller.util.LogUtil;
-
-import java.util.Objects;
-
-/**
- * The screen which tells users that provision is not required any more.
- */
-public final class ProvisionNotRequiredFragment extends Fragment {
-
-    private static final String TAG = "ProvisionNotRequiredFragment";
-
-    @Nullable
-    @Override
-    public View onCreateView(
-            @NonNull LayoutInflater inflater,
-            @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.fragment_provision_not_required, container, false);
-    }
-
-    @Override
-    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        ProvisionInfoViewModel viewModel;
-        switch (Objects.requireNonNull(getActivity()).getIntent().getAction()) {
-            case ACTION_DEVICE_FINANCING_PROVISION_NOT_REQUIRED:
-                viewModel = new ViewModelProvider(this).get(
-                        DeviceFinancingProvisionNotRequiredViewModel.class);
-                break;
-            case ACTION_DEVICE_SUBSIDY_PROVISION_NOT_REQUIRED:
-                viewModel = new ViewModelProvider(this).get(
-                        DeviceSubsidyProvisionNotRequiredViewModel.class);
-                break;
-            default:
-                LogUtil.e(TAG, "Unknown action is received, exiting");
-                return;
-        }
-
-        RecyclerView recyclerView = view.findViewById(R.id.recyclerview_provision_info);
-        checkNotNull(recyclerView);
-
-        ProvisionInfoListAdapter adapter = new ProvisionInfoListAdapter(viewModel,
-                getViewLifecycleOwner());
-        viewModel.mProvisionInfoListLiveData.observe(getViewLifecycleOwner(),
-                adapter::submitList);
-        recyclerView.setAdapter(adapter);
-
-        ImageView imageView = view.findViewById(R.id.header_icon);
-        checkNotNull(imageView);
-        viewModel.mHeaderDrawableIdLiveData.observe(getViewLifecycleOwner(),
-                imageView::setImageResource);
-
-        TextView headerTextView = view.findViewById(R.id.header_text);
-        checkNotNull(headerTextView);
-        viewModel.mHeaderTextLiveData.observe(getViewLifecycleOwner(),
-                pair -> {
-                    if (pair.first > 0 && !TextUtils.isEmpty(pair.second)) {
-                        headerTextView.setText(getString(pair.first, pair.second));
-                    }
-                });
-
-        TextView subheaderTextView = view.findViewById(R.id.subheader_text);
-        checkNotNull(subheaderTextView);
-        viewModel.mSubHeaderTextLiveData.observe(getViewLifecycleOwner(),
-                pair -> {
-                    if (pair.first > 0 && !TextUtils.isEmpty(pair.second)) {
-                        subheaderTextView.setText(getString(pair.first, pair.second));
-                    }
-                });
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningActivity.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningActivity.java
index df15d2b..588e4ba 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningActivity.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningActivity.java
@@ -16,6 +16,10 @@
 
 package com.android.devicelockcontroller.activities;
 
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.POLICY_ENFORCEMENT_FAILED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.UNKNOWN_REASON;
+
+import android.content.Intent;
 import android.os.Bundle;
 import android.view.WindowInsets;
 import android.view.WindowInsetsController;
@@ -25,12 +29,26 @@
 import androidx.lifecycle.ViewModelProvider;
 
 import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.util.LogUtil;
 
 /**
  * The activity displayed when provisioning is in progress.
  */
 public final class ProvisioningActivity extends AppCompatActivity {
 
+    private static final String TAG = "ProvisioningActivity";
+
+    static final String EXTRA_SHOW_PROVISION_FAILED_UI_ON_START =
+            "com.android.devicelockcontroller.activities.extra.SHOW_PROVISION_FAILED_UI_ON_START";
+
+    /**
+     * An extra boolean set on the provisioning activity intent to signal that it should
+     * show the provisioning failed screen on start.
+     */
+    public static final String EXTRA_SHOW_CRITICAL_PROVISION_FAILED_UI_ON_START =
+            "com.android.devicelockcontroller.activities.extra.SHOW_CRITICAL_PROVISION"
+                    + "_FAILED_UI_ON_START";
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -49,10 +67,25 @@
                     .replace(R.id.fragment_container, progressFragment)
                     .commit();
         });
-
-        getSupportFragmentManager()
-                .beginTransaction()
-                .add(R.id.fragment_container, new DevicePoliciesFragment())
-                .commit();
+        final Intent intent = getIntent();
+        if (intent.getBooleanExtra(EXTRA_SHOW_CRITICAL_PROVISION_FAILED_UI_ON_START, false)) {
+            LogUtil.d(TAG, "showing critical provision failed ui");
+            viewModel.setProvisioningProgress(
+                    ProvisioningProgress.getMandatoryProvisioningFailedProgress(
+                            POLICY_ENFORCEMENT_FAILED));
+        } else if (intent.getBooleanExtra(EXTRA_SHOW_PROVISION_FAILED_UI_ON_START, false)) {
+            LogUtil.d(TAG, "showing provision failed ui");
+            // Using an unknown reason should not be allowed but is okay here because the UI will
+            // not report to the server
+            // TODO(b/321110148): Refactor reporting logic so that we don't need to do this
+            viewModel.setProvisioningProgress(
+                    ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(UNKNOWN_REASON));
+        }
+        if (savedInstanceState == null) {
+            getSupportFragmentManager()
+                    .beginTransaction()
+                    .add(R.id.fragment_container, new DevicePoliciesFragment())
+                    .commit();
+        }
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgress.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgress.java
index fa3ed2d..f7028bf 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgress.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgress.java
@@ -16,7 +16,12 @@
 
 package com.android.devicelockcontroller.activities;
 
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.UNKNOWN_REASON;
+
 import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason;
+
+import java.util.Objects;
 
 /**
  * Different stages of the provisioning progress.
@@ -34,15 +39,94 @@
     final int mIconId;
     final int mHeaderId;
     final int mSubheaderId;
+    final boolean mProgressBarVisible;
+    final boolean mBottomViewVisible;
+
+    final boolean mCountDownTimerVisible;
+
+    @ProvisionFailureReason
+    final int mFailureReason;
 
     ProvisioningProgress(int iconId, int headerId) {
         this(iconId, headerId, 0);
     }
 
     ProvisioningProgress(int iconId, int headerId, int subheaderId) {
-        this.mHeaderId = headerId;
-        this.mIconId = iconId;
-        this.mSubheaderId = subheaderId;
+        this(iconId, headerId, subheaderId, /* progressBarVisible= */ true,
+                /* bottomViewVisible= */ false, /* countDownTimerVisible= */ false, UNKNOWN_REASON);
     }
 
+    ProvisioningProgress(boolean bottomViewVisible, boolean countDownTimerVisible,
+            @ProvisionFailureReason int failureReason) {
+        this(R.drawable.ic_warning_24px, R.string.provisioning_failed,
+                R.string.click_to_contact_financier, /* progressBarVisible=*/ false,
+                bottomViewVisible, countDownTimerVisible, failureReason);
+    }
+
+    ProvisioningProgress(int iconId, int headerId, int subheaderId, boolean progressBarVisible,
+            boolean bottomViewVisible, boolean countDownTimerVisible,
+            @ProvisionFailureReason int failureReason) {
+        mHeaderId = headerId;
+        mIconId = iconId;
+        mSubheaderId = subheaderId;
+        mProgressBarVisible = progressBarVisible;
+        mBottomViewVisible = bottomViewVisible;
+        mCountDownTimerVisible = countDownTimerVisible;
+        mFailureReason = failureReason;
+    }
+
+    /**
+     * Get the provision failure progress item for mandatory case with the failure reason.
+     *
+     * @param failureReason one of {@link ProvisionFailureReason} The reason why provision failed.
+     */
+    public static ProvisioningProgress getMandatoryProvisioningFailedProgress(
+            @ProvisionFailureReason int failureReason) {
+        return new ProvisioningProgress(
+                /* bottomViewVisible= */ false, /* countDownTimerVisible= */ true, failureReason);
+    }
+
+    /**
+     * Get the provision failure progress item for non-mandatory case with the failure reason.
+     *
+     * @param failureReason one of {@link ProvisionFailureReason} The reason why provision failed.
+     */
+    public static ProvisioningProgress getNonMandatoryProvisioningFailedProgress(
+            @ProvisionFailureReason int failureReason) {
+        return new ProvisioningProgress(
+                /* bottomViewVisible= */ true, /* countDownTimerVisible= */ false, failureReason);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ProvisioningProgress that = (ProvisioningProgress) o;
+        return mIconId == that.mIconId && mHeaderId == that.mHeaderId
+                && mSubheaderId == that.mSubheaderId
+                && mProgressBarVisible == that.mProgressBarVisible
+                && mBottomViewVisible == that.mBottomViewVisible
+                && mCountDownTimerVisible == that.mCountDownTimerVisible
+                && mFailureReason == that.mFailureReason;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIconId, mHeaderId, mSubheaderId, mProgressBarVisible,
+                mBottomViewVisible,
+                mCountDownTimerVisible, mFailureReason);
+    }
+
+    @Override
+    public String toString() {
+        return "ProvisioningProgress{"
+                + "mIconId=" + mIconId
+                + ", mHeaderId=" + mHeaderId
+                + ", mSubheaderId=" + mSubheaderId
+                + ", mProgressBarVisible=" + mProgressBarVisible
+                + ", mBottomViewVisible=" + mBottomViewVisible
+                + ", mCountDownTimerVisible=" + mCountDownTimerVisible
+                + ", mFailureReason=" + mFailureReason
+                + '}';
+    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgressController.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgressController.java
new file mode 100644
index 0000000..d61bea0
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgressController.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
+
+/**
+ * An interface providing API to change provisioning progress.
+ */
+public interface ProvisioningProgressController {
+    /**
+     * Set the {@link ProvisioningProgress} to the given state.
+     *
+     * <p>This method is thread-safe and can be called from any thread.
+     */
+    void setProvisioningProgress(ProvisioningProgress provisioningProgress);
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgressViewModel.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgressViewModel.java
index 2838ec9..633252a 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgressViewModel.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/ProvisioningProgressViewModel.java
@@ -19,9 +19,7 @@
 import android.text.TextUtils;
 
 import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MediatorLiveData;
 import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.Observer;
 import androidx.lifecycle.ViewModel;
 
 import com.android.devicelockcontroller.storage.SetupParametersClient;
@@ -29,24 +27,32 @@
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
 /**
  * A {@link ViewModel} which provides {@link ProvisioningProgress} to the
  * {@link ProvisioningActivity}.
  */
-public final class ProvisioningProgressViewModel extends ViewModel {
+public final class ProvisioningProgressViewModel extends ViewModel implements
+        ProvisioningProgressController {
 
     private static final String TAG = "ProvisioningProgressViewModel";
 
     final MutableLiveData<String> mProviderNameLiveData;
-    private final MediatorLiveData<ProvisioningProgress> mProvisioningProgressLiveData;
+    final MutableLiveData<String> mSupportUrlLiveData;
+    private volatile boolean mAreProviderNameAndSupportUrlReady;
+    private final MutableLiveData<ProvisioningProgress> mProvisioningProgressLiveData;
     private ProvisioningProgress mProvisioningProgress;
 
     public ProvisioningProgressViewModel() {
         mProviderNameLiveData = new MutableLiveData<>();
+        mSupportUrlLiveData = new MutableLiveData<>();
+
+        ListenableFuture<String> getKioskAppProviderNameFuture =
+                SetupParametersClient.getInstance().getKioskAppProviderName();
         Futures.addCallback(
-                SetupParametersClient.getInstance().getKioskAppProviderName(),
+                getKioskAppProviderNameFuture,
                 new FutureCallback<>() {
                     @Override
                     public void onSuccess(String providerName) {
@@ -63,15 +69,39 @@
                     }
                 }, MoreExecutors.directExecutor());
 
-        mProvisioningProgressLiveData = new MediatorLiveData<>();
-        Observer<String> observer = unused -> {
-            LogUtil.d(TAG, "The upstream ProviderNameLiveData is complete");
-            if (mProvisioningProgress != null) {
-                LogUtil.d(TAG, "Sending ProvisioningProgress to observers.");
-                mProvisioningProgressLiveData.postValue(mProvisioningProgress);
+        ListenableFuture<String> getSupportUrlFuture =
+                SetupParametersClient.getInstance().getSupportUrl();
+        Futures.addCallback(getSupportUrlFuture, new FutureCallback<>() {
+            @Override
+            public void onSuccess(String supportUrl) {
+                mSupportUrlLiveData.postValue(supportUrl);
             }
-        };
-        mProvisioningProgressLiveData.addSource(mProviderNameLiveData, observer);
+
+            @Override
+            public void onFailure(Throwable t) {
+                LogUtil.e(TAG, "Failed to get support Url", t);
+            }
+        }, MoreExecutors.directExecutor());
+
+        mProvisioningProgressLiveData = new MutableLiveData<>();
+        ListenableFuture<?> result = Futures.whenAllSucceed(getKioskAppProviderNameFuture,
+                getSupportUrlFuture).run(() -> {
+                    mAreProviderNameAndSupportUrlReady = true;
+                    if (mProvisioningProgress != null) {
+                        mProvisioningProgressLiveData.postValue(mProvisioningProgress);
+                    }
+                }, MoreExecutors.directExecutor());
+        Futures.addCallback(result, new FutureCallback<Object>() {
+            @Override
+            public void onSuccess(Object result) {
+                LogUtil.i(TAG, "Successfully updated provisioning progress live data");
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                throw new RuntimeException(t);
+            }
+        }, MoreExecutors.directExecutor());
     }
 
     /**
@@ -89,16 +119,16 @@
      *
      * <p>This method is thread-safe and can be called from any thread.
      */
+    @Override
     public void setProvisioningProgress(ProvisioningProgress provisioningProgress) {
-        if (mProviderNameLiveData.getValue() != null) {
+        if (mAreProviderNameAndSupportUrlReady) {
             LogUtil.d(TAG, "Updating ProvisioningProgress");
+            mProvisioningProgress = provisioningProgress;
             mProvisioningProgressLiveData.postValue(provisioningProgress);
         } else {
             LogUtil.d(TAG,
-                    "The upstream ProviderNameLiveData is not ready yet, hold on until it "
-                            + "completes");
+                    "The upstream LiveData is not ready yet, hold on until it completes");
             mProvisioningProgress = provisioningProgress;
         }
     }
-
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/UrlTextPreference.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/UrlTextPreference.java
new file mode 100644
index 0000000..219c226
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/UrlTextPreference.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.devicelockcontroller.activities.util.UrlUtils;
+
+public class UrlTextPreference extends Preference {
+
+    public static final String TAG = UrlTextPreference.class.getSimpleName();
+
+    public UrlTextPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        TextView title = holder.itemView.findViewById(android.R.id.title);
+        if (title != null && !TextUtils.isEmpty(getTitle())) {
+            UrlUtils.setUrlText(title, String.valueOf(getTitle()));
+            title.setMovementMethod(LinkMovementMethod.getInstance());
+        }
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/util/UrlUtils.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/util/UrlUtils.java
new file mode 100644
index 0000000..0fe9d28
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/util/UrlUtils.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.activities.util;
+
+import android.content.Context;
+import android.content.Intent;
+import android.text.Html;
+import android.text.Spannable;
+import android.text.SpannableString;
+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 com.android.devicelockcontroller.activities.HelpActivity;
+
+/**
+ * A utility class which handles URL.
+ */
+public final class UrlUtils {
+
+    private UrlUtils() {}
+
+    /**
+     * Sets a text on the given {@link TextView}. If the text contains URLs, the text will be
+     * formatted.
+     */
+    public static void setUrlText(TextView textView, String text) {
+        SpannableString spannableString =
+                new SpannableString(Html.fromHtml(text, Html.FROM_HTML_MODE_COMPACT));
+        if (handleUrlSpan(spannableString)) {
+            textView.setText(spannableString);
+            textView.setMovementMethod(LinkMovementMethod.getInstance());
+        } else {
+            textView.setText(text);
+        }
+    }
+
+    private static boolean handleUrlSpan(SpannableString text) {
+        boolean hasUrl = false;
+        URLSpan[] spans = text.getSpans(0, text.length(), URLSpan.class);
+        for (URLSpan span : spans) {
+            int start = text.getSpanStart(span);
+            int end = text.getSpanEnd(span);
+            ClickableSpan clickableSpan = new CustomClickableSpan(span.getURL());
+            text.removeSpan(span);
+            text.setSpan(clickableSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            hasUrl = true;
+        }
+        return hasUrl;
+    }
+
+    /**
+     * A {@link ClickableSpan} which will open the URL the text contains in the
+     * {@link HelpActivity}.
+     */
+    private static final class CustomClickableSpan extends ClickableSpan {
+        final String mUrl;
+
+        CustomClickableSpan(String url) {
+            mUrl = url;
+        }
+
+        @Override
+        public void onClick(@NonNull View view) {
+            Context context = view.getContext();
+            Intent webIntent = new Intent(context, HelpActivity.class);
+            webIntent.putExtra(HelpActivity.EXTRA_URL_PARAM, mUrl);
+            context.startActivity(webIntent);
+        }
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/common/DeviceLockConstants.java b/DeviceLockController/src/com/android/devicelockcontroller/common/DeviceLockConstants.java
index 0e86c05..0cc3cd2 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/common/DeviceLockConstants.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/common/DeviceLockConstants.java
@@ -16,8 +16,6 @@
 
 package com.android.devicelockcontroller.common;
 
-import android.content.Context;
-
 import androidx.annotation.IntDef;
 
 import java.lang.annotation.ElementType;
@@ -27,8 +25,10 @@
 
 /** Constants being used by more than one class in the Device Lock application. */
 public final class DeviceLockConstants {
-
-    public static final String KEY_KIOSK_APP_INSTALLED = "devicelock_kiosk_app_installed";
+    /** Device reset count down minute when mandatory provision fails */
+    public static final int MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE = 2;
+    /** Device reset count down minute when non-mandatory provision fails */
+    public static final int NON_MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE = 30;
 
     // Constants related to unique device identifiers.
     @Retention(RetentionPolicy.SOURCE)
@@ -90,10 +90,27 @@
         int TYPE_SUBSIDY = 2;
     }
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            ProvisionFailureReason.UNKNOWN_REASON,
+            ProvisionFailureReason.PLAY_TASK_UNAVAILABLE,
+            ProvisionFailureReason.PLAY_INSTALLATION_FAILED,
+            ProvisionFailureReason.COUNTRY_INFO_UNAVAILABLE,
+            ProvisionFailureReason.NOT_IN_ELIGIBLE_COUNTRY,
+            ProvisionFailureReason.POLICY_ENFORCEMENT_FAILED,
+    })
+    public @interface ProvisionFailureReason {
+        int UNKNOWN_REASON = 0;
+        int PLAY_TASK_UNAVAILABLE = 1;
+        int PLAY_INSTALLATION_FAILED = 2;
+        int COUNTRY_INFO_UNAVAILABLE = 3;
+        int NOT_IN_ELIGIBLE_COUNTRY = 4;
+        int POLICY_ENFORCEMENT_FAILED = 5;
+        int DEADLINE_PASSED = 6;
+    }
+
     public static final String EXTRA_KIOSK_PACKAGE =
             "com.android.devicelockcontroller.KIOSK_PACKAGE";
-    public static final String EXTRA_KIOSK_SETUP_ACTIVITY =
-            "com.android.devicelockcontroller.KIOSK_SETUP_ACTIVITY";
     public static final String EXTRA_KIOSK_DISABLE_OUTGOING_CALLS =
             "com.android.devicelockcontroller.KIOSK_DISABLE_OUTGOING_CALLS";
     /**
@@ -121,66 +138,10 @@
 
     public static final String ACTION_START_DEVICE_FINANCING_PROVISIONING =
             "com.android.devicelockcontroller.action.START_DEVICE_FINANCING_PROVISIONING";
-    public static final String ACTION_START_DEVICE_FINANCING_DEFERRED_PROVISIONING =
-            "com.android.devicelockcontroller.action.START_DEVICE_FINANCING_DEFERRED_PROVISIONING";
-
-    public static final String ACTION_START_DEVICE_FINANCING_SECONDARY_USER_PROVISIONING =
-            "com.android.devicelockcontroller.action"
-            + ".START_DEVICE_FINANCING_SECONDARY_USER_PROVISIONING";
 
     public static final String ACTION_START_DEVICE_SUBSIDY_PROVISIONING =
             "com.android.devicelockcontroller.action.START_DEVICE_SUBSIDY_PROVISIONING";
 
-    public static final String ACTION_START_DEVICE_SUBSIDY_DEFERRED_PROVISIONING =
-            "com.android.devicelockcontroller.action.START_DEVICE_SUBSIDY_DEFERRED_PROVISIONING";
-
-    public static final String ACTION_DEVICE_FINANCING_PROVISION_NOT_REQUIRED =
-            "com.android.devicelockcontroller.action.DEVICE_FINANCING_PROVISION_NOT_REQUIRED";
-
-    public static final String ACTION_DEVICE_SUBSIDY_PROVISION_NOT_REQUIRED =
-            "com.android.devicelockcontroller.action.DEVICE_SUBSIDY_PROVISION_NOT_REQUIRED";
-
-    public static final String ACTION_START_DEVICE_FINANCING_ENROLLMENT =
-            "com.android.devicelockcontroller.action.START_DEVICE_FINANCING_ENROLLMENT";
-
-    public static final String ACTION_START_DEVICE_SUBSIDY_ENROLLMENT =
-            "com.android.devicelockcontroller.action.START_DEVICE_SUBSIDY_ENROLLMENT";
-
-    /** Uses the package name of {@link Context#getPackageName()} to return the landing activity. */
-    public static String getLandingActivity(Context context) {
-        return context.getPackageName() + "/"
-               + "com.android.devicelockcontroller.activities.LandingActivity";
-    }
-
-    /** Definitions for setup failure types. */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(
-            value = {
-                    SetupFailureReason.SETUP_FAILED,
-                    SetupFailureReason.DOWNLOAD_FAILED,
-                    SetupFailureReason.VERIFICATION_FAILED,
-                    SetupFailureReason.INSTALL_FAILED,
-                    SetupFailureReason.PACKAGE_DOES_NOT_EXIST,
-                    SetupFailureReason.DELETE_PACKAGE_FAILED,
-                    SetupFailureReason.INSTALL_EXISTING_FAILED,
-            })
-    public @interface SetupFailureReason {
-        /** Setup failed to complete */
-        int SETUP_FAILED = 0;
-        /** Failed to download the creditor apk. */
-        int DOWNLOAD_FAILED = 1;
-        /** Verification of the creditor apk failed. */
-        int VERIFICATION_FAILED = 2;
-        /** Failed to install the creditor apk. */
-        int INSTALL_FAILED = 3;
-        /** Pre-installed package not found */
-        int PACKAGE_DOES_NOT_EXIST = 4;
-        /** Delete apk failed */
-        int DELETE_PACKAGE_FAILED = 5;
-        /** Install package for secondary users failed */
-        int INSTALL_EXISTING_FAILED = 6;
-    }
-
     /** Definitions for device provision states. */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(
@@ -213,7 +174,7 @@
         int PROVISION_STATE_SUCCESS = 5;
     }
 
-    /** Restrict instantiation. */
+    /** Prevent instantiation. */
     private DeviceLockConstants() {
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/debug/Android.bp b/DeviceLockController/src/com/android/devicelockcontroller/debug/Android.bp
index 01dd371..e1bc70b 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/debug/Android.bp
+++ b/DeviceLockController/src/com/android/devicelockcontroller/debug/Android.bp
@@ -15,8 +15,12 @@
 //
 
 package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "packages_modules_DeviceLock_DeviceLockController_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: [
-        "Android-Apache-2.0",
         "packages_modules_DeviceLock_DeviceLockController_license",
     ],
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/debug/AndroidManifest.xml b/DeviceLockController/src/com/android/devicelockcontroller/debug/AndroidManifest.xml
index a48c103..f976d81 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/debug/AndroidManifest.xml
+++ b/DeviceLockController/src/com/android/devicelockcontroller/debug/AndroidManifest.xml
@@ -23,25 +23,18 @@
     Note that this manifest is only included in debug build.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     package="com.android.devicelockcontroller">
 
     <application android:name=".DeviceLockControllerApplication">
         <!-- Receiver used for debugging purpose.
             This component is only included in debug build -->
-        <receiver android:name="com.android.devicelockcontroller.debug.SetupParametersOverrider"
-            android:exported="true" />
-
-        <receiver android:name="com.android.devicelockcontroller.debug.SetupFlowStarter"
-            android:exported="true" />
-
-        <receiver android:name="com.android.devicelockcontroller.debug.DeviceLockCommandReceiver"
-            android:exported="true" />
-
         <activity
             android:name="com.android.devicelockcontroller.activities.HelpActivity"
             android:exported="true"
             tools:replace="android:exported" />
+
         <activity
             android:name="com.android.devicelockcontroller.activities.LandingActivity"
             android:exported="true"
@@ -52,11 +45,6 @@
             android:exported="true"
             tools:replace="android:exported" />
 
-        <activity
-            android:name="com.android.devicelockcontroller.activities.DeviceEnrollmentActivity"
-            android:exported="true"
-            tools:replace="android:exported" />
-
         <activity-alias
             android:name="com.android.devicelockcontroller.activities.DeviceFinancingSecondaryUserLandingActivity"
             android:exported="true"
@@ -65,6 +53,7 @@
             android:name="com.android.devicelockcontroller.activities.DeviceFinancingDeferredProvisioningLandingActivity"
             android:exported="true"
             tools:replace="android:exported" />
+
         <activity-alias
             android:name="com.android.devicelockcontroller.activities.DeviceSubsidyProvisioningLandingActivity"
             android:exported="true"
@@ -75,20 +64,13 @@
             android:exported="true"
             tools:replace="android:exported" />
 
-        <activity-alias
-            android:name="com.android.devicelockcontroller.activities.DeviceSubsidyEnrollmentActivity"
-            android:exported="true"
-            tools:replace="android:exported" />
+        <receiver
+            android:name="com.android.devicelockcontroller.debug.SetupParametersOverrider"
+            android:exported="true" />
 
-        <activity-alias
-            android:name="com.android.devicelockcontroller.activities.DeviceFinancingProvisionNotRequiredLandingActivity"
-            android:exported="true"
-            tools:replace="android:exported"/>
-
-        <activity-alias
-            android:name="com.android.devicelockcontroller.activities.DeviceSubsidyProvisionNotRequiredLandingActivity"
-            android:exported="true"
-            tools:replace="android:exported"/>
+        <receiver
+            android:name="com.android.devicelockcontroller.debug.DeviceLockCommandReceiver"
+            android:exported="true" />
 
         <receiver
             android:name="com.android.devicelockcontroller.receivers.CheckInBootCompletedReceiver"
@@ -96,7 +78,7 @@
             tools:replace="android:exported" />
 
         <receiver
-            android:name="com.android.devicelockcontroller.receivers.LockTaskBootCompletedReceiver"
+            android:name="com.android.devicelockcontroller.receivers.FinalizationBootCompletedReceiver"
             android:exported="true"
             tools:replace="android:exported" />
 
@@ -105,6 +87,36 @@
             android:exported="true"
             tools:replace="android:exported" />
 
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.RecordBootTimestampReceiver"
+            android:exported="true"
+            tools:replace="android:exported" />
+
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.TimeChangedBroadcastReceiver"
+            android:exported="true"
+            tools:replace="android:exported" />
+
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.ResumeProvisionReceiver"
+            android:exported="true"
+            tools:replace="android:exported" />
+
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.NextProvisionFailedStepReceiver"
+            android:exported="true"
+            tools:replace="android:exported" />
+
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.ResetDeviceReceiver"
+            android:exported="true"
+            tools:replace="android:exported" />
+
+        <receiver
+            android:name="com.android.devicelockcontroller.receivers.ProvisionReadyReceiver"
+            android:exported="true"
+            tools:replace="android:exported" />
+
         <service
             android:name="com.android.devicelockcontroller.DeviceLockControllerService"
             android:exported="true"
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/debug/DeviceCheckInClientDebug.java b/DeviceLockController/src/com/android/devicelockcontroller/debug/DeviceCheckInClientDebug.java
index 8660fa6..a61cb45 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/debug/DeviceCheckInClientDebug.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/debug/DeviceCheckInClientDebug.java
@@ -17,9 +17,11 @@
 package com.android.devicelockcontroller.debug;
 
 import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_UNSPECIFIED;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.STATUS_UNSPECIFIED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.READY_FOR_PROVISION;
 
-import android.os.SystemProperties;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.SystemClock;
 import android.util.ArraySet;
 
 import androidx.annotation.Keep;
@@ -28,6 +30,7 @@
 import com.android.devicelockcontroller.common.DeviceId;
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceCheckInStatus;
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
+import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason;
 import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType;
 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
 import com.android.devicelockcontroller.provision.grpc.GetDeviceCheckInStatusGrpcResponse;
@@ -35,18 +38,85 @@
 import com.android.devicelockcontroller.provision.grpc.PauseDeviceProvisioningGrpcResponse;
 import com.android.devicelockcontroller.provision.grpc.ProvisioningConfiguration;
 import com.android.devicelockcontroller.provision.grpc.ReportDeviceProvisionStateGrpcResponse;
+import com.android.devicelockcontroller.util.LogUtil;
+import com.android.devicelockcontroller.util.ThreadAsserts;
 
 import java.time.Duration;
 import java.time.Instant;
+import java.util.List;
 
 /**
  * An implementation of the {@link DeviceCheckInClient} which simulate server responses by
- * reading it from {@link  SystemProperties}.
+ * reading it from local storage.
  */
 @Keep
 public final class DeviceCheckInClientDebug extends DeviceCheckInClient {
 
     public static final String TAG = "DeviceCheckInClientDebug";
+    public static final String DEBUG_DEVICELOCK_CHECKIN_STATUS = "debug.devicelock.checkin.status";
+    public static final String DEBUG_DEVICELOCK_CHECKIN_RETRY_DELAY =
+            "debug.devicelock.checkin.retry-delay";
+    public static final String DEBUG_DEVICELOCK_CHECKIN_FORCE_PROVISIONING =
+            "debug.devicelock.checkin.force-provisioning";
+    public static final String DEBUG_DEVICELOCK_CHECKIN_APPROVED_COUNTRY =
+            "debug.devicelock.checkin.approved-country";
+    public static final String DEBUG_DEVICELOCK_CHECKIN_NEXT_PROVISION_STATE =
+            "debug.devicelock.checkin.next-provision-state";
+    public static final String DEBUG_DEVICELOCK_CHECKIN_DAYS_LEFT_UNTIL_RESET =
+            "debug.devicelock.checkin.days-left-until-reset";
+
+    static void setDebugClientEnabled(Context context, boolean enabled) {
+        getSharedPreferences(context).edit().putBoolean(DEBUG_DEVICELOCK_CHECKIN, enabled).apply();
+    }
+
+    static void setDebugCheckInStatus(Context context, @DeviceCheckInStatus int status) {
+        getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_CHECKIN_STATUS,
+                status).apply();
+    }
+
+    static void setDebugForceProvisioning(Context context, boolean isForced) {
+        getSharedPreferences(context).edit().putBoolean(DEBUG_DEVICELOCK_CHECKIN_FORCE_PROVISIONING,
+                isForced).apply();
+    }
+
+    static void setDebugCheckInRetryDelay(Context context, int delayMinute) {
+        getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_CHECKIN_RETRY_DELAY,
+                delayMinute).apply();
+    }
+
+    static void setDebugApprovedCountry(Context context,
+            boolean isInApprovedCountry) {
+        getSharedPreferences(context).edit().putBoolean(DEBUG_DEVICELOCK_CHECKIN_APPROVED_COUNTRY,
+                isInApprovedCountry).apply();
+    }
+
+    static void setDebugNextProvisionState(
+            Context context, @DeviceProvisionState int provisionState) {
+        getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_CHECKIN_NEXT_PROVISION_STATE,
+                provisionState).apply();
+    }
+
+    static void setDebugDaysLeftUntilReset(Context context,
+            int daysLeftUntilReset) {
+        getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_CHECKIN_DAYS_LEFT_UNTIL_RESET,
+                daysLeftUntilReset).apply();
+    }
+
+    static void dumpDebugCheckInClientResponses(Context context) {
+        LogUtil.d(TAG,
+                "Current Debug Client Responses:\n" + getSharedPreferences(context).getAll());
+    }
+
+    static void clear(Context context) {
+        getSharedPreferences(context).edit().clear().apply();
+    }
+
+    private static <T> T getSharedPreference(String key, T defValue) {
+        SharedPreferences preferences = getSharedPreferences(/* context= */ null);
+        if (preferences == null) return defValue;
+        T value = (T) preferences.getAll().get(key);
+        return value == null ? defValue : value;
+    }
 
     /**
      * Check In with DeviceLock backend server and get the next step for the device.
@@ -54,64 +124,68 @@
     @Override
     public GetDeviceCheckInStatusGrpcResponse getDeviceCheckInStatus(ArraySet<DeviceId> deviceIds,
             String carrierInfo, @Nullable String fcmRegistrationToken) {
+        ThreadAsserts.assertWorkerThread("getDeviceCheckInStatus");
         return new GetDeviceCheckInStatusGrpcResponse() {
             @Override
             @DeviceCheckInStatus
             public int getDeviceCheckInStatus() {
                 return DebugLogUtil.logAndReturn(TAG,
-                        SystemProperties.getInt("debug.devicelock.checkin.status",
-                                STATUS_UNSPECIFIED));
+                        getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_STATUS, READY_FOR_PROVISION));
             }
 
             @Nullable
             @Override
             public String getRegisteredDeviceIdentifier() {
-                return DebugLogUtil.logAndReturn(TAG, SystemProperties.get(
-                        "debug.devicelock.checkin.registered-id"));
+                return DebugLogUtil.logAndReturn(TAG,
+                        !deviceIds.isEmpty() ? deviceIds.valueAt(0).getId() : null);
             }
 
             @Nullable
             @Override
             public Instant getNextCheckInTime() {
                 Duration delay = Duration.ofMinutes(
-                        SystemProperties.getInt(
-                                "debug.devicelock.checkin.retry-delay", /* def= */ 1));
-                return DebugLogUtil.logAndReturn(TAG, Instant.now().plusSeconds(delay.toSeconds()));
+                        getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_RETRY_DELAY, /* def= */ 1));
+                return DebugLogUtil.logAndReturn(TAG,
+                        SystemClock.currentNetworkTimeClock().instant().plus(delay));
             }
 
             @Nullable
             @Override
             public ProvisioningConfiguration getProvisioningConfig() {
-                // Can be override using SetupParametersOverrider.
-                return null;
+                // This should be overridden using SetupParametersOverrider.
+                return new ProvisioningConfiguration(
+                        /* kioskAppProviderName= */ "",
+                        /* kioskAppPackageName= */ "",
+                        /* kioskAppAllowlistPackages= */ List.of(""),
+                        /* kioskAppEnableOutgoingCalls= */ false,
+                        /* kioskAppEnableEnableNotifications= */ false,
+                        /* disallowInstallingFromUnknownSources= */ false,
+                        /* termsAndConditionsUrl= */ "",
+                        /* supportUrl= */ "");
             }
 
             @Override
             public @ProvisioningType int getProvisioningType() {
-                return DebugLogUtil.logAndReturn(TAG,
-                        SystemProperties.getInt("debug.devicelock.checkin.provision-type",
-                                ProvisioningType.TYPE_UNDEFINED));
+                // This should be overridden using SetupParametersOverrider.
+                return ProvisioningType.TYPE_UNDEFINED;
             }
 
             @Override
             public boolean isProvisioningMandatory() {
-                return DebugLogUtil.logAndReturn(TAG, SystemProperties.getBoolean(
-                        "debug.devicelock.checkin.mandatory-provisioning",
-                        false));
+                // This should be overridden using SetupParametersOverrider.
+                return false;
             }
 
             @Override
             public boolean isProvisionForced() {
-                return DebugLogUtil.logAndReturn(TAG, SystemProperties.getBoolean(
-                        "debug.devicelock.checkin.force-provisioning",
-                        false));
+                return DebugLogUtil.logAndReturn(TAG,
+                        getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_FORCE_PROVISIONING, false));
             }
 
             @Override
             public boolean isDeviceInApprovedCountry() {
-                return DebugLogUtil.logAndReturn(TAG, SystemProperties.getBoolean(
-                        "debug.devicelock.checkin.approved-country",
-                        true));
+                return DebugLogUtil.logAndReturn(TAG,
+                        getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_APPROVED_COUNTRY, true));
             }
         };
     }
@@ -122,12 +196,12 @@
     @Override
     public IsDeviceInApprovedCountryGrpcResponse isDeviceInApprovedCountry(
             @Nullable String carrierInfo) {
+        ThreadAsserts.assertWorkerThread("isDeviceInApprovedCountry");
         return new IsDeviceInApprovedCountryGrpcResponse() {
             @Override
             public boolean isDeviceInApprovedCountry() {
-                return DebugLogUtil.logAndReturn(TAG, SystemProperties.getBoolean(
-                        "debug.devicelock.checkin.approved-country",
-                        true));
+                return DebugLogUtil.logAndReturn(TAG,
+                        getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_APPROVED_COUNTRY, true));
             }
         };
     }
@@ -137,43 +211,32 @@
      */
     @Override
     public PauseDeviceProvisioningGrpcResponse pauseDeviceProvisioning(int reason) {
-        return new PauseDeviceProvisioningGrpcResponse() {
-            @Override
-            public boolean shouldForceProvisioning() {
-                return DebugLogUtil.logAndReturn(TAG, SystemProperties.getBoolean(
-                        "debug.devicelock.checkin.force-provisioning",
-                        true));
-            }
-        };
+        ThreadAsserts.assertWorkerThread("pauseDeviceProvisioning");
+        return new PauseDeviceProvisioningGrpcResponse();
     }
 
     /**
      * Reports the current provision state of the device.
      */
     @Override
-    public ReportDeviceProvisionStateGrpcResponse reportDeviceProvisionState(int reasonOfFailure,
-            int lastReceivedProvisionState, boolean isSuccessful) {
+    public ReportDeviceProvisionStateGrpcResponse reportDeviceProvisionState(
+            int lastReceivedProvisionState, boolean isSuccessful,
+            @ProvisionFailureReason int reason) {
+        ThreadAsserts.assertWorkerThread("reportDeviceProvisionState");
         return new ReportDeviceProvisionStateGrpcResponse() {
             @Override
             @DeviceProvisionState
             public int getNextClientProvisionState() {
-                return DebugLogUtil.logAndReturn(TAG, SystemProperties.getInt(
-                        "debug.devicelock.checkin.next-provision-state",
+                return DebugLogUtil.logAndReturn(TAG, getSharedPreference(
+                        DEBUG_DEVICELOCK_CHECKIN_NEXT_PROVISION_STATE,
                         PROVISION_STATE_UNSPECIFIED));
             }
 
-            @Nullable
-            @Override
-            public String getEnrollmentToken() {
-                // Not useful in local testing setup.
-                return null;
-            }
-
             @Override
             public int getDaysLeftUntilReset() {
                 return DebugLogUtil.logAndReturn(TAG,
-                        SystemProperties.getInt(
-                                "debug.devicelock.checkin.days-left", /* def= */ 1));
+                        getSharedPreference(
+                                DEBUG_DEVICELOCK_CHECKIN_DAYS_LEFT_UNTIL_RESET, /* def= */ 1));
             }
         };
     }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/debug/DeviceLockCommandReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/debug/DeviceLockCommandReceiver.java
index aa0d031..f52f77e 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/debug/DeviceLockCommandReceiver.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/debug/DeviceLockCommandReceiver.java
@@ -16,13 +16,21 @@
 
 package com.android.devicelockcontroller.debug;
 
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_UNSPECIFIED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.NON_MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.READY_FOR_PROVISION;
 import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED;
 import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED;
 import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNPROVISIONED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED;
+import static com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerImpl.PROVISION_PAUSED_MINUTES_DEFAULT;
+import static com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerImpl.PROVISION_STATE_REPORT_INTERVAL_DEFAULT_MINUTES;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.app.AlarmManager;
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -31,10 +39,28 @@
 import android.text.TextUtils;
 
 import androidx.annotation.StringDef;
+import androidx.work.WorkManager;
 
+import com.android.devicelockcontroller.FcmRegistrationTokenProvider;
+import com.android.devicelockcontroller.WorkManagerExceptionHandler.WorkFailureAlarmReceiver;
+import com.android.devicelockcontroller.policy.DevicePolicyController;
 import com.android.devicelockcontroller.policy.DeviceStateController;
 import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionHelperImpl;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
+import com.android.devicelockcontroller.provision.grpc.DeviceFinalizeClient;
+import com.android.devicelockcontroller.provision.worker.DeviceCheckInWorker;
+import com.android.devicelockcontroller.provision.worker.PauseProvisioningWorker;
+import com.android.devicelockcontroller.provision.worker.ReportDeviceLockProgramCompleteWorker;
+import com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker;
+import com.android.devicelockcontroller.receivers.NextProvisionFailedStepReceiver;
+import com.android.devicelockcontroller.receivers.ResetDeviceReceiver;
+import com.android.devicelockcontroller.receivers.ResumeProvisionReceiver;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerImpl;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
 import com.android.devicelockcontroller.storage.GlobalParametersClient;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.storage.UserParameters;
@@ -46,6 +72,7 @@
 import com.google.common.util.concurrent.MoreExecutors;
 
 import java.lang.annotation.Retention;
+import java.util.Objects;
 
 /**
  * A {@link BroadcastReceiver} that can handle reset, lock, unlock command.
@@ -58,17 +85,55 @@
 
     private static final String TAG = "DeviceLockCommandReceiver";
     private static final String EXTRA_COMMAND = "command";
+    private static final String EXTRA_CHECK_IN_STATUS = "check-in-status";
+    private static final String EXTRA_CHECK_IN_RETRY_DELAY = "check-in-retry-delay";
+    private static final String EXTRA_FORCE_PROVISION = "force-provision";
+    private static final String EXTRA_IS_IN_APPROVED_COUNTRY = "is-in-approved-country";
+    private static final String EXTRA_NEXT_PROVISION_STATE = "next-provision-state";
+    private static final String EXTRA_DAYS_LEFT_UNTIL_RESET = "days-left-until-reset";
+    private static final String EXTRA_PAUSED_MINUTES = "paused-minutes";
+    private static final String EXTRA_REPORT_INTERVAL_MINUTES = "report-interval-minutes";
+    private static final String EXTRA_RESET_DEVICE_MINUTES = "reset-device-minutes";
+    private static final String EXTRA_MANDATORY_RESET_DEVICE_MINUTES =
+            "mandatory-reset-device-minutes";
+    private static final String EXTRA_HOST_NAME = "host-name";
+    public static final String EXTRA_RESET_INCLUDE_SETUP_PARAMETERS_AND_DEBUG_SETUPS =
+            "include-setup-params-and-debug-setups";
 
     @Retention(SOURCE)
     @StringDef({
             Commands.RESET,
             Commands.LOCK,
             Commands.UNLOCK,
+            Commands.CHECK_IN,
+            Commands.CLEAR,
+            Commands.DUMP,
+            Commands.FCM,
+            Commands.ENABLE_DEBUG_CLIENT,
+            Commands.DISABLE_DEBUG_CLIENT,
+            Commands.SET_DEBUG_CLIENT_RESPONSE,
+            Commands.DUMP_DEBUG_CLIENT_RESPONSE,
+            Commands.SET_DEBUG_CLIENT_RESPONSE,
+            Commands.DUMP_DEBUG_SCHEDULER,
     })
     private @interface Commands {
         String RESET = "reset";
         String LOCK = "lock";
         String UNLOCK = "unlock";
+        String CHECK_IN = "check-in";
+        String CLEAR = "clear";
+        String DUMP = "dump";
+        String FCM = "fcm";
+        String ENABLE_DEBUG_CLIENT = "enable-debug-client";
+        String DISABLE_DEBUG_CLIENT = "disable-debug-client";
+        String SET_CHECK_IN_HOST_NAME = "set-check-in-host-name";
+        String SET_FINALIZE_HOST_NAME = "set-finalize-host-name";
+        String SET_DEBUG_CLIENT_RESPONSE = "set-debug-client-response";
+        String DUMP_DEBUG_CLIENT_RESPONSE = "dump-debug-client-response";
+        String SET_UP_DEBUG_SCHEDULER = "set-up-debug-scheduler";
+        String DUMP_DEBUG_SCHEDULER = "dump-debug-scheduler";
+        String ENABLE_PREINSTALLED_KIOSK = "enable-preinstalled-kiosk";
+        String DISABLE_PREINSTALLED_KIOSK = "disable-preinstalled-kiosk";
     }
 
     @Override
@@ -88,45 +153,269 @@
             return;
         }
 
+        Context appContext = context.getApplicationContext();
+
+        ProvisionStateController provisionStateController =
+                ((PolicyObjectsProvider) appContext).getProvisionStateController();
+        DeviceStateController deviceStateController =
+                provisionStateController.getDeviceStateController();
+
         @Commands
         String command = String.valueOf(intent.getStringExtra(EXTRA_COMMAND));
         switch (command) {
             case Commands.RESET:
-                forceReset(context);
+                forceReset(appContext, intent.getBooleanExtra(
+                        EXTRA_RESET_INCLUDE_SETUP_PARAMETERS_AND_DEBUG_SETUPS, false));
                 break;
             case Commands.LOCK:
-                Futures.addCallback(forceSetState(context, LOCKED),
+                Futures.addCallback(deviceStateController.lockDevice(),
                         getSetStateCallBack(LOCKED), MoreExecutors.directExecutor());
                 break;
             case Commands.UNLOCK:
-                Futures.addCallback(forceSetState(context, UNLOCKED),
+                Futures.addCallback(deviceStateController.unlockDevice(),
                         getSetStateCallBack(UNLOCKED), MoreExecutors.directExecutor());
                 break;
+            case Commands.CLEAR:
+                Futures.addCallback(deviceStateController.clearDevice(),
+                        getSetStateCallBack(CLEARED), MoreExecutors.directExecutor());
+                break;
+            case Commands.CHECK_IN:
+                tryCheckIn(appContext);
+                break;
+            case Commands.DUMP:
+                dumpStorage(context);
+                break;
+            case Commands.FCM:
+                logFcmToken(appContext);
+                break;
+            case Commands.ENABLE_DEBUG_CLIENT:
+                DeviceCheckInClientDebug.setDebugClientEnabled(context, true);
+                break;
+            case Commands.DISABLE_DEBUG_CLIENT:
+                DeviceCheckInClientDebug.setDebugClientEnabled(context, false);
+                break;
+            case Commands.SET_CHECK_IN_HOST_NAME:
+                setCheckInHostName(context, intent);
+                break;
+            case Commands.SET_FINALIZE_HOST_NAME:
+                setFinalizeHostName(context, intent);
+                break;
+            case Commands.SET_DEBUG_CLIENT_RESPONSE:
+                setDebugCheckInClientResponse(context, intent);
+                break;
+            case Commands.DUMP_DEBUG_CLIENT_RESPONSE:
+                DeviceCheckInClientDebug.dumpDebugCheckInClientResponses(context);
+                break;
+            case Commands.SET_UP_DEBUG_SCHEDULER:
+                setUpDebugScheduler(context, intent);
+                break;
+            case Commands.DUMP_DEBUG_SCHEDULER:
+                DeviceLockControllerSchedulerImpl.dumpDebugScheduler(context);
+                break;
+            case Commands.ENABLE_PREINSTALLED_KIOSK:
+                ProvisionHelperImpl.setPreinstalledKioskAllowed(context, true);
+                break;
+            case Commands.DISABLE_PREINSTALLED_KIOSK:
+                ProvisionHelperImpl.setPreinstalledKioskAllowed(context, false);
+                break;
             default:
                 throw new IllegalArgumentException("Unsupported command: " + command);
         }
     }
 
-    private static ListenableFuture<Void> forceSetState(Context context, @DeviceState int state) {
-        PolicyObjectsInterface policyObjectsInterface =
-                (PolicyObjectsInterface) context.getApplicationContext();
-        policyObjectsInterface.destroyObjects();
-        UserParameters.setDeviceStateSync(context, state);
-        return policyObjectsInterface.getStateController().enforcePoliciesForCurrentState();
+    private static void setCheckInHostName(Context context, Intent intent) {
+        if (!intent.hasExtra(EXTRA_HOST_NAME)) {
+            throw new IllegalArgumentException("Missing host name override!");
+        }
+        DeviceCheckInClient.setHostNameOverride(context, intent.getStringExtra(EXTRA_HOST_NAME));
     }
 
-    private static void forceReset(Context context) {
-        ListenableFuture<Void> resetFuture = Futures.transformAsync(
-                // First clear restrictions
-                forceSetState(context, CLEARED),
-                // Then clear storage, this will reset state to the default state which is
-                // UNPROVISIONED.
-                (Void unused) -> clearStorage(context),
-                MoreExecutors.directExecutor());
+    private static void setFinalizeHostName(Context context, Intent intent) {
+        if (!intent.hasExtra(EXTRA_HOST_NAME)) {
+            throw new IllegalArgumentException("Missing host name override!");
+        }
+        DeviceFinalizeClient.setHostNameOverride(context, intent.getStringExtra(EXTRA_HOST_NAME));
+    }
+
+    private static void setDebugCheckInClientResponse(Context context, Intent intent) {
+        if (intent.hasExtra(EXTRA_CHECK_IN_STATUS)) {
+            DeviceCheckInClientDebug.setDebugCheckInStatus(context,
+                    intent.getIntExtra(EXTRA_CHECK_IN_STATUS, READY_FOR_PROVISION));
+
+        }
+        if (intent.hasExtra(EXTRA_FORCE_PROVISION)) {
+            DeviceCheckInClientDebug.setDebugForceProvisioning(context,
+                    intent.getBooleanExtra(EXTRA_FORCE_PROVISION, false));
+        }
+        if (intent.hasExtra(EXTRA_IS_IN_APPROVED_COUNTRY)) {
+            DeviceCheckInClientDebug.setDebugApprovedCountry(context,
+                    intent.getBooleanExtra(EXTRA_IS_IN_APPROVED_COUNTRY, true));
+        }
+        if (intent.hasExtra(EXTRA_NEXT_PROVISION_STATE)) {
+            DeviceCheckInClientDebug.setDebugNextProvisionState(context,
+                    intent.getIntExtra(EXTRA_NEXT_PROVISION_STATE,
+                            PROVISION_STATE_UNSPECIFIED));
+        }
+        if (intent.hasExtra(EXTRA_DAYS_LEFT_UNTIL_RESET)) {
+            DeviceCheckInClientDebug.setDebugDaysLeftUntilReset(
+                    context, intent.getIntExtra(EXTRA_DAYS_LEFT_UNTIL_RESET, /* days_left*/ 1));
+        }
+        if (intent.hasExtra(EXTRA_CHECK_IN_RETRY_DELAY)) {
+            DeviceCheckInClientDebug.setDebugCheckInRetryDelay(context,
+                    intent.getIntExtra(EXTRA_CHECK_IN_RETRY_DELAY, /* delay_minute= */ 1));
+        }
+    }
+
+    private static void setUpDebugScheduler(Context context, Intent intent) {
+        if (intent.hasExtra(EXTRA_PAUSED_MINUTES)) {
+            DeviceLockControllerSchedulerImpl.setDebugProvisionPausedMinutes(context,
+                    intent.getIntExtra(EXTRA_PAUSED_MINUTES, PROVISION_PAUSED_MINUTES_DEFAULT));
+        }
+        if (intent.hasExtra(EXTRA_REPORT_INTERVAL_MINUTES)) {
+            DeviceLockControllerSchedulerImpl.setDebugReportIntervalMinutes(context,
+                    intent.getLongExtra(EXTRA_REPORT_INTERVAL_MINUTES,
+                            PROVISION_STATE_REPORT_INTERVAL_DEFAULT_MINUTES));
+        }
+        if (intent.hasExtra(EXTRA_RESET_DEVICE_MINUTES)) {
+            DeviceLockControllerSchedulerImpl.setDebugResetDeviceMinutes(context,
+                    intent.getIntExtra(EXTRA_RESET_DEVICE_MINUTES,
+                            NON_MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE));
+        }
+        if (intent.hasExtra(EXTRA_MANDATORY_RESET_DEVICE_MINUTES)) {
+            DeviceLockControllerSchedulerImpl.setDebugMandatoryResetDeviceMinutes(context,
+                    intent.getIntExtra(EXTRA_MANDATORY_RESET_DEVICE_MINUTES,
+                            MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE));
+        }
+    }
+
+    private static void dumpStorage(Context context) {
         Futures.addCallback(
-                resetFuture,
-                getSetStateCallBack(UNPROVISIONED),
+                Futures.transformAsync(SetupParametersClient.getInstance().dump(),
+                        unused -> GlobalParametersClient.getInstance().dump(),
+                        MoreExecutors.directExecutor()),
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Void result) {
+                        UserParameters.dump(context);
+                        LogUtil.i(TAG, "Successfully dumped storage");
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        LogUtil.e(TAG, "Error encountered when dumping storage", t);
+                    }
+                }, MoreExecutors.directExecutor());
+    }
+
+    private static void tryCheckIn(Context appContext) {
+        if (!appContext.getSystemService(UserManager.class).isSystemUser()) {
+            LogUtil.e(TAG, "Only system user can perform a check-in");
+            return;
+        }
+        DeviceLockControllerSchedulerProvider schedulerProvider =
+                (DeviceLockControllerSchedulerProvider) appContext;
+        DeviceLockControllerScheduler scheduler =
+                schedulerProvider.getDeviceLockControllerScheduler();
+
+        Futures.addCallback(GlobalParametersClient.getInstance().isProvisionReady(),
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Boolean provisioningInfoReady) {
+                        if (!provisioningInfoReady) {
+                            scheduler.scheduleInitialCheckInWork();
+                        } else {
+                            LogUtil.e(TAG,
+                                    "Can not check in when provisioning info has already been "
+                                            + "received. Use the \"reset\" command to reset "
+                                            + "DLC first.");
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        LogUtil.e(TAG, "Failed to determine if provisioning info is ready", t);
+                    }
+                }, MoreExecutors.directExecutor());
+    }
+
+    private static void forceReset(Context context,
+            boolean shouldCleanSetupParametersAndDebugSetups) {
+        // Cancel provision works
+        LogUtil.d(TAG, "cancelling works");
+        WorkManager workManager = WorkManager.getInstance(context);
+        workManager.cancelAllWorkByTag(DeviceCheckInWorker.class.getName());
+        workManager.cancelAllWorkByTag(PauseProvisioningWorker.class.getName());
+        workManager.cancelAllWorkByTag(
+                ReportDeviceProvisionStateWorker.class.getName());
+        workManager.cancelAllWorkByTag(
+                ReportDeviceLockProgramCompleteWorker.class.getName());
+
+        // Cancel All alarms
+        AlarmManager alarmManager = Objects.requireNonNull(
+                context.getSystemService(AlarmManager.class));
+        alarmManager.cancel(
+                PendingIntent.getBroadcast(
+                        context, /* ignored */ 0,
+                        new Intent(context, ResetDeviceReceiver.class),
+                        PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE));
+        alarmManager.cancel(PendingIntent.getBroadcast(
+                context, /* ignored */ 0,
+                new Intent(context, NextProvisionFailedStepReceiver.class),
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE));
+        alarmManager.cancel(PendingIntent.getBroadcast(
+                context, /* ignored */ 0,
+                new Intent(context, ResumeProvisionReceiver.class),
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE));
+        alarmManager.cancel(PendingIntent.getBroadcast(
+                context, /* ignored */ 0,
+                new Intent(context, NextProvisionFailedStepReceiver.class),
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE));
+        alarmManager.cancel(PendingIntent.getBroadcast(
+                context, /* ignored */ 0,
+                new Intent(context, WorkFailureAlarmReceiver.class),
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE));
+
+        PolicyObjectsProvider policyObjectsProvider =
+                (PolicyObjectsProvider) context.getApplicationContext();
+        policyObjectsProvider.destroyObjects();
+        UserParameters.setProvisionState(context, PROVISION_SUCCEEDED);
+        GlobalParametersClient.getInstance().setDeviceState(CLEARED);
+        DevicePolicyController policyController = policyObjectsProvider.getPolicyController();
+        ListenableFuture<Void> clearPolicies = Futures.catching(
+                policyController.enforceCurrentPolicies(),
+                RuntimeException.class, unused -> null,
                 MoreExecutors.directExecutor());
+        Futures.addCallback(Futures.transformAsync(clearPolicies,
+                        unused -> clearStorage(context, shouldCleanSetupParametersAndDebugSetups),
+                        MoreExecutors.directExecutor()),
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Void result) {
+                        LogUtil.i(TAG, "Reset device state.");
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        throw new RuntimeException(t);
+                    }
+                }, MoreExecutors.directExecutor());
+    }
+
+    private static void logFcmToken(Context appContext) {
+        final ListenableFuture<String> fcmRegistrationToken =
+                ((FcmRegistrationTokenProvider) appContext).getFcmRegistrationToken();
+        Futures.addCallback(fcmRegistrationToken, new FutureCallback<>() {
+            @Override
+            public void onSuccess(String token) {
+                LogUtil.i(TAG,
+                        "FCM Registration Token: " + (token == null ? "Not set" : token));
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LogUtil.e(TAG, "Unable to get FCM registration token", t);
+            }
+        }, MoreExecutors.directExecutor());
     }
 
     private static FutureCallback<Void> getSetStateCallBack(@DeviceState int state) {
@@ -134,28 +423,32 @@
         return new FutureCallback<>() {
 
             @Override
-            public void onSuccess(Void v) {
-                LogUtil.i(TAG,
-                        "Successfully set state to: " + DeviceStateController.stateToString(state));
+            public void onSuccess(Void unused) {
+                LogUtil.i(TAG, "Successfully set state to: " + state);
             }
 
             @Override
             public void onFailure(Throwable t) {
-                LogUtil.e(TAG,
-                        "Unsuccessfully set state to: "
-                                + DeviceStateController.stateToString(state), t);
+                LogUtil.e(TAG, "Unsuccessfully set state to: " + state, t);
             }
         };
     }
 
-    private static ListenableFuture<Void> clearStorage(Context context) {
+    private static ListenableFuture<Void> clearStorage(Context context,
+            boolean shouldCleanSetupParametersAndDebugSetups) {
+        if (shouldCleanSetupParametersAndDebugSetups) {
+            DeviceCheckInClientDebug.clear(context);
+            DeviceLockControllerSchedulerImpl.clear(context);
+        }
         UserParameters.clear(context);
         return Futures.whenAllSucceed(
-                        SetupParametersClient.getInstance().clear(),
+                        shouldCleanSetupParametersAndDebugSetups
+                                ? SetupParametersClient.getInstance().clear()
+                                : Futures.immediateVoidFuture(),
                         GlobalParametersClient.getInstance().clear())
                 .call(() -> {
-                    ((PolicyObjectsInterface) context.getApplicationContext()).destroyObjects();
+                    ((PolicyObjectsProvider) context.getApplicationContext()).destroyObjects();
                     return null;
-                }, MoreExecutors.directExecutor());
+                }, context.getMainExecutor());
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/debug/SetupFlowStarter.java b/DeviceLockController/src/com/android/devicelockcontroller/debug/SetupFlowStarter.java
deleted file mode 100644
index 7dc5755..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/debug/SetupFlowStarter.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.debug;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-import android.os.UserManager;
-import android.text.TextUtils;
-
-import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
-import com.android.devicelockcontroller.provision.worker.DeviceCheckInHelper;
-import com.android.devicelockcontroller.util.LogUtil;
-
-/**
- * Broadcast receiver which can start the setup flow.
- */
-public final class SetupFlowStarter extends BroadcastReceiver {
-
-    private static final String TAG = "SetupFlowStarter";
-    private static final String EXTRA_IS_MANDATORY = "is-mandatory";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (!Build.isDebuggable()) {
-            LogUtil.w(TAG, "Adb command is not supported in non-debuggable build!");
-            return;
-        }
-
-        if (!TextUtils.equals(intent.getComponent().getClassName(),
-                SetupFlowStarter.class.getName())) {
-            LogUtil.w(TAG, "Implicit intent should not be used!");
-            return;
-        }
-
-        final boolean isUserProfile =
-                context.getSystemService(UserManager.class).isProfile();
-        if (isUserProfile) {
-            LogUtil.w(TAG, "Broadcast should not target user profiles");
-            return;
-        }
-
-        PolicyObjectsInterface policyObjects =
-                (PolicyObjectsInterface) context.getApplicationContext();
-        DevicePolicyController devicePolicyController = policyObjects.getPolicyController();
-        DeviceStateController deviceStateController = policyObjects.getStateController();
-
-        DeviceCheckInHelper.setProvisionSucceeded(deviceStateController, devicePolicyController,
-                context, intent.getBooleanExtra(EXTRA_IS_MANDATORY, /* defaultValue= */ true));
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/AbstractTask.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/AbstractTask.java
deleted file mode 100644
index e496f34..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/AbstractTask.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
-
-import android.content.Context;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.work.Data;
-import androidx.work.ListenableWorker;
-import androidx.work.WorkerParameters;
-
-import com.android.devicelockcontroller.util.LogUtil;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Locale;
-
-/** Base class for download, verify and install packages. */
-public abstract class AbstractTask extends ListenableWorker {
-    private static final String TAG = "AbstractTask";
-
-    static final String TASK_RESULT_ERROR_CODE_KEY = "error-code";
-
-    // Error code for install package
-    static final int ERROR_CODE_CREATE_SESSION_FAILED = 20;
-    static final int ERROR_CODE_OPEN_SESSION_FAILED = 21;
-    static final int ERROR_CODE_COPY_STREAM_FAILED = 22;
-    static final int ERROR_CODE_INSTALLATION_FAILED = 23;
-    static final int ERROR_CODE_GET_PENDING_INTENT_FAILED = 24;
-    // Error code for install existing package
-    static final int ERROR_CODE_NO_PACKAGE_NAME = 40;
-    // Error code for add financed device kiosk role
-    static final int ERROR_CODE_ADD_FINANCED_DEVICE_KIOSK_FAILED = 50;
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            ERROR_CODE_CREATE_SESSION_FAILED,
-            ERROR_CODE_OPEN_SESSION_FAILED,
-            ERROR_CODE_COPY_STREAM_FAILED,
-            ERROR_CODE_INSTALLATION_FAILED,
-            ERROR_CODE_GET_PENDING_INTENT_FAILED,
-            ERROR_CODE_NO_PACKAGE_NAME,
-            ERROR_CODE_ADD_FINANCED_DEVICE_KIOSK_FAILED
-    })
-    @interface ErrorCode {}
-
-    public AbstractTask(@NonNull Context appContext, @NonNull WorkerParameters workerParams) {
-        super(appContext, workerParams);
-    }
-
-    /**
-     * Creates a {@link androidx.work.ListenableWorker.Result.Failure} result and puts the error
-     * code in its output {@link Data} with the key {@link #TASK_RESULT_ERROR_CODE_KEY}.
-     *
-     * @param errorCode the error code that will be included in the result, it should be one of the
-     *     values defined in {@link ErrorCode}.
-     * @return a Failure result which contains error code.
-     */
-    static Result failure(@ErrorCode int errorCode) {
-        LogUtil.e(TAG, String.format(Locale.US, "Task failed with error code %d", errorCode));
-        Data data = new Data.Builder().putInt(TASK_RESULT_ERROR_CODE_KEY, errorCode).build();
-        return Result.failure(data);
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/AppOpsPolicyHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/AppOpsPolicyHandler.java
index 334721e..44d54a2 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/AppOpsPolicyHandler.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/AppOpsPolicyHandler.java
@@ -16,128 +16,163 @@
 
 package com.android.devicelockcontroller.policy;
 
-import android.app.AppOpsManager;
-import android.content.Context;
 import android.os.OutcomeReceiver;
 
 import androidx.concurrent.futures.CallbackToFutureAdapter;
 
 import com.android.devicelockcontroller.SystemDeviceLockManager;
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
-import com.android.devicelockcontroller.storage.SetupParametersClientInterface;
 import com.android.devicelockcontroller.util.LogUtil;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
+import java.util.concurrent.Executor;
+
 final class AppOpsPolicyHandler implements PolicyHandler {
     private static final String TAG = "AppOpsPolicyHandler";
-    // The following should be a SystemApi on AppOpsManager.
-    private static final String OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION =
-            "android:system_exempt_from_activity_bg_start_restriction";
-    private final Context mContext;
     private final SystemDeviceLockManager mSystemDeviceLockManager;
-    private final AppOpsManager mAppOpsManager;
-    private final SetupParametersClientInterface mSetupParametersClient;
+    private final Executor mBgExecutor;
 
-    AppOpsPolicyHandler(Context context, SystemDeviceLockManager systemDeviceLockManager,
-            AppOpsManager appOpsManager) {
-        this(context, systemDeviceLockManager, appOpsManager, SetupParametersClient.getInstance());
-    }
-
-    AppOpsPolicyHandler(Context context, SystemDeviceLockManager systemDeviceLockManager,
-            AppOpsManager appOpsManager, SetupParametersClientInterface setupParametersClient) {
-        mContext = context;
+    AppOpsPolicyHandler(SystemDeviceLockManager systemDeviceLockManager, Executor bgExecutor) {
         mSystemDeviceLockManager = systemDeviceLockManager;
-        mAppOpsManager = appOpsManager;
-        mSetupParametersClient = setupParametersClient;
+        mBgExecutor = bgExecutor;
     }
 
-    private ListenableFuture<@ResultType Integer>
-            getExemptFromBackgroundStartRestrictionsFuture(boolean exempt) {
-        return CallbackToFutureAdapter.getFuture(
-                completer -> {
-                    mSystemDeviceLockManager.setExemptFromActivityBackgroundStartRestriction(exempt,
-                            mContext.getMainExecutor(),
-                            new OutcomeReceiver<Void, Exception>() {
-                                @Override
-                                public void onResult(Void unused) {
-                                    completer.set(SUCCESS);
-                                }
+    /**
+     * Set the exempt from activity background start restriction state for dlc app.
+     */
+    private ListenableFuture<Boolean> setDlcExemptFromActivityBgStartRestrictionState(
+            boolean exempt) {
+        return CallbackToFutureAdapter.getFuture(completer -> {
+            mSystemDeviceLockManager.setDlcExemptFromActivityBgStartRestrictionState(exempt,
+                    mBgExecutor, new OutcomeReceiver<>() {
+                        @Override
+                        public void onResult(Void unused) {
+                            completer.set(true);
+                        }
 
-                                @Override
-                                public void onError(Exception error) {
-                                    LogUtil.e(TAG, "Cannot set background start exemption", error);
-                                    completer.set(FAILURE);
-                                }
-                            });
-                    // Used only for debugging.
-                    return "getExemptFromBackgroundStartRestrictionFuture";
-                });
+                        @Override
+                        public void onError(Exception error) {
+                            LogUtil.e(TAG, "Cannot set background start exemption", error);
+                            completer.set(false);
+                        }
+                    });
+            // Used only for debugging.
+            return "setDlcExemptFromActivityBgStartRestrictionState";
+        });
     }
 
-    private ListenableFuture<@ResultType Integer> getExemptFromHibernationFuture(boolean exempt) {
-        return Futures.transformAsync(mSetupParametersClient.getKioskPackage(),
-                kioskPackageName -> kioskPackageName == null
-                        ? Futures.immediateFuture(SUCCESS)
-                        : CallbackToFutureAdapter.getFuture(
-                            completer -> {
-                                mSystemDeviceLockManager.setExemptFromHibernation(
-                                        kioskPackageName, exempt,
-                                        mContext.getMainExecutor(),
-                                        new OutcomeReceiver<Void, Exception>() {
-                                            @Override
-                                            public void onResult(Void unused) {
-                                                completer.set(SUCCESS);
-                                            }
+    /**
+     * Set whether the dlc can send undismissible notifications.
+     */
+    private ListenableFuture<Boolean> setDlcAllowedToSendUndismissibleNotifications(
+            boolean allowed) {
+        return CallbackToFutureAdapter.getFuture(completer -> {
+            mSystemDeviceLockManager.setDlcAllowedToSendUndismissibleNotifications(allowed,
+                    mBgExecutor, new OutcomeReceiver<>() {
+                        @Override
+                        public void onResult(Void unused) {
+                            completer.set(true);
+                        }
 
-                                            @Override
-                                            public void onError(Exception error) {
-                                                LogUtil.e(TAG, "Cannot set exempt from hibernation",
-                                                        error);
-                                                completer.set(FAILURE);
-                                            }
-                                        });
-                                // Used only for debugging.
-                                return "setExemptFromHibernationFuture";
-                            }), MoreExecutors.directExecutor());
+                        @Override
+                        public void onError(Exception error) {
+                            LogUtil.e(TAG, "Cannot set undismissible notifs", error);
+                            // Returns true here to make sure state transition
+                            // success.
+                            completer.set(true);
+                        }
+                    });
+            // Used only for debugging.
+            return "setDlcAllowedToSendUndismissibleNotifications";
+        });
     }
 
-    private ListenableFuture<@ResultType Integer>
-            getExemptFromBackgroundStartAndHibernationFuture(boolean exempt) {
-        final ListenableFuture<@ResultType Integer> backgroundFuture =
-                getExemptFromBackgroundStartRestrictionsFuture(exempt /* exempt */);
-        final ListenableFuture<@ResultType Integer> hibernationFuture =
-                getExemptFromHibernationFuture(exempt /* exempt */);
-        return Futures.whenAllSucceed(backgroundFuture, hibernationFuture)
-                .call(() -> (Futures.getDone(backgroundFuture) == SUCCESS
-                                && Futures.getDone(hibernationFuture) == SUCCESS)
-                                ? SUCCESS : FAILURE,
-                        MoreExecutors.directExecutor());
+    /**
+     * Set the exempt from hibernation, battery and data usage restriction state for kiosk app.
+     */
+    private ListenableFuture<Boolean> setKioskAppExemptionsState(boolean exempt) {
+        return Futures.transformAsync(SetupParametersClient.getInstance().getKioskPackage(),
+                kioskPackageName -> kioskPackageName == null ? Futures.immediateFuture(true)
+                        : CallbackToFutureAdapter.getFuture(completer -> {
+                            mSystemDeviceLockManager.setKioskAppExemptFromRestrictionsState(
+                                    kioskPackageName, exempt, mBgExecutor, new OutcomeReceiver<>() {
+                                        @Override
+                                        public void onResult(Void unused) {
+                                            completer.set(true);
+                                        }
+
+                                        @Override
+                                        public void onError(Exception error) {
+                                            LogUtil.e(TAG, "Cannot set exempt kiosk app", error);
+                                            // Returns true here to make sure state transition
+                                            // success.
+                                            completer.set(true);
+                                        }
+                                    });
+                            // Used only for debugging.
+                            return "setKioskAppExemptionsState";
+                        }), MoreExecutors.directExecutor());
+    }
+
+    /**
+     * Set the exempt state for dlc and kiosk app. Note that the exemptions are different between
+     * dlc app and kiosk app.
+     */
+    private ListenableFuture<Boolean> setDlcAndKioskAppExemptionsState(boolean exempt) {
+        final ListenableFuture<Boolean> backgroundFuture =
+                setDlcExemptFromActivityBgStartRestrictionState(exempt);
+        final ListenableFuture<Boolean> kioskExemptionFuture = setKioskAppExemptionsState(exempt);
+        return Futures.whenAllSucceed(backgroundFuture, kioskExemptionFuture).call(
+                () -> Futures.getDone(backgroundFuture) && Futures.getDone(kioskExemptionFuture),
+                MoreExecutors.directExecutor());
     }
 
     @Override
-    public ListenableFuture<@ResultType Integer> setPolicyForState(@DeviceState int state) {
-        switch (state) {
-            case DeviceState.PSEUDO_LOCKED:
-            case DeviceState.PSEUDO_UNLOCKED:
-                return Futures.immediateFuture(SUCCESS);
-            case DeviceState.SETUP_IN_PROGRESS:
-            case DeviceState.SETUP_SUCCEEDED:
-            case DeviceState.SETUP_FAILED:
-            case DeviceState.KIOSK_SETUP:
-                return getExemptFromBackgroundStartRestrictionsFuture(true /* exempt */);
-            case DeviceState.UNLOCKED:
-            case DeviceState.LOCKED:
-                return getExemptFromBackgroundStartAndHibernationFuture(true /* exempt */);
-            case DeviceState.UNPROVISIONED:
-            case DeviceState.CLEARED:
-                return getExemptFromBackgroundStartAndHibernationFuture(false /* exempt */);
-            default:
-                return Futures.immediateFailedFuture(
-                        new IllegalStateException(String.valueOf(state)));
-        }
+    public ListenableFuture<Boolean> onProvisioned() {
+        return setDlcAndKioskAppExemptionsState(/* exempt= */ true);
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisionInProgress() {
+        final ListenableFuture<Boolean> notifFuture =
+                setDlcAllowedToSendUndismissibleNotifications(/* allowed= */ true);
+        final ListenableFuture<Boolean> backgroundFuture =
+                setDlcExemptFromActivityBgStartRestrictionState(/* exempt= */ true);
+        return Futures.whenAllSucceed(notifFuture, backgroundFuture).call(
+                () -> Futures.getDone(notifFuture) && Futures.getDone(backgroundFuture),
+                MoreExecutors.directExecutor());
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisionFailed() {
+        return setDlcExemptFromActivityBgStartRestrictionState(/* exempt= */ false);
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onCleared() {
+        final ListenableFuture<Boolean> notifFuture =
+                setDlcAllowedToSendUndismissibleNotifications(/* allowed= */ false);
+        final ListenableFuture<Boolean> clearExemptions =
+                setDlcAndKioskAppExemptionsState(/* exempt= */ false);
+        return Futures.whenAllSucceed(notifFuture, clearExemptions).call(
+                () -> Futures.getDone(notifFuture) && Futures.getDone(clearExemptions),
+                MoreExecutors.directExecutor());
+    }
+
+    // Due to some reason, AppOpsManager does not persist exemption after reboot, therefore we
+    // need to always set them from our end.
+    @Override
+    public ListenableFuture<Boolean> onLocked() {
+        return setDlcAndKioskAppExemptionsState(/* exempt= */ true);
+    }
+
+    // Due to some reason, AppOpsManager does not persist exemption after reboot, therefore we
+    // need to always set them from our end.
+    @Override
+    public ListenableFuture<Boolean> onUnlocked() {
+        return setKioskAppExemptionsState(/* exempt= */ true);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/ControllerKeepAlivePolicyHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/ControllerKeepAlivePolicyHandler.java
new file mode 100644
index 0000000..67761a0
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/ControllerKeepAlivePolicyHandler.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import android.os.OutcomeReceiver;
+
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.concurrent.Executor;
+
+/** Handles device lock controller keep-alive. */
+public final class ControllerKeepAlivePolicyHandler implements PolicyHandler {
+    private static final String TAG = "ControllerKeepAlivePolicyHandler";
+
+    private final SystemDeviceLockManager mSystemDeviceLockManager;
+    private final Executor mBgExecutor;
+
+    ControllerKeepAlivePolicyHandler(SystemDeviceLockManager systemDeviceLockManager,
+            Executor bgExecutor) {
+        mSystemDeviceLockManager = systemDeviceLockManager;
+        mBgExecutor = bgExecutor;
+    }
+
+    private ListenableFuture<Boolean> getEnableControllerKeepAliveFuture() {
+        return CallbackToFutureAdapter.getFuture(
+                completer -> {
+                    mSystemDeviceLockManager.enableControllerKeepalive(
+                            mBgExecutor,
+                            new OutcomeReceiver<>() {
+                                @Override
+                                public void onResult(Void result) {
+                                    completer.set(true);
+                                }
+
+                                @Override
+                                public void onError(Exception ex) {
+                                    LogUtil.e(TAG, "Failed to enable controller keep-alive",
+                                            ex);
+                                    // Return SUCCESS since we don't want to fail the transition
+                                    completer.set(true);
+                                }
+                            });
+                    // Used only for debugging.
+                    return "getEnableControllerKeepAliveFuture";
+                });
+    }
+
+    private ListenableFuture<Boolean> getDisableControllerKeepAliveFuture() {
+        return CallbackToFutureAdapter.getFuture(
+                completer -> {
+                    mSystemDeviceLockManager.disableControllerKeepalive(mBgExecutor,
+                            new OutcomeReceiver<>() {
+                                @Override
+                                public void onResult(Void result) {
+                                    completer.set(true);
+                                }
+
+                                @Override
+                                public void onError(Exception ex) {
+                                    LogUtil.e(TAG, "Failed to disable controller keep-alive",
+                                            ex);
+                                    // Return SUCCESS since we don't want to fail the transition
+                                    completer.set(true);
+                                }
+                            });
+                    // Used only for debugging.
+                    return "getDisableControllerKeepAliveFuture";
+                });
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisionInProgress() {
+        return getEnableControllerKeepAliveFuture();
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisionPaused() {
+        return getDisableControllerKeepAliveFuture();
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisioned() {
+        return getDisableControllerKeepAliveFuture();
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/DevicePolicyController.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/DevicePolicyController.java
index b431ea6..c920182 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/DevicePolicyController.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/DevicePolicyController.java
@@ -16,50 +16,92 @@
 
 package com.android.devicelockcontroller.policy;
 
+import android.content.Intent;
+
+import androidx.annotation.IntDef;
+
 import com.google.common.util.concurrent.ListenableFuture;
 
-import java.time.Duration;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Interface for the policy controller that is responsible for applying policies based
  * on state.
  */
 public interface DevicePolicyController {
-    /**
-     * Launches an activity in locked mode. The specific activity is resolved based on the current
-     * device state. Returns false if package containing the activity is not in the allowlist.
-     */
-    ListenableFuture<Boolean> launchActivityInLockedMode();
-
-    /**
-     * Similar to
-     * {@link DevicePolicyController#enqueueStartLockTaskModeWorkerWithDelay(boolean, Duration)}
-     * but with zero delay.
-     *
-     * @param isMandatory whether starting lock task mode is mandatory at the time of request.
-     */
-    void enqueueStartLockTaskModeWorker(boolean isMandatory);
-
-    /**
-     * Enqueue a worker to start lock task mode and launch corresponding activity with a delay of
-     * certain {@link Duration}.
-     * The work will be retried until device is in lock task mode.
-     *
-     * @param isMandatory whether starting lock task mode is mandatory at the time of request.
-     * @param delay       The {@link Duration} that should be delayed before device enters lock
-     *                    task mode.
-     */
-    void enqueueStartLockTaskModeWorkerWithDelay(boolean isMandatory, Duration delay);
-
 
     /**
      * Factory resets the device when the setup has failed and cannot continue.
      * Returns true if action was successful.
+     * <p>
+     * Using the new {@code DevicePolicyManager#wipeDevice()} introduced in Android U to
+     * reset the device. This is because the {@code DevicePolicyManager#wipeData()} no longer resets
+     * the device when called as the device owner, as it used to do in earlier Android versions.
      */
-    boolean wipeData();
+    boolean wipeDevice();
 
     /**
-     * Get the State Controller associated with this Policy Controller.
+     * Enforce current policies.
      */
-    DeviceStateController getStateController();
+    ListenableFuture<Void> enforceCurrentPolicies();
+
+    /**
+     * Enforce current policies. This is only used in an attempts to restore previous enforced
+     * policies in the case enforceCurrentPolicies() fails.
+     */
+    ListenableFuture<Void> enforceCurrentPoliciesForCriticalFailure();
+
+    /**
+     * Get the launch intent for current enforced state.
+     */
+    ListenableFuture<Intent> getLaunchIntentForCurrentState();
+
+    /**
+     * Called by {@link com.android.devicelockcontroller.DeviceLockControllerService} to call
+     * encryption-aware components.
+     */
+    ListenableFuture<Void> onUserUnlocked();
+
+    /**
+     * Called when a user has completed set-up wizard.
+     */
+    ListenableFuture<Void> onUserSetupCompleted();
+
+    /**
+     * Called by {@link com.android.devicelockcontroller.DeviceLockControllerService} when the
+     * controller or kiosk app crashed.
+     */
+    ListenableFuture<Void> onAppCrashed(boolean isKiosk);
+
+    @Target(ElementType.TYPE_USE)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            LockTaskType.UNDEFINED,
+            LockTaskType.NOT_IN_LOCK_TASK,
+            LockTaskType.LANDING_ACTIVITY,
+            LockTaskType.CRITICAL_ERROR,
+            LockTaskType.KIOSK_SETUP_ACTIVITY,
+            LockTaskType.KIOSK_LOCK_ACTIVITY
+    })
+    @interface LockTaskType {
+
+        int UNDEFINED = -1;
+        /* Not in lock task mode */
+        int NOT_IN_LOCK_TASK = 0;
+
+        /* Device lock controller landing activity */
+        int LANDING_ACTIVITY = 1;
+
+        /* Hit a critical error during policy enforcement, device will be reset */
+        int CRITICAL_ERROR = 2;
+
+        /* Kiosk app setup activity */
+        int KIOSK_SETUP_ACTIVITY = 3;
+
+        /* Kiosk app lock activity */
+        int KIOSK_LOCK_ACTIVITY = 4;
+    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/DevicePolicyControllerImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/DevicePolicyControllerImpl.java
index d669687..e8ea142 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/DevicePolicyControllerImpl.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/DevicePolicyControllerImpl.java
@@ -16,323 +16,508 @@
 
 package com.android.devicelockcontroller.policy;
 
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_DEFERRED_PROVISIONING;
+import static com.android.devicelockcontroller.activities.ProvisioningActivity.EXTRA_SHOW_CRITICAL_PROVISION_FAILED_UI_ON_START;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_PROVISIONING;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_SECONDARY_USER_PROVISIONING;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_SUBSIDY_DEFERRED_PROVISIONING;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_SUBSIDY_PROVISIONING;
-import static com.android.devicelockcontroller.policy.PolicyHandler.SUCCESS;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNDEFINED;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.KIOSK_PROVISIONED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_FAILED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_IN_PROGRESS;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_PAUSED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED;
+import static com.android.devicelockcontroller.policy.StartLockTaskModeWorker.START_LOCK_TASK_MODE_WORKER_RETRY_INTERVAL_SECONDS;
+import static com.android.devicelockcontroller.policy.StartLockTaskModeWorker.START_LOCK_TASK_MODE_WORK_NAME;
 
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.database.sqlite.SQLiteException;
 import android.os.Build;
 import android.os.UserManager;
 
-import androidx.annotation.NonNull;
+import androidx.annotation.GuardedBy;
 import androidx.annotation.VisibleForTesting;
 import androidx.work.BackoffPolicy;
 import androidx.work.ExistingWorkPolicy;
 import androidx.work.OneTimeWorkRequest;
+import androidx.work.Operation;
 import androidx.work.OutOfQuotaPolicy;
 import androidx.work.WorkManager;
-import androidx.work.Worker;
-import androidx.work.WorkerParameters;
 
-import com.android.devicelockcontroller.DeviceLockControllerApplication;
-import com.android.devicelockcontroller.SystemDeviceLockManagerImpl;
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+import com.android.devicelockcontroller.activities.LandingActivity;
+import com.android.devicelockcontroller.activities.ProvisioningActivity;
 import com.android.devicelockcontroller.common.DeviceLockConstants;
 import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType;
 import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState;
+import com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.util.LogUtil;
 
+import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
-import java.time.Duration;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
+import java.util.concurrent.Executor;
 
 /**
- * Class that listens to state changes and applies the corresponding policies.
- * <p>
- * Note that some APIs return a listenable future because the underlying calls to
- * SetupParameterClient return a listenable future for inter process calls.
+ * An implementation of {@link DevicePolicyController}. This class guarantees thread safety by
+ * synchronizing policies enforcement on background threads in the order of when the API calls
+ * happen. That is, a pre-exist enforcement request will always blocks a incoming enforcement
+ * request until the former completes.
  */
-public final class DevicePolicyControllerImpl
-        implements DevicePolicyController, DeviceStateController.StateListener {
-    static final String START_LOCK_TASK_MODE_WORK_NAME = StartLockTaskModeWorker.TAG;
+public final class DevicePolicyControllerImpl implements DevicePolicyController {
     private static final String TAG = "DevicePolicyControllerImpl";
-    private static final int START_LOCK_TASK_MODE_WORKER_INTERVAL = 35;
+
     private final List<PolicyHandler> mPolicyList = new ArrayList<>();
     private final Context mContext;
     private final DevicePolicyManager mDpm;
-    private final LockTaskModePolicyHandler mLockTaskHandler;
-    private final DeviceStateController mStateController;
+    private final ProvisionStateController mProvisionStateController;
+    // A future that returns the current lock task type for the current provision/device state
+    // after policies enforcement are done.
+    @GuardedBy("this")
+    private ListenableFuture<@LockTaskType Integer> mCurrentEnforcedLockTaskTypeFuture =
+            Futures.immediateFuture(LockTaskType.UNDEFINED);
+    private final Executor mBgExecutor;
+    static final String ACTION_DEVICE_LOCK_KIOSK_SETUP =
+            "com.android.devicelock.action.KIOSK_SETUP";
+    private final UserManager mUserManager;
 
     /**
      * Create a new policy controller.
      *
-     * @param context         The context used by this policy controller.
-     * @param stateController State controller.
+     * @param context The context used by this policy controller.
+     * @param devicePolicyManager  The device policy manager.
+     * @param userManager The user manager.
+     * @param systemDeviceLockManager The system device lock manager.
+     * @param provisionStateController The provision state controller.
+     * @param bgExecutor The background executor.
      */
-    public DevicePolicyControllerImpl(Context context, DeviceStateController stateController) {
-        this(context, stateController,
-                context.getSystemService(DevicePolicyManager.class));
+    public DevicePolicyControllerImpl(Context context,
+            DevicePolicyManager devicePolicyManager,
+            UserManager userManager,
+            SystemDeviceLockManager systemDeviceLockManager,
+            ProvisionStateController provisionStateController,
+            Executor bgExecutor) {
+        this(context,
+                devicePolicyManager,
+                userManager,
+                new UserRestrictionsPolicyHandler(devicePolicyManager, userManager,
+                        Build.isDebuggable(),
+                        bgExecutor),
+                new AppOpsPolicyHandler(systemDeviceLockManager, bgExecutor),
+                new LockTaskModePolicyHandler(context, devicePolicyManager, bgExecutor),
+                new PackagePolicyHandler(context, devicePolicyManager, bgExecutor),
+                new RolePolicyHandler(systemDeviceLockManager, bgExecutor),
+                new KioskKeepAlivePolicyHandler(systemDeviceLockManager, bgExecutor),
+                new ControllerKeepAlivePolicyHandler(systemDeviceLockManager, bgExecutor),
+                new NotificationsPolicyHandler(systemDeviceLockManager, bgExecutor),
+                provisionStateController,
+                bgExecutor);
     }
 
     @VisibleForTesting
     DevicePolicyControllerImpl(Context context,
-            DeviceStateController stateController, DevicePolicyManager dpm) {
+            DevicePolicyManager devicePolicyManager,
+            UserManager userManager,
+            UserRestrictionsPolicyHandler userRestrictionsPolicyHandler,
+            AppOpsPolicyHandler appOpsPolicyHandler,
+            LockTaskModePolicyHandler lockTaskModePolicyHandler,
+            PackagePolicyHandler packagePolicyHandler,
+            RolePolicyHandler rolePolicyHandler,
+            KioskKeepAlivePolicyHandler kioskKeepAlivePolicyHandler,
+            ControllerKeepAlivePolicyHandler controllerKeepAlivePolicyHandler,
+            NotificationsPolicyHandler notificationsPolicyHandler,
+            ProvisionStateController provisionStateController,
+            Executor bgExecutor) {
         mContext = context;
-        mDpm = dpm;
-        mStateController = stateController;
-        mLockTaskHandler = new LockTaskModePolicyHandler(context, dpm);
-
-        mPolicyList.add(new UserRestrictionsPolicyHandler(dpm,
-                context.getSystemService(UserManager.class), Build.isDebuggable()));
-        mPolicyList.add(new AppOpsPolicyHandler(context, SystemDeviceLockManagerImpl.getInstance(),
-                context.getSystemService(AppOpsManager.class)));
-        mPolicyList.add(mLockTaskHandler);
-        mPolicyList.add(new PackagePolicyHandler(context, dpm));
-        mPolicyList.add(new RolePolicyHandler(context, SystemDeviceLockManagerImpl.getInstance()));
-        stateController.addCallback(this);
+        mProvisionStateController = provisionStateController;
+        mBgExecutor = bgExecutor;
+        mDpm = devicePolicyManager;
+        mUserManager = userManager;
+        mPolicyList.add(userRestrictionsPolicyHandler);
+        mPolicyList.add(appOpsPolicyHandler);
+        mPolicyList.add(lockTaskModePolicyHandler);
+        mPolicyList.add(packagePolicyHandler);
+        mPolicyList.add(rolePolicyHandler);
+        mPolicyList.add(kioskKeepAlivePolicyHandler);
+        mPolicyList.add(controllerKeepAlivePolicyHandler);
+        mPolicyList.add(notificationsPolicyHandler);
     }
 
     @Override
-    public ListenableFuture<Boolean> launchActivityInLockedMode() {
-        return Futures.transform(getLockedActivity(), launchIntent -> {
-            if (launchIntent == null) {
-                LogUtil.e(TAG, "Failed to get the locked activity");
-                return false;
-            }
-
-            final ComponentName activity = launchIntent.getComponent();
-            if (activity == null || !mLockTaskHandler.setPreferredActivityForHome(activity)) {
-                LogUtil.e(TAG, "Failed to set preferred activity");
-                return false;
-            }
-
-            launchIntent.addFlags(
-                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-            LogUtil.i(TAG, String.format(Locale.US, "Launching activity: %s", activity));
-            mContext.startActivity(launchIntent,
-                    ActivityOptions.makeBasic().setLockTaskEnabled(true).toBundle());
-            return true;
-        }, mContext.getMainExecutor());
-    }
-
-    @Override
-    public void enqueueStartLockTaskModeWorker(boolean isMandatory) {
-        enqueueStartLockTaskModeWorkerWithDelay(isMandatory, Duration.ZERO);
-    }
-
-    @Override
-    public void enqueueStartLockTaskModeWorkerWithDelay(boolean isMandatory, Duration delay) {
-        final OneTimeWorkRequest.Builder startLockTaskModeRequestBuilder =
-                new OneTimeWorkRequest.Builder(StartLockTaskModeWorker.class)
-                        .setInitialDelay(delay)
-                        .setBackoffCriteria(BackoffPolicy.LINEAR,
-                                Duration.ofSeconds(START_LOCK_TASK_MODE_WORKER_INTERVAL));
-        if (isMandatory) {
-            startLockTaskModeRequestBuilder
-                    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST);
-        }
-
-        WorkManager.getInstance(mContext)
-                .enqueueUniqueWork(START_LOCK_TASK_MODE_WORK_NAME,
-                        ExistingWorkPolicy.APPEND_OR_REPLACE,
-                        startLockTaskModeRequestBuilder.build());
-    }
-
-    @Override
-    public boolean wipeData() {
+    public boolean wipeDevice() {
         LogUtil.i(TAG, "Wiping device");
-
         try {
-            mDpm.wipeData(DevicePolicyManager.WIPE_SILENTLY
+            mDpm.wipeDevice(DevicePolicyManager.WIPE_SILENTLY
                     | DevicePolicyManager.WIPE_RESET_PROTECTION_DATA);
         } catch (SecurityException e) {
             LogUtil.e(TAG, "Cannot wipe device", e);
-
             return false;
         }
-
         return true;
     }
 
     @Override
-    public ListenableFuture<Void> onStateChanged(@DeviceState int newState) {
-        LogUtil.d(TAG, String.format(Locale.US, "onStateChanged (%d)", newState));
-
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
-        for (int i = 0, policyLen = mPolicyList.size(); i < policyLen; i++) {
-            PolicyHandler policy = mPolicyList.get(i);
-            futures.add(Futures.transform(
-                    policy.setPolicyForState(newState), result -> {
-                        if (SUCCESS != result) {
-                            throw new RuntimeException(
-                                    String.format(Locale.US, "Failed to set %s policy", policy));
-                        }
-                        return null;
-                    }, mContext.getMainExecutor()));
-        }
-        return Futures.whenAllSucceed(futures).call(() -> null, mContext.getMainExecutor());
+    public ListenableFuture<Void> enforceCurrentPolicies() {
+        return Futures.transform(enforceCurrentPoliciesAndResolveLockTaskType(
+                        /* failure= */ false),
+                mode -> {
+                    startLockTaskModeIfNeeded(mode);
+                    return null;
+                },
+                mBgExecutor);
     }
 
     @Override
-    public DeviceStateController getStateController() {
-        return mStateController;
+    public ListenableFuture<Void> enforceCurrentPoliciesForCriticalFailure() {
+        return Futures.transform(enforceCurrentPoliciesAndResolveLockTaskType(
+                        /* failure= */ true),
+                mode -> {
+                    startLockTaskModeIfNeeded(mode);
+                    handlePolicyEnforcementFailure();
+                    return null;
+                },
+                mBgExecutor);
     }
 
-    private ListenableFuture<Intent> getLockedActivity() {
-        @DeviceState int state = mStateController.getState();
+    private void handlePolicyEnforcementFailure() {
+        final DeviceLockControllerSchedulerProvider schedulerProvider =
+                (DeviceLockControllerSchedulerProvider) mContext.getApplicationContext();
+        final DeviceLockControllerScheduler scheduler =
+                schedulerProvider.getDeviceLockControllerScheduler();
+        // Hard failure due to policy enforcement, treat it as mandatory reset device alarm.
+        scheduler.scheduleMandatoryResetDeviceAlarm();
 
-        switch (state) {
-            case DeviceState.SETUP_IN_PROGRESS:
-            case DeviceState.SETUP_SUCCEEDED:
-                return getLandingActivityIntent();
-            case DeviceState.KIOSK_SETUP:
-                return getKioskSetupActivityIntent();
-            case DeviceState.LOCKED:
-                return getLockScreenActivityIntent();
-            case DeviceState.SETUP_FAILED:
-            case DeviceState.UNLOCKED:
-            case DeviceState.CLEARED:
-            case DeviceState.UNPROVISIONED:
-                LogUtil.w(TAG, String.format(Locale.US, "%d is not a locked state", state));
-                return Futures.immediateFuture(null);
-            default:
-                LogUtil.w(TAG, String.format(Locale.US, "%d is an invalid state", state));
-                return Futures.immediateFuture(null);
+        ReportDeviceProvisionStateWorker.reportSetupFailed(WorkManager.getInstance(mContext),
+                DeviceLockConstants.ProvisionFailureReason.POLICY_ENFORCEMENT_FAILED);
+    }
+
+    /**
+     * Enforce current policies and then return the resulting lock task type
+     *
+     * @param failure true if this enforcement is due to resetting policies in case of failure.
+     * @return A future for the lock task type corresponding to the current policies.
+     */
+    private ListenableFuture<@LockTaskType Integer> enforceCurrentPoliciesAndResolveLockTaskType(
+            boolean failure) {
+        synchronized (this) {
+            // current lock task type must be assigned to a local variable; otherwise, if
+            // retrieved down the execution flow, it will be returning the new type after execution.
+            ListenableFuture<@LockTaskType Integer> currentLockTaskType =
+                    mCurrentEnforcedLockTaskTypeFuture;
+            ListenableFuture<@LockTaskType Integer> policiesEnforcementFuture =
+                    Futures.transformAsync(
+                            currentLockTaskType,
+                            unused -> {
+                                final ListenableFuture<@ProvisionState Integer> provisionState =
+                                        mProvisionStateController.getState();
+                                final ListenableFuture<@DeviceState Integer> deviceState =
+                                        GlobalParametersClient.getInstance().getDeviceState();
+                                return Futures.whenAllSucceed(provisionState, deviceState)
+                                        .callAsync(
+                                                () -> enforcePoliciesForCurrentStates(
+                                                        Futures.getDone(provisionState),
+                                                        Futures.getDone(deviceState)),
+                                                mBgExecutor
+                                );
+                            },
+                            mBgExecutor);
+            if (failure) {
+                mCurrentEnforcedLockTaskTypeFuture = Futures.immediateFuture(
+                        LockTaskType.CRITICAL_ERROR);
+                return mCurrentEnforcedLockTaskTypeFuture;
+            } else {
+                // To prevent exception propagate to future policies enforcement, catch any
+                // exceptions that might happen during the execution and fallback to previous type
+                // if exception happens.
+                mCurrentEnforcedLockTaskTypeFuture = Futures.catchingAsync(
+                        policiesEnforcementFuture,
+                        Exception.class, unused -> currentLockTaskType,
+                        MoreExecutors.directExecutor());
+            }
+            return policiesEnforcementFuture;
         }
     }
 
-    private ListenableFuture<Intent> getLandingActivityIntent() {
-        SetupParametersClient client = SetupParametersClient.getInstance();
-        ListenableFuture<Boolean> isMandatoryTask = client.isProvisionMandatory();
-        ListenableFuture<@ProvisioningType Integer> provisioningTypeTask =
-                client.getProvisioningType();
-        return Futures.whenAllSucceed(isMandatoryTask, provisioningTypeTask).call(
-                () -> {
-                    Intent resultIntent = new Intent()
-                            .setComponent(ComponentName.unflattenFromString(
-                                    DeviceLockConstants.getLandingActivity(mContext)));
-                    boolean isMandatory = Futures.getDone(isMandatoryTask);
-                    switch (Futures.getDone(provisioningTypeTask)) {
-                        case ProvisioningType.TYPE_FINANCED:
-                            if (!mContext.getUser().isSystem()) {
-                                return resultIntent.setAction(
-                                        ACTION_START_DEVICE_FINANCING_SECONDARY_USER_PROVISIONING);
-                            }
-                            return resultIntent.setAction(
-                                    isMandatory ? ACTION_START_DEVICE_FINANCING_PROVISIONING
-                                            : ACTION_START_DEVICE_FINANCING_DEFERRED_PROVISIONING);
-                        case ProvisioningType.TYPE_SUBSIDY:
-                            return resultIntent.setAction(
-                                    isMandatory ? ACTION_START_DEVICE_SUBSIDY_PROVISIONING
-                                            : ACTION_START_DEVICE_SUBSIDY_DEFERRED_PROVISIONING);
-                        case ProvisioningType.TYPE_UNDEFINED:
-                        default:
-                            throw new IllegalArgumentException("Provisioning type is unknown!");
+    private ListenableFuture<@LockTaskType Integer> enforcePoliciesForCurrentStates(
+            @ProvisionState int provisionState, @DeviceState int deviceState) {
+        LogUtil.i(TAG, "Enforcing policies for provision state " + provisionState
+                + " and device state " + deviceState);
+        if (provisionState == UNPROVISIONED) {
+            return Futures.immediateFuture(resolveLockTaskType(provisionState, deviceState));
+        }
+        List<ListenableFuture<Boolean>> futures = new ArrayList<>();
+        if (deviceState == CLEARED) {
+            // If device is cleared, then ignore provision state and add cleared policies
+            for (int i = 0, policyLen = mPolicyList.size(); i < policyLen; i++) {
+                PolicyHandler policy = mPolicyList.get(i);
+                futures.add(policy.onCleared());
+            }
+        } else if (provisionState == PROVISION_SUCCEEDED) {
+            // If provisioning has succeeded, then ignore provision state and add device state
+            // policies
+            for (int i = 0, policyLen = mPolicyList.size(); i < policyLen; i++) {
+                PolicyHandler policy = mPolicyList.get(i);
+                switch (deviceState) {
+                    case UNLOCKED:
+                        futures.add(policy.onUnlocked());
+                        break;
+                    case LOCKED:
+                        futures.add(policy.onLocked());
+                        break;
+                    case UNDEFINED:
+                        // No policies to enforce in this state.
+                        break;
+                    default:
+                        throw new IllegalArgumentException(
+                                "Invalid device state to enforce: " + deviceState);
+                }
+            }
+        } else {
+            for (int i = 0, policyLen = mPolicyList.size(); i < policyLen; i++) {
+                PolicyHandler policy = mPolicyList.get(i);
+                switch (provisionState) {
+                    case PROVISION_IN_PROGRESS:
+                        futures.add(policy.onProvisionInProgress());
+                        break;
+                    case KIOSK_PROVISIONED:
+                        futures.add(policy.onProvisioned());
+                        break;
+                    case PROVISION_PAUSED:
+                        futures.add(policy.onProvisionPaused());
+                        break;
+                    case PROVISION_FAILED:
+                        futures.add(policy.onProvisionFailed());
+                        break;
+                    default:
+                        throw new IllegalArgumentException(
+                                "Invalid provision state to enforce: " + provisionState);
+                }
+            }
+        }
+        return Futures.transform(Futures.allAsList(futures),
+                results -> {
+                    if (results.stream().reduce(true, (a, r) -> a && r)) {
+                        return resolveLockTaskType(provisionState, deviceState);
+                    } else {
+                        throw new IllegalStateException(
+                                "Failed to enforce policies for provision state " + provisionState
+                                        + " and device state " + deviceState);
                     }
-                }, MoreExecutors.directExecutor());
+                },
+                MoreExecutors.directExecutor());
+    }
+
+    /**
+     * Determines the lock task type based on the current provision and device state
+     */
+    private @LockTaskType int resolveLockTaskType(int provisionState, int deviceState) {
+        if (provisionState == UNPROVISIONED || deviceState == CLEARED) {
+            return LockTaskType.NOT_IN_LOCK_TASK;
+        }
+        if (provisionState == PROVISION_IN_PROGRESS) {
+            return LockTaskType.LANDING_ACTIVITY;
+        }
+        if (provisionState == KIOSK_PROVISIONED) {
+            return LockTaskType.KIOSK_SETUP_ACTIVITY;
+        }
+        if (provisionState == PROVISION_SUCCEEDED && deviceState == LOCKED) {
+            return LockTaskType.KIOSK_LOCK_ACTIVITY;
+        }
+        return LockTaskType.NOT_IN_LOCK_TASK;
     }
 
     private ListenableFuture<Intent> getLockScreenActivityIntent() {
-        final PackageManager packageManager = mContext.getPackageManager();
-        return Futures.transform(SetupParametersClient.getInstance().getKioskPackage(),
+        return Futures.transform(
+                SetupParametersClient.getInstance().getKioskPackage(),
                 kioskPackage -> {
                     if (kioskPackage == null) {
-                        LogUtil.e(TAG, "Missing kiosk package parameter");
-                        return null;
+                        throw new IllegalStateException("Missing kiosk package parameter!");
                     }
-
-                    final Intent homeIntent =
-                            new Intent(Intent.ACTION_MAIN)
-                                    .addCategory(Intent.CATEGORY_HOME)
-                                    .setPackage(kioskPackage);
-                    final ResolveInfo resolvedInfo =
-                            packageManager
-                                    .resolveActivity(
-                                            homeIntent,
-                                            PackageManager.MATCH_DEFAULT_ONLY);
+                    Intent homeIntent = new Intent(Intent.ACTION_MAIN)
+                            .addCategory(Intent.CATEGORY_HOME)
+                            .setPackage(kioskPackage);
+                    PackageManager pm = mContext.getPackageManager();
+                    ResolveInfo resolvedInfo = pm.resolveActivity(homeIntent,
+                            PackageManager.MATCH_DEFAULT_ONLY);
                     if (resolvedInfo != null && resolvedInfo.activityInfo != null) {
                         return homeIntent.setComponent(
                                 new ComponentName(kioskPackage,
                                         resolvedInfo.activityInfo.name));
                     }
-                    // Kiosk app does not have an activity to handle the default home intent.
-                    // Fall back to the
-                    // launch activity.
-                    // Note that in this case, Kiosk App can't be effectively set as the
-                    // default home activity.
-                    final Intent launchIntent = packageManager.getLaunchIntentForPackage(
-                            kioskPackage);
+                    // Kiosk app does not have an activity to handle the default
+                    // home intent. Fall back to the launch activity.
+                    // Note that in this case, Kiosk App can't be effectively set as
+                    // the default home activity.
+                    Intent launchIntent = pm.getLaunchIntentForPackage(kioskPackage);
                     if (launchIntent == null) {
-                        LogUtil.e(TAG,
-                                String.format(Locale.US, "Failed to get launch intent for %s",
-                                        kioskPackage));
-                        return null;
+                        throw new IllegalStateException(
+                                "Failed to get launch intent for kiosk app!");
                     }
-
                     return launchIntent;
-                }, mContext.getMainExecutor());
+                }, mBgExecutor);
+    }
+
+    private ListenableFuture<Intent> getLandingActivityIntent() {
+        SetupParametersClient client = SetupParametersClient.getInstance();
+        ListenableFuture<@ProvisioningType Integer> provisioningType =
+                client.getProvisioningType();
+        return Futures.transform(provisioningType,
+                type -> {
+                    Intent resultIntent = new Intent(mContext, LandingActivity.class);
+                    switch (type) {
+                        case ProvisioningType.TYPE_FINANCED:
+                            // TODO(b/288923554) this used to return an intent with action
+                            // ACTION_START_DEVICE_FINANCING_SECONDARY_USER_PROVISIONING
+                            // for secondary users. Rework once a decision has been made about
+                            // what to show to users.
+                            return resultIntent.setAction(
+                                    ACTION_START_DEVICE_FINANCING_PROVISIONING);
+                        case ProvisioningType.TYPE_SUBSIDY:
+                            return resultIntent.setAction(ACTION_START_DEVICE_SUBSIDY_PROVISIONING);
+                        case ProvisioningType.TYPE_UNDEFINED:
+                        default:
+                            throw new IllegalArgumentException("Provisioning type is unknown!");
+                    }
+                }, mBgExecutor);
     }
 
     private ListenableFuture<Intent> getKioskSetupActivityIntent() {
-        return Futures.transform(SetupParametersClient.getInstance().getKioskSetupActivity(),
-                setupActivity -> {
-                    if (setupActivity == null) {
-                        LogUtil.e(TAG, "Failed to get setup Activity");
-                        return null;
+        return Futures.transform(SetupParametersClient.getInstance().getKioskPackage(),
+                kioskPackageName -> {
+                    if (kioskPackageName == null) {
+                        throw new IllegalStateException("Missing kiosk package parameter!");
                     }
+                    final Intent kioskSetupIntent = new Intent(ACTION_DEVICE_LOCK_KIOSK_SETUP);
+                    kioskSetupIntent.setPackage(kioskPackageName);
+                    final ResolveInfo resolveInfo = mContext.getPackageManager()
+                            .resolveActivity(kioskSetupIntent, PackageManager.MATCH_DEFAULT_ONLY);
+                    if (resolveInfo == null || resolveInfo.activityInfo == null) {
+                        throw new IllegalStateException(
+                                "Failed to get setup activity intent for kiosk app!");
+                    }
+                    return kioskSetupIntent.setComponent(new ComponentName(kioskPackageName,
+                            resolveInfo.activityInfo.name));
+                }, mBgExecutor);
+    }
 
-                    return new Intent().setComponent(
-                            ComponentName.unflattenFromString(setupActivity));
-                }, mContext.getMainExecutor());
+    private ListenableFuture<Intent> getProvisioningActivityIntentForCriticalFailure() {
+        final Intent intent = new Intent(mContext, ProvisioningActivity.class)
+                .putExtra(EXTRA_SHOW_CRITICAL_PROVISION_FAILED_UI_ON_START, true);
+        return Futures.immediateFuture(intent);
+    }
+
+
+    @Override
+    public ListenableFuture<Intent> getLaunchIntentForCurrentState() {
+        return Futures.transformAsync(getCurrentEnforcedLockTaskType(),
+                type -> {
+                    switch (type) {
+                        case LockTaskType.NOT_IN_LOCK_TASK:
+                            return Futures.immediateFuture(null);
+                        case LockTaskType.LANDING_ACTIVITY:
+                            return getLandingActivityIntent();
+                        case LockTaskType.CRITICAL_ERROR:
+                            return getProvisioningActivityIntentForCriticalFailure();
+                        case LockTaskType.KIOSK_SETUP_ACTIVITY:
+                            return getKioskSetupActivityIntent();
+                        case LockTaskType.KIOSK_LOCK_ACTIVITY:
+                            return getLockScreenActivityIntent();
+                        default:
+                            throw new IllegalArgumentException("Invalid lock task type!");
+                    }
+                }, mBgExecutor);
     }
 
     /**
-     * A worker class dedicated to start lock task mode when device is locked.
+     * Gets the currently enforced lock task type, enforcing current policies if they haven't been
+     * enforced yet.
      */
-    public static final class StartLockTaskModeWorker extends Worker {
-
-        private static final String TAG = "StartLockTaskModeWorker";
-
-        public StartLockTaskModeWorker(
-                @NonNull Context context,
-                @NonNull WorkerParameters workerParams) {
-            super(context, workerParams);
+    private ListenableFuture<@LockTaskType Integer> getCurrentEnforcedLockTaskType() {
+        synchronized (this) {
+            return Futures.transformAsync(
+                    mCurrentEnforcedLockTaskTypeFuture,
+                    type -> type == LockTaskType.UNDEFINED
+                            ? enforceCurrentPoliciesAndResolveLockTaskType(/* failure= */ false)
+                            : Futures.immediateFuture(type),
+                    mBgExecutor);
         }
+    }
 
-        @NonNull
-        @Override
-        public Result doWork() {
-            final Context context = DeviceLockControllerApplication.getAppContext();
-            final ActivityManager am = context.getSystemService(ActivityManager.class);
-            if (am != null && am.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED) {
-                LogUtil.i(TAG, "successfully entered lock task mode");
-                return Result.success();
+    @Override
+    public ListenableFuture<Void> onUserUnlocked() {
+        return Futures.transformAsync(mProvisionStateController.onUserUnlocked(),
+                unused -> Futures.transform(getCurrentEnforcedLockTaskType(),
+                        mode -> {
+                            startLockTaskModeIfNeeded(mode);
+                            return null;
+                        },
+                        mBgExecutor),
+                mBgExecutor);
+    }
+
+    @Override
+    public ListenableFuture<Void> onUserSetupCompleted() {
+        return mProvisionStateController.onUserSetupCompleted();
+    }
+
+    @Override
+    public ListenableFuture<Void> onAppCrashed(boolean isKiosk) {
+        final String crashedApp = isKiosk ? "kiosk" : "dlc";
+        LogUtil.i(TAG, "Controller notified about " + crashedApp
+                + " having crashed while in lock task mode");
+        return Futures.transform(getCurrentEnforcedLockTaskType(),
+                mode -> {
+                    startLockTaskModeIfNeeded(mode);
+                    return null;
+                },
+                mBgExecutor);
+    }
+
+    private void startLockTaskModeIfNeeded(@LockTaskType Integer type) {
+        if (type == LockTaskType.NOT_IN_LOCK_TASK || !mUserManager.isUserUnlocked()) {
+            return;
+        }
+        WorkManager workManager = WorkManager.getInstance(mContext);
+        OneTimeWorkRequest startLockTask = new OneTimeWorkRequest.Builder(
+                StartLockTaskModeWorker.class)
+                .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
+                .setBackoffCriteria(BackoffPolicy.LINEAR,
+                        START_LOCK_TASK_MODE_WORKER_RETRY_INTERVAL_SECONDS)
+                .build();
+        final ListenableFuture<Operation.State.SUCCESS> enqueueResult =
+                workManager.enqueueUniqueWork(START_LOCK_TASK_MODE_WORK_NAME,
+                        ExistingWorkPolicy.REPLACE, startLockTask).getResult();
+        Futures.addCallback(enqueueResult, new FutureCallback<>() {
+            @Override
+            public void onSuccess(Operation.State.SUCCESS result) {
+                // Enqueued
             }
 
-            if (!Futures.getUnchecked(((PolicyObjectsInterface) context).getPolicyController()
-                    .launchActivityInLockedMode())) {
-                LogUtil.i(TAG, "failed entering lock task mode");
-                return Result.failure();
+            @Override
+            public void onFailure(Throwable t) {
+                LogUtil.e(TAG, "Failed to enqueue 'start lock task mode' work", t);
+                if (t instanceof SQLiteException) {
+                    wipeDevice();
+                } else {
+                    LogUtil.e(TAG, "Not wiping device (non SQL exception)");
+                }
             }
-
-            LogUtil.i(TAG, "Retry entering lock task mode");
-            return Result.retry();
-        }
+        }, mBgExecutor);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/DeviceStateController.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/DeviceStateController.java
index 2718075..890ebfe 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/DeviceStateController.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/DeviceStateController.java
@@ -17,7 +17,6 @@
 package com.android.devicelockcontroller.policy;
 
 import androidx.annotation.IntDef;
-import androidx.annotation.MainThread;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -26,204 +25,51 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
-// TODO: rework the state and events for vNext
-
 /**
- * Interface for the device lock controller state machine.
+ * Interface for lock/unlock and clear state machine.
+ * All users share the same state.
  */
-@MainThread
 public interface DeviceStateController {
-    /**
-     * Enforce all policies for the current device state.
-     */
-    ListenableFuture<Void> enforcePoliciesForCurrentState();
 
     /**
-     * Moves the device to a new state based on the input event
+     * Lock the device.
      */
-    ListenableFuture<Void> setNextStateForEvent(@DeviceEvent int event);
+    ListenableFuture<Void> lockDevice();
 
     /**
-     * Returns the current state of the device
+     * Unlock the device.
      */
-    @DeviceState
-    int getState();
+    ListenableFuture<Void> unlockDevice();
 
     /**
-     * Returns true if the device is in locked state.
+     * Clear the device restrictions.
      */
-    boolean isLocked();
+    ListenableFuture<Void> clearDevice();
+
+    /** Returns true if the device is in locked state. */
+    ListenableFuture<Boolean> isLocked();
 
     /**
-     * Returns true if the device needs to check in with DeviceLock server
+     * Returns the current {@link DeviceState}.
      */
-    boolean isCheckInNeeded();
+    ListenableFuture<Integer> getDeviceState();
 
-    /**
-     * Returns true if the device is in setup flow.
-     */
-    boolean isInSetupState();
+    /** Returns true if the device restrictions have been cleared. */
+    ListenableFuture<Boolean> isCleared();
 
-    /**
-     * Register a callback to get notified on state change.
-     */
-    void addCallback(StateListener listener);
-
-    /**
-     * Remove a previously registered callback.
-     */
-    void removeCallback(StateListener listener);
-
-    /**
-     * Device state definitions
-     */
+    /** Device state definitions. */
     @Target(ElementType.TYPE_USE)
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
-            DeviceState.UNPROVISIONED,
-            DeviceState.SETUP_IN_PROGRESS,
-            DeviceState.SETUP_SUCCEEDED,
-            DeviceState.SETUP_FAILED,
-            DeviceState.KIOSK_SETUP,
+            DeviceState.UNDEFINED,
             DeviceState.UNLOCKED,
             DeviceState.LOCKED,
             DeviceState.CLEARED,
-            DeviceState.PSEUDO_LOCKED,
-            DeviceState.PSEUDO_UNLOCKED,
     })
     @interface DeviceState {
-
-        /* DLC is not provisioned */
-        int UNPROVISIONED = 0;
-
-        /* Setup flow is in progress. This is where kiosk app will be downloaded. */
-        int SETUP_IN_PROGRESS = 1;
-
-        /* Setup has succeeded */
-        int SETUP_SUCCEEDED = 2;
-
-        /* Setup has failed */
-        int SETUP_FAILED = 3;
-
-        /* Showing kiosk setup activity */
-        int KIOSK_SETUP = 4;
-
-        /* Device is unlocked */
-        int UNLOCKED = 5;
-
-        /* Device is locked */
-        int LOCKED = 6;
-
-        /* Fully cleared from locking */
-        int CLEARED = 7;
-
-        /* Device appears to be locked. No Actual locking is performed. Used for testing */
-        int PSEUDO_LOCKED = 8;
-
-        /* Device appears to be unlocked. No Actual unlocking is performed. Used for testing */
-        int PSEUDO_UNLOCKED = 9;
-    }
-
-    /**
-     * Get the corresponding string for input {@link DeviceState}.
-     */
-    static String stateToString(@DeviceState int state) {
-        switch (state) {
-            case DeviceState.UNPROVISIONED:
-                return "UNPROVISIONED";
-            case DeviceState.SETUP_IN_PROGRESS:
-                return "SETUP_IN_PROGRESS";
-            case DeviceState.SETUP_SUCCEEDED:
-                return "SETUP_SUCCEEDED";
-            case DeviceState.SETUP_FAILED:
-                return "SETUP_FAILED";
-            case DeviceState.KIOSK_SETUP:
-                return "KIOSK_SETUP";
-            case DeviceState.UNLOCKED:
-                return "UNLOCKED";
-            case DeviceState.LOCKED:
-                return "LOCKED";
-            case DeviceState.CLEARED:
-                return "CLEARED";
-            case DeviceState.PSEUDO_LOCKED:
-                return "PSEUDO_LOCKED";
-            case DeviceState.PSEUDO_UNLOCKED:
-                return "PSEUDO_UNLOCKED";
-            default:
-                return "UNKNOWN_STATE";
-        }
-    }
-
-
-    /**
-     * Device event definitions
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            DeviceEvent.PROVISIONING_SUCCESS,
-            DeviceEvent.SETUP_SUCCESS,
-            DeviceEvent.SETUP_FAILURE,
-            DeviceEvent.SETUP_COMPLETE,
-            DeviceEvent.LOCK_DEVICE,
-            DeviceEvent.UNLOCK_DEVICE,
-            DeviceEvent.CLEAR,
-    })
-    @interface DeviceEvent {
-
-        /* App provisioned */
-        int PROVISIONING_SUCCESS = 0;
-
-        /* Setup completed successfully */
-        int SETUP_SUCCESS = 1;
-
-        /* Setup failed to complete */
-        int SETUP_FAILURE = 2;
-
-        /* Setup has complete */
-        int SETUP_COMPLETE = 3;
-
-        /* Lock device */
-        int LOCK_DEVICE = 4;
-
-        /* Unlock device */
-        int UNLOCK_DEVICE = 5;
-
-        /* Clear device lock restrictions */
-        int CLEAR = 6;
-    }
-
-    /**
-     * Listener interface for state changes.
-     */
-    interface StateListener {
-        /**
-         * Notified after the device transitions to a new state
-         */
-        ListenableFuture<Void> onStateChanged(@DeviceState int newState);
-    }
-
-
-    /**
-     * Get the corresponding string for the input {@link DeviceEvent}
-     */
-    static String eventToString(@DeviceEvent int event) {
-        switch (event) {
-            case DeviceEvent.PROVISIONING_SUCCESS:
-                return "PROVISIONING_SUCCESS";
-            case DeviceEvent.SETUP_SUCCESS:
-                return "SETUP_SUCCESS";
-            case DeviceEvent.SETUP_FAILURE:
-                return "SETUP_FAILURE";
-            case DeviceEvent.SETUP_COMPLETE:
-                return "SETUP_COMPLETE";
-            case DeviceEvent.LOCK_DEVICE:
-                return "LOCK_DEVICE";
-            case DeviceEvent.UNLOCK_DEVICE:
-                return "UNLOCK_DEVICE";
-            case DeviceEvent.CLEAR:
-                return "CLEAR";
-            default:
-                return "UNKNOWN_EVENT";
-        }
+        int UNDEFINED = 0;
+        int UNLOCKED = 1;
+        int LOCKED = 2;
+        int CLEARED = 3;
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/DeviceStateControllerImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/DeviceStateControllerImpl.java
index 0630a11..0480b74 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/DeviceStateControllerImpl.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/DeviceStateControllerImpl.java
@@ -16,171 +16,130 @@
 
 package com.android.devicelockcontroller.policy;
 
-import android.content.Context;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNDEFINED;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_SUCCESS;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.KIOSK_PROVISIONED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED;
 
-import androidx.annotation.VisibleForTesting;
-
-import com.android.devicelockcontroller.storage.UserParameters;
-import com.android.devicelockcontroller.util.LogUtil;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
+import java.util.concurrent.Executor;
 
-/**
- * State machine for device lock controller.
- */
+/** An implementation of the {@link DeviceStateController} */
 public final class DeviceStateControllerImpl implements DeviceStateController {
-    private static final String TAG = "DeviceStateControllerImpl";
-    private final Context mContext;
-    private final ArrayList<StateListener> mListeners = new ArrayList<>();
-    private int mState;
+    private final ProvisionStateController mProvisionStateController;
+    private final DevicePolicyController mPolicyController;
+    private final GlobalParametersClient mGlobalParametersClient;
+    private final Executor mExecutor;
+    // Used to exercising APIs under CTS without actually applying any policies.
+    // This is not persistent across controller restarts, but should be good enough for the
+    // intended purpose.
+    private volatile @DeviceState int mPseudoDeviceState;
 
-    /**
-     * Create a new state machine.
-     *
-     * @param context The context used for the state machine.
-     */
-    public DeviceStateControllerImpl(Context context) {
-        mState = UserParameters.getDeviceState(context);
-        LogUtil.i(TAG, String.format(Locale.US, "Starting state is %d", mState));
-        mContext = context;
+    public DeviceStateControllerImpl(DevicePolicyController policyController,
+            ProvisionStateController provisionStateController, Executor executor) {
+        mPolicyController = policyController;
+        mProvisionStateController = provisionStateController;
+        mGlobalParametersClient = GlobalParametersClient.getInstance();
+        mExecutor = executor;
+        mPseudoDeviceState = UNDEFINED;
+    }
+
+    @Override
+    public ListenableFuture<Void> lockDevice() {
+        return setDeviceState(LOCKED);
+    }
+
+    @Override
+    public ListenableFuture<Void> unlockDevice() {
+        return setDeviceState(UNLOCKED);
+    }
+
+    @Override
+    public ListenableFuture<Void> clearDevice() {
+        return setDeviceState(CLEARED);
     }
 
     /**
-     * Enforce all policies for the current state.
-     * This method is used to initially enforce policies.
-     * Note that policies are also automatically enforced on state transitions.
+     * Set the global device state to be the input {@link DeviceState}. The returned
+     * {@link ListenableFuture} will complete when both the state change and policies enforcement
+     * for new state are done.
      */
-    @Override
-    public ListenableFuture<Void> enforcePoliciesForCurrentState() {
-        final List<ListenableFuture<Void>> onStateChangedTasks = new ArrayList<>();
-        synchronized (mListeners) {
-            for (StateListener listener : mListeners) {
-                onStateChangedTasks.add(listener.onStateChanged(mState));
-            }
+    private ListenableFuture<Void> setDeviceState(@DeviceState int deviceState) {
+        if (deviceState == UNDEFINED) {
+            throw new IllegalArgumentException("Cannot set device state to UNDEFINED");
         }
-        return Futures.whenAllSucceed(onStateChangedTasks).call((() -> null),
-                MoreExecutors.directExecutor());
+        return Futures.transformAsync(mProvisionStateController.getState(),
+                provisionState -> {
+                    final ListenableFuture<Void> maybeSetProvisioningSuccess;
+                    if (provisionState == KIOSK_PROVISIONED) {
+                        maybeSetProvisioningSuccess =
+                                mProvisionStateController.setNextStateForEvent(PROVISION_SUCCESS);
+                    } else if (provisionState == PROVISION_SUCCEEDED) {
+                        maybeSetProvisioningSuccess = Futures.immediateVoidFuture();
+                    } else if (provisionState == UNPROVISIONED && (deviceState == LOCKED
+                            || deviceState == UNLOCKED)) {
+                        // During normal operation, we should not get lock/unlock requests in
+                        // the UNPROVISIONED state. Used for CTS compliance.
+                        mPseudoDeviceState = deviceState;
+                        // Do not apply any policies
+                        return Futures.immediateVoidFuture();
+                    } else {
+                        throw new RuntimeException(
+                                "User has not been provisioned! Current state " + provisionState);
+                    }
+                    return Futures.transformAsync(maybeSetProvisioningSuccess,
+                            unused -> Futures.transformAsync(isCleared(),
+                                    isCleared -> {
+                                        if (isCleared) {
+                                            throw new RuntimeException("Device has been cleared!");
+                                        }
+                                        return Futures.transformAsync(
+                                                mGlobalParametersClient.setDeviceState(deviceState),
+                                                state -> mPolicyController.enforceCurrentPolicies(),
+                                                mExecutor);
+                                    }, mExecutor),
+                            mExecutor);
+                }, mExecutor);
     }
 
     @Override
-    public ListenableFuture<Void> setNextStateForEvent(@DeviceEvent int event) {
-        try {
-            updateState(getNextState(event));
-        } catch (StateTransitionException e) {
-            return Futures.immediateFailedFuture(e);
-        }
-        LogUtil.i(TAG, String.format(Locale.US, "handleEvent %d, newState %d", event, mState));
-
-        return enforcePoliciesForCurrentState();
+    public ListenableFuture<Boolean> isLocked() {
+        return Futures.transformAsync(mProvisionStateController.getState(),
+                provisionState -> {
+                    if (provisionState == UNPROVISIONED) {
+                        // Used for CTS compliance.
+                        return Futures.immediateFuture(mPseudoDeviceState == LOCKED);
+                    } else {
+                        return Futures.transform(mGlobalParametersClient.getDeviceState(),
+                                s -> {
+                                    if (s == UNDEFINED) {
+                                        throw new IllegalStateException("isLocked called before "
+                                                + "setting the locked state "
+                                                + "(lockDevice/unlockDevice)");
+                                    }
+                                    return s == LOCKED;
+                                }, mExecutor);
+                    }
+                }, mExecutor);
     }
 
     @Override
-    public int getState() {
-        return mState;
+    public ListenableFuture<Integer> getDeviceState() {
+        return mGlobalParametersClient.getDeviceState();
     }
 
     @Override
-    public boolean isLocked() {
-        return mState == DeviceState.SETUP_IN_PROGRESS
-                || mState == DeviceState.SETUP_SUCCEEDED
-                || mState == DeviceState.KIOSK_SETUP
-                || mState == DeviceState.LOCKED
-                || mState == DeviceState.PSEUDO_LOCKED;
-    }
-
-    @Override
-    public boolean isCheckInNeeded() {
-        return mState == DeviceState.UNPROVISIONED || mState == DeviceState.PSEUDO_LOCKED
-                || mState == DeviceState.PSEUDO_UNLOCKED;
-    }
-
-    @Override
-    public boolean isInSetupState() {
-        return mState == DeviceState.SETUP_IN_PROGRESS
-                || mState == DeviceState.SETUP_SUCCEEDED
-                || mState == DeviceState.SETUP_FAILED;
-    }
-
-    @Override
-    public void addCallback(StateListener listener) {
-        synchronized (mListeners) {
-            mListeners.add(listener);
-        }
-    }
-
-    @Override
-    public void removeCallback(StateListener listener) {
-        synchronized (mListeners) {
-            mListeners.remove(listener);
-        }
-    }
-
-    @VisibleForTesting
-    @DeviceState
-    int getNextState(@DeviceEvent int event) throws StateTransitionException {
-        switch (event) {
-            case DeviceEvent.PROVISIONING_SUCCESS:
-                if (mState == DeviceState.UNPROVISIONED || mState == DeviceState.SETUP_FAILED
-                        || mState == DeviceState.PSEUDO_LOCKED
-                        || mState == DeviceState.PSEUDO_UNLOCKED) {
-                    return DeviceState.SETUP_IN_PROGRESS;
-                }
-                break;
-            case DeviceEvent.SETUP_SUCCESS:
-                if (mState == DeviceState.SETUP_IN_PROGRESS) {
-                    return DeviceState.SETUP_SUCCEEDED;
-                }
-                break;
-            case DeviceEvent.SETUP_FAILURE:
-                if (mState == DeviceState.SETUP_IN_PROGRESS) {
-                    return DeviceState.SETUP_FAILED;
-                }
-                break;
-            case DeviceEvent.SETUP_COMPLETE:
-                if (mState == DeviceState.SETUP_SUCCEEDED) {
-                    return DeviceState.KIOSK_SETUP;
-                }
-                break;
-            case DeviceEvent.LOCK_DEVICE:
-                if (mState == DeviceState.UNPROVISIONED || mState == DeviceState.PSEUDO_UNLOCKED
-                        || mState == DeviceState.PSEUDO_LOCKED) {
-                    return DeviceState.PSEUDO_LOCKED;
-                }
-                if (mState == DeviceState.UNLOCKED || mState == DeviceState.LOCKED) {
-                    return DeviceState.LOCKED;
-                }
-                break;
-            case DeviceEvent.UNLOCK_DEVICE:
-                if (mState == DeviceState.PSEUDO_LOCKED || mState == DeviceState.PSEUDO_UNLOCKED) {
-                    return DeviceState.PSEUDO_UNLOCKED;
-                }
-                if (mState == DeviceState.LOCKED || mState == DeviceState.UNLOCKED
-                        || mState == DeviceState.KIOSK_SETUP) {
-                    return DeviceState.UNLOCKED;
-                }
-                break;
-            case DeviceEvent.CLEAR:
-                if (mState == DeviceState.LOCKED
-                        || mState == DeviceState.UNLOCKED
-                        || mState == DeviceState.KIOSK_SETUP) {
-                    return DeviceState.CLEARED;
-                }
-                break;
-            default:
-                break;
-        }
-
-        throw new StateTransitionException(mState, event);
-    }
-
-    private void updateState(@DeviceState int newState) {
-        UserParameters.setDeviceState(mContext, newState);
-        mState = newState;
+    public ListenableFuture<Boolean> isCleared() {
+        return Futures.transform(mGlobalParametersClient.getDeviceState(),
+                s -> s == CLEARED, MoreExecutors.directExecutor());
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/FinalizationController.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/FinalizationController.java
new file mode 100644
index 0000000..514d775
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/FinalizationController.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import com.android.devicelockcontroller.provision.grpc.DeviceFinalizeClient.ReportDeviceProgramCompleteResponse;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Controller that handles finalizing the device when the restrictions are cleared and the device
+ * should no longer be financed.
+ */
+public interface FinalizationController {
+
+    /**
+     * Initializes the controller and enforces the initial state.
+     *
+     * @return future for when the state has been enforced
+     */
+    ListenableFuture<Void> enforceInitialState();
+
+    /**
+     * Notifies the controller that the device restrictions have been cleared and that the device
+     * should start the finalization process.
+     *
+     * @return future for when the clear has been handled
+     */
+    ListenableFuture<Void> notifyRestrictionsCleared();
+
+    /**
+     * Notifies the controller of the result of reporting the finalization state to the server
+     *
+     * @param response from the server
+     * @return future for when the report has been handled
+     */
+    ListenableFuture<Void> notifyFinalizationReportResult(
+            ReportDeviceProgramCompleteResponse response);
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/FinalizationControllerImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/FinalizationControllerImpl.java
new file mode 100644
index 0000000..4032901
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/FinalizationControllerImpl.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.FINALIZED;
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.FINALIZED_UNREPORTED;
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.UNFINALIZED;
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.UNINITIALIZED;
+import static com.android.devicelockcontroller.provision.worker.AbstractCheckInWorker.BACKOFF_DELAY;
+import static com.android.devicelockcontroller.provision.worker.ReportDeviceLockProgramCompleteWorker.REPORT_DEVICE_LOCK_PROGRAM_COMPLETE_WORK_NAME;
+
+import android.annotation.IntDef;
+import android.app.AlarmManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.OutcomeReceiver;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+import androidx.work.BackoffPolicy;
+import androidx.work.Constraints;
+import androidx.work.ExistingWorkPolicy;
+import androidx.work.ListenableWorker;
+import androidx.work.NetworkType;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.Operation;
+import androidx.work.WorkManager;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+import com.android.devicelockcontroller.SystemDeviceLockManagerImpl;
+import com.android.devicelockcontroller.provision.grpc.DeviceFinalizeClient.ReportDeviceProgramCompleteResponse;
+import com.android.devicelockcontroller.provision.worker.ReportDeviceLockProgramCompleteWorker;
+import com.android.devicelockcontroller.receivers.FinalizationBootCompletedReceiver;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * Implementation of {@link FinalizationController} that finalizes the device by reporting the
+ * state to the server and effectively disabling this application entirely.
+ */
+public final class FinalizationControllerImpl implements FinalizationController {
+
+    private static final String TAG = FinalizationControllerImpl.class.getSimpleName();
+
+    @Target(ElementType.TYPE_USE)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            UNFINALIZED,
+            FINALIZED_UNREPORTED,
+            FINALIZED,
+            UNINITIALIZED
+    })
+    public @interface FinalizationState {
+        /* Not finalized */
+        int UNFINALIZED = 0;
+
+        /* Device is finalized but still needs to report finalization to server */
+        int FINALIZED_UNREPORTED = 1;
+
+        /* Fully finalized. All bookkeeping is finished and okay to disable app. */
+        int FINALIZED = 2;
+
+        /* State has yet to be initialized */
+        int UNINITIALIZED = -1;
+    }
+
+    /** Dispatch queue to guarantee state changes occur sequentially */
+    private final FinalizationStateDispatchQueue mDispatchQueue;
+    private final Executor mBgExecutor;
+    private final Context mContext;
+    private final SystemDeviceLockManager mSystemDeviceLockManager;
+    private final Class<? extends ListenableWorker> mReportDeviceFinalizedWorkerClass;
+    private final Object mLock = new Object();
+    /** Future for after initial finalization state is set from disk */
+    private volatile ListenableFuture<Void> mStateInitializedFuture;
+
+    public FinalizationControllerImpl(Context context) {
+        this(context,
+                new FinalizationStateDispatchQueue(),
+                Executors.newCachedThreadPool(),
+                ReportDeviceLockProgramCompleteWorker.class,
+                SystemDeviceLockManagerImpl.getInstance());
+    }
+
+    @VisibleForTesting
+    public FinalizationControllerImpl(
+            Context context,
+            FinalizationStateDispatchQueue dispatchQueue,
+            Executor bgExecutor,
+            Class<? extends ListenableWorker> reportDeviceFinalizedWorkerClass,
+            SystemDeviceLockManager systemDeviceLockManager) {
+        mContext = context;
+        mDispatchQueue = dispatchQueue;
+        mDispatchQueue.init(this::onStateChanged);
+        mBgExecutor = bgExecutor;
+        mReportDeviceFinalizedWorkerClass = reportDeviceFinalizedWorkerClass;
+        mSystemDeviceLockManager = systemDeviceLockManager;
+    }
+
+    @Override
+    public ListenableFuture<Void> enforceInitialState() {
+        ListenableFuture<Void> initializedFuture = mStateInitializedFuture;
+        if (initializedFuture == null) {
+            synchronized (mLock) {
+                initializedFuture = mStateInitializedFuture;
+                if (initializedFuture == null) {
+                    ListenableFuture<Integer> initialStateFuture =
+                            GlobalParametersClient.getInstance().getFinalizationState();
+                    initializedFuture = Futures.transformAsync(initialStateFuture,
+                            initialState -> {
+                                LogUtil.d(TAG, "Enforcing initial state: " + initialState);
+                                return mDispatchQueue.enqueueStateChange(initialState);
+                            },
+                            mBgExecutor);
+                    mStateInitializedFuture = initializedFuture;
+                }
+            }
+        }
+        return initializedFuture;
+    }
+
+    @Override
+    public ListenableFuture<Void> notifyRestrictionsCleared() {
+        LogUtil.d(TAG, "Clearing restrictions");
+        return Futures.transformAsync(enforceInitialState(),
+                unused -> mDispatchQueue.enqueueStateChange(FINALIZED_UNREPORTED),
+                mBgExecutor);
+    }
+
+    @Override
+    public ListenableFuture<Void> notifyFinalizationReportResult(
+            ReportDeviceProgramCompleteResponse response) {
+        if (response.isSuccessful()) {
+            LogUtil.d(TAG, "Successfully reported finalization to server. Finalizing...");
+            return Futures.transformAsync(enforceInitialState(),
+                    unused -> mDispatchQueue.enqueueStateChange(FINALIZED),
+                    mBgExecutor);
+        } else {
+            // TODO(301320235): Determine how to handle an unrecoverable failure
+            // response from the server
+            LogUtil.e(TAG, "Unrecoverable failure in reporting finalization state: " + response);
+            return Futures.immediateVoidFuture();
+        }
+    }
+
+    @WorkerThread
+    private ListenableFuture<Void> onStateChanged(@FinalizationState int oldState,
+            @FinalizationState int newState) {
+        final ListenableFuture<Void> persistStateFuture =
+                GlobalParametersClient.getInstance().setFinalizationState(newState);
+        if (oldState == UNFINALIZED) {
+            // Enable boot receiver to check finalization state on disk
+            PackageManager pm = mContext.getPackageManager();
+            pm.setComponentEnabledSetting(
+                    new ComponentName(mContext,
+                            FinalizationBootCompletedReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                    PackageManager.DONT_KILL_APP);
+        }
+        switch (newState) {
+            case UNFINALIZED:
+                return persistStateFuture;
+            case FINALIZED_UNREPORTED:
+                requestWorkToReportFinalized();
+                return persistStateFuture;
+            case FINALIZED:
+                // Ensure disabling only happens after state is written to disk in case we somehow
+                // exit the disabled state and need to disable again.
+                return Futures.transformAsync(persistStateFuture,
+                        unused -> disableEntireApplication(),
+                        mBgExecutor);
+            case UNINITIALIZED:
+                throw new IllegalArgumentException("Tried to set state back to uninitialized!");
+            default:
+                throw new IllegalArgumentException("Unknown state " + newState);
+        }
+    }
+
+    /**
+     * Request work to report device is finalized.
+     */
+    private void requestWorkToReportFinalized() {
+        WorkManager workManager =
+                WorkManager.getInstance(mContext);
+        Constraints constraints = new Constraints.Builder()
+                .setRequiredNetworkType(NetworkType.CONNECTED)
+                .build();
+        OneTimeWorkRequest work =
+                new OneTimeWorkRequest.Builder(mReportDeviceFinalizedWorkerClass)
+                        .setConstraints(constraints)
+                        .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, BACKOFF_DELAY)
+                        .build();
+        ListenableFuture<Operation.State.SUCCESS> result =
+                workManager.enqueueUniqueWork(REPORT_DEVICE_LOCK_PROGRAM_COMPLETE_WORK_NAME,
+                        ExistingWorkPolicy.REPLACE, work).getResult();
+        Futures.addCallback(result,
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Operation.State.SUCCESS result) {
+                        // no-op
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        // Don't reset the device in this case since the financing program is
+                        // effectively over.
+                        LogUtil.e(TAG, "Failed to enqueue 'device lock program complete' work",
+                                t);
+                    }
+                },
+                MoreExecutors.directExecutor()
+        );
+    }
+
+    /**
+     * Disables the entire device lock controller application.
+     *
+     * This will remove any work, alarms, receivers, etc., and this application should never run
+     * on the device again after this point.
+     *
+     * This method returns a future but it is a bit of an odd case as the application itself
+     * may end up disabled before/after the future is handled depending on when package manager
+     * enforces the application is disabled.
+     *
+     * @return future for when this is done
+     */
+    private ListenableFuture<Void> disableEntireApplication() {
+        WorkManager workManager = WorkManager.getInstance(mContext);
+        workManager.cancelAllWork();
+        AlarmManager alarmManager = mContext.getSystemService(AlarmManager.class);
+        alarmManager.cancelAll();
+        // This kills and disables the app
+        ListenableFuture<Void> disableApplicationFuture = CallbackToFutureAdapter.getFuture(
+                completer -> {
+                        mSystemDeviceLockManager.setDeviceFinalized(true, mBgExecutor,
+                                new OutcomeReceiver<>() {
+                                    @Override
+                                    public void onResult(Void result) {
+                                        completer.set(null);
+                                    }
+
+                                    @Override
+                                    public void onError(@NonNull Exception error) {
+                                        LogUtil.e(TAG, "Failed to set device finalized in"
+                                                + "system service.", error);
+                                        completer.setException(error);
+                                    }
+                                });
+                    return "Disable application future";
+                }
+        );
+        return disableApplicationFuture;
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/FinalizationStateDispatchQueue.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/FinalizationStateDispatchQueue.java
new file mode 100644
index 0000000..96b6f6c
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/FinalizationStateDispatchQueue.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.FINALIZED;
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.FINALIZED_UNREPORTED;
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.UNFINALIZED;
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.UNINITIALIZED;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState;
+
+import com.google.common.util.concurrent.ExecutionSequencer;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * Dispatch queue for any changes to the finalization state.
+ *
+ * Guarantees serialization of any state changes so that callbacks happen sequentially in the
+ * order the state changes occurred.
+ */
+final class FinalizationStateDispatchQueue {
+    private final ExecutionSequencer mExecutionSequencer;
+    private final Executor mBgExecutor;
+    private @Nullable StateChangeCallback mCallback;
+    private @FinalizationState int mState = UNINITIALIZED;
+
+    FinalizationStateDispatchQueue() {
+        this(ExecutionSequencer.create());
+    }
+
+    @VisibleForTesting
+    FinalizationStateDispatchQueue(ExecutionSequencer sequencer) {
+        mExecutionSequencer = sequencer;
+        mBgExecutor = Executors.newSingleThreadExecutor();
+    }
+
+    /**
+     * Initializes the queue.
+     *
+     * @param callback callback that runs atomically with any state changes
+     */
+    void init(@NonNull StateChangeCallback callback) {
+        mCallback = callback;
+    }
+
+    /**
+     * Enqueue a state change to be handled after all previous state change requests have resolved.
+     *
+     * Attempting to return to a previous state in the finalization process will no-op.
+     *
+     * @param newState new state to go to
+     * @return future for when the state changes and any callbacks are complete
+     */
+    ListenableFuture<Void> enqueueStateChange(@FinalizationState int newState) {
+        return mExecutionSequencer.submitAsync(() -> handleStateChange(newState), mBgExecutor);
+    }
+
+    /**
+     * Handles a state change.
+     *
+     * @param newState state to change to
+     * @return future for when the state changes and any callbacks are complete
+     */
+    private ListenableFuture<Void> handleStateChange(@FinalizationState int newState) {
+        final int oldState = mState;
+        if (oldState == newState) {
+            return Futures.immediateVoidFuture();
+        }
+        if (!isValidStateChange(oldState, newState)) {
+            return Futures.immediateVoidFuture();
+        }
+        mState = newState;
+        if (mCallback == null) {
+            return Futures.immediateVoidFuture();
+        }
+        return mCallback.onStateChanged(oldState, newState);
+    }
+
+    private static boolean isValidStateChange(
+            @FinalizationState int oldState,
+            @FinalizationState int newState) {
+        if (oldState == UNINITIALIZED) {
+            return true;
+        }
+        if (oldState == UNFINALIZED && newState == FINALIZED_UNREPORTED) {
+            return true;
+        }
+        if (oldState == FINALIZED_UNREPORTED && newState == FINALIZED) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Callback for when the state has changed. Runs sequentially with {@link #mExecutionSequencer}.
+     */
+    interface StateChangeCallback {
+
+        /**
+         * Called when the state has changed
+         *
+         * @param oldState the previous state
+         * @param newState the new state
+         * @return future for when state change callback has finished
+         */
+        ListenableFuture<Void> onStateChanged(@FinalizationState int oldState,
+                @FinalizationState int newState);
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/InstallExistingPackageTask.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/InstallExistingPackageTask.java
deleted file mode 100644
index 4380cde..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/InstallExistingPackageTask.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
-
-import static android.app.PendingIntent.FLAG_MUTABLE;
-import static android.app.PendingIntent.FLAG_ONE_SHOT;
-import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
-import static android.content.pm.ApplicationInfo.FLAG_INSTALLED;
-import static android.content.pm.PackageInstaller.EXTRA_STATUS_MESSAGE;
-import static android.content.pm.PackageManager.INSTALL_REASON_UNKNOWN;
-
-import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
-
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageInstaller;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.PackageInfoFlags;
-import android.os.Handler;
-import android.os.Looper;
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.work.WorkerParameters;
-
-import com.android.devicelockcontroller.util.LogUtil;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.util.concurrent.FluentFuture;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.SettableFuture;
-
-import java.util.Locale;
-
-/**
- * Install an existing package for a secondary user.
- */
-public final class InstallExistingPackageTask extends AbstractTask {
-    private static final String TAG = "InstallExistingPackageTask";
-
-    @VisibleForTesting
-    static final String ACTION_INSTALL_EXISTING_APP_COMPLETE =
-            "com.android.devicelockcontroller.policy.ACTION_INSTALL_EXISTING_APP_COMPLETE";
-
-    private final Context mContext;
-    private final ListeningExecutorService mExecutorService;
-    private final InstallExistingPackageCompleteBroadcastReceiver mBroadcastReceiver;
-    private final PackageInstallerWrapper mPackageInstaller;
-    private final PackageInstallPendingIntentProvider mPackageInstallPendingIntentProvider;
-    private final String mPackageName;
-
-    public InstallExistingPackageTask(Context context, WorkerParameters workerParameters,
-            ListeningExecutorService executorService) {
-        this(context, workerParameters, executorService,
-                new InstallExistingPackageCompleteBroadcastReceiver(context),
-                new PackageInstallerWrapper(context.getPackageManager().getPackageInstaller()),
-                new PackageInstallPendingIntentProviderImpl(context));
-    }
-
-    @VisibleForTesting
-    InstallExistingPackageTask(Context context, WorkerParameters workerParameters,
-            ListeningExecutorService executorService,
-            InstallExistingPackageCompleteBroadcastReceiver broadcastReceiver,
-            PackageInstallerWrapper packageInstaller,
-            PackageInstallPendingIntentProvider packageInstallPendingIntentProvider) {
-        super(context, workerParameters);
-
-        mContext = context;
-        mExecutorService = executorService;
-        mBroadcastReceiver = broadcastReceiver;
-        mPackageInstaller = packageInstaller;
-        mPackageInstallPendingIntentProvider = packageInstallPendingIntentProvider;
-        mPackageName = workerParameters.getInputData().getString(EXTRA_KIOSK_PACKAGE);
-    }
-
-    private static boolean isPackageInstalled(Context context, String packageName) {
-        final PackageManager pm = context.getPackageManager();
-        try {
-            // Requires permission QUERY_ALL_PACKAGES
-            final PackageInfo packageInfo =
-                    pm.getPackageInfo(packageName, PackageInfoFlags.of(0));
-            return (packageInfo != null)
-                    && ((packageInfo.applicationInfo.flags & FLAG_INSTALLED) != 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            return false;
-        }
-    }
-
-    @NonNull
-    @Override
-    public ListenableFuture<Result> startWork() {
-        return mExecutorService.submit(
-                () -> {
-                    LogUtil.i(TAG, "Starts to run");
-
-                    if (TextUtils.isEmpty(mPackageName)) {
-                        LogUtil.e(TAG, "The package name is null or empty");
-                        return failure(ERROR_CODE_NO_PACKAGE_NAME);
-                    }
-
-                    if (isPackageInstalled(mContext, mPackageName)) {
-                        LogUtil.i(TAG, "Package already installed");
-
-                        return Result.success();
-                    }
-
-                    mContext.registerReceiver(mBroadcastReceiver,
-                            new IntentFilter(ACTION_INSTALL_EXISTING_APP_COMPLETE),
-                            Context.RECEIVER_NOT_EXPORTED);
-
-                    final PendingIntent pendingIntent =
-                            mPackageInstallPendingIntentProvider.get();
-                    if (pendingIntent != null) {
-                        mBroadcastReceiver.startPeriodicTask(mPackageName);
-                        mPackageInstaller.installExistingPackage(mPackageName,
-                                INSTALL_REASON_UNKNOWN, pendingIntent.getIntentSender());
-                    } else {
-                        LogUtil.e(TAG, "Unable to get pending intent");
-
-                        return failure(ERROR_CODE_GET_PENDING_INTENT_FAILED);
-                    }
-                    return FluentFuture
-                            .from(mBroadcastReceiver.getFuture())
-                            .transform(success -> {
-                                if (success == null || !success) {
-                                    LogUtil.e(TAG, String.format(Locale.US,
-                                            "InstallExistingPackageCompleteBroadcastReceiver "
-                                                    + "returned result: %b", success));
-                                    return failure(ERROR_CODE_INSTALLATION_FAILED);
-                                } else {
-                                    LogUtil.i(TAG,
-                                            "InstallExistingPackageCompleteBroadcastReceiver "
-                                                    + "returned result: true");
-                                    return Result.success();
-                                }
-                            }, MoreExecutors.directExecutor()).get();
-                });
-    }
-
-    /** Provides a pending intent for a given sessionId from PackageInstaller. */
-    interface PackageInstallPendingIntentProvider {
-        /**
-         * Returns a pending intent for a given sessionId from PackageInstaller.
-         */
-        @Nullable
-        PendingIntent get();
-    }
-
-    /** Default implementation which returns pending intent for package install. */
-    static final class PackageInstallPendingIntentProviderImpl
-            implements PackageInstallPendingIntentProvider {
-        private final Context mContext;
-
-        PackageInstallPendingIntentProviderImpl(Context context) {
-            mContext = context;
-        }
-
-        @Nullable
-        @Override
-        public PendingIntent get() {
-            return PendingIntent.getBroadcast(mContext, /* requestCode */ 0,
-                    new Intent(ACTION_INSTALL_EXISTING_APP_COMPLETE)
-                            .setPackage(mContext.getPackageName()),
-                    FLAG_MUTABLE | FLAG_ONE_SHOT | FLAG_UPDATE_CURRENT);
-        }
-    }
-
-    /**
-     * A broadcast receiver which handles the broadcast intent when package installation is
-     * complete.
-     * The broadcast receiver will use the {@link PackageInstaller#EXTRA_STATUS} field to determine
-     * if the installation is successful.
-     * Note that installExistingPackage only sends the broadcast on success, and therefore we have
-     * an alternative way of detecting failures using polling and a timeout.
-     */
-    static final class InstallExistingPackageCompleteBroadcastReceiver extends BroadcastReceiver {
-        @VisibleForTesting
-        final SettableFuture<Boolean> mFuture = SettableFuture.create();
-
-        private Context mContext;
-        private int mCounter = 0;
-        private final Handler mHandler;
-        private boolean mIsTaskRunning = false;
-        private String mPackageName;
-        private static final int ITERATIONS = 30;
-        private static final int INTERVAL_MS = 1000;
-
-        InstallExistingPackageCompleteBroadcastReceiver(Context context) {
-            super();
-
-            mContext = context;
-            mHandler = new Handler(Looper.getMainLooper());
-        }
-
-        private final Runnable mPeriodicTask = new Runnable() {
-            @Override
-            public void run() {
-                // Already set in onReceive.
-                if (mFuture.isDone()) {
-                    return;
-                }
-
-                executeTask();
-                mCounter++;
-
-                if (mCounter <= ITERATIONS && mIsTaskRunning) {
-                    mHandler.postDelayed(mPeriodicTask, INTERVAL_MS);
-                } else {
-                    LogUtil.e(TAG, "Timed out waiting for package installation");
-                    stopPeriodicTask();
-                    mFuture.set(false);
-                    mContext.unregisterReceiver(
-                            InstallExistingPackageCompleteBroadcastReceiver.this);
-                }
-            }
-        };
-
-        private void executeTask() {
-            if (isPackageInstalled(mContext, mPackageName)) {
-                mFuture.set(true);
-                mContext.unregisterReceiver(this);
-            }
-        }
-
-        private void startPeriodicTask() {
-            if (!mIsTaskRunning) {
-                mIsTaskRunning = true;
-                mCounter = 0;
-                mHandler.postDelayed(mPeriodicTask, INTERVAL_MS);
-            }
-        }
-
-        public void startPeriodicTask(String packageName) {
-            mHandler.post(() -> {
-                mPackageName = packageName;
-                startPeriodicTask();
-            });
-        }
-
-        private void stopPeriodicTask() {
-            if (mIsTaskRunning) {
-                mIsTaskRunning = false;
-                mHandler.removeCallbacks(mPeriodicTask);
-            }
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            stopPeriodicTask();
-
-            // Already set by the periodic task.
-            if (mFuture.isDone()) {
-                return;
-            }
-
-            final int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
-                    PackageInstaller.STATUS_FAILURE);
-
-            context.unregisterReceiver(this);
-            if (status == PackageInstaller.STATUS_SUCCESS) {
-                LogUtil.i(TAG, "Package installation succeed");
-                mFuture.set(true);
-            } else {
-                LogUtil.e(TAG, String.format(Locale.US,
-                        "Package installation failed: status= %d, status message= %s",
-                        status, intent.getStringExtra(EXTRA_STATUS_MESSAGE)));
-                mFuture.set(false);
-            }
-        }
-
-        ListenableFuture<Boolean> getFuture() {
-            return mFuture;
-        }
-    }
-
-    /**
-     * Wrapper for {@link PackageInstaller}, used for testing purpose, especially for failure
-     * testing.
-     */
-    static class PackageInstallerWrapper {
-        private final PackageInstaller mPackageInstaller;
-
-        PackageInstallerWrapper(PackageInstaller packageInstaller) {
-            mPackageInstaller = packageInstaller;
-        }
-
-        void installExistingPackage(String packageName, int installReason,
-                IntentSender statusReceiver) {
-            mPackageInstaller.installExistingPackage(packageName, installReason, statusReceiver);
-        }
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/KioskKeepAlivePolicyHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/KioskKeepAlivePolicyHandler.java
new file mode 100644
index 0000000..71553e5
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/KioskKeepAlivePolicyHandler.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import android.os.OutcomeReceiver;
+
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+import com.android.devicelockcontroller.storage.SetupParametersClientInterface;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.concurrent.Executor;
+
+/** Handles kiosk app keep-alive. */
+public final class KioskKeepAlivePolicyHandler implements PolicyHandler {
+    private static final String TAG = "KioskKeepAlivePolicyHandler";
+
+    private final SystemDeviceLockManager mSystemDeviceLockManager;
+    private final SetupParametersClientInterface mSetupParametersClient;
+    private final Executor mBgExecutor;
+
+    KioskKeepAlivePolicyHandler(SystemDeviceLockManager systemDeviceLockManager,
+            Executor bgExecutor) {
+        mSystemDeviceLockManager = systemDeviceLockManager;
+        mBgExecutor = bgExecutor;
+        mSetupParametersClient = SetupParametersClient.getInstance();
+    }
+
+    private ListenableFuture<Boolean> getEnableKioskKeepAliveFuture(String packageName) {
+        return CallbackToFutureAdapter.getFuture(
+                completer -> {
+                    mSystemDeviceLockManager.enableKioskKeepalive(packageName,
+                            mBgExecutor,
+                            new OutcomeReceiver<>() {
+                                @Override
+                                public void onResult(Void result) {
+                                    completer.set(true);
+                                }
+
+                                @Override
+                                public void onError(Exception ex) {
+                                    // Return true since the keep-alive service is optional
+                                    LogUtil.d(TAG, "Failed to enable kiosk keep-alive", ex);
+                                    completer.set(true);
+                                }
+                            });
+                    // Used only for debugging.
+                    return "getEnableKioskKeepAliveFuture";
+                });
+    }
+
+    private ListenableFuture<Boolean> getEnableKioskKeepAliveFuture() {
+        return Futures.transformAsync(mSetupParametersClient.getKioskPackage(),
+                kioskPackageName -> kioskPackageName == null
+                        ? Futures.immediateFuture(false)
+                        : getEnableKioskKeepAliveFuture(kioskPackageName),
+                MoreExecutors.directExecutor());
+    }
+
+    private ListenableFuture<Boolean> getDisableKioskKeepAliveFuture() {
+        return CallbackToFutureAdapter.getFuture(
+                completer -> {
+                    mSystemDeviceLockManager.disableKioskKeepalive(mBgExecutor,
+                            new OutcomeReceiver<>() {
+                                @Override
+                                public void onResult(Void result) {
+                                    completer.set(true);
+                                }
+
+                                @Override
+                                public void onError(Exception ex) {
+                                    // Return true since the keep-alive service is optional
+                                    LogUtil.d(TAG, "Failed to disable kiosk keep-alive", ex);
+                                    completer.set(true);
+                                }
+                            });
+                    // Used only for debugging.
+                    return "getDisableKioskKeepAliveFuture";
+                });
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisioned() {
+        return getEnableKioskKeepAliveFuture();
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onCleared() {
+        return getDisableKioskKeepAliveFuture();
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/LockTaskModePolicyHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/LockTaskModePolicyHandler.java
index 6f8159a..adcd230 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/LockTaskModePolicyHandler.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/LockTaskModePolicyHandler.java
@@ -18,179 +18,183 @@
 
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
 
-import static com.android.devicelockcontroller.policy.DevicePolicyControllerImpl.START_LOCK_TASK_MODE_WORK_NAME;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.KIOSK_SETUP;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_FAILED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_IN_PROGRESS;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_SUCCEEDED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNPROVISIONED;
+import static com.android.devicelockcontroller.policy.StartLockTaskModeWorker.START_LOCK_TASK_MODE_WORK_NAME;
 
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.telecom.TelecomManager;
+import android.util.ArraySet;
 
-import androidx.annotation.VisibleForTesting;
 import androidx.work.WorkManager;
 
 import com.android.devicelockcontroller.R;
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
-import com.android.devicelockcontroller.storage.GlobalParametersClient;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.storage.UserParameters;
 import com.android.devicelockcontroller.util.LogUtil;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
+import java.util.Objects;
+import java.util.concurrent.Executor;
 
 /** Handles lock task mode features. */
 final class LockTaskModePolicyHandler implements PolicyHandler {
-    @VisibleForTesting
-    static final int DEFAULT_LOCK_TASK_FEATURES =
+    static final int DEFAULT_LOCK_TASK_FEATURES_FOR_DLC =
             (DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO
-             | DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD
-             | DevicePolicyManager.LOCK_TASK_FEATURE_HOME
-             | DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS
-             | DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK);
+                    | DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD
+                    | DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS
+                    | DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK);
+    static final int DEFAULT_LOCK_TASK_FEATURES_FOR_KIOSK =
+            DEFAULT_LOCK_TASK_FEATURES_FOR_DLC | DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
     private static final String TAG = "LockTaskModePolicyHandler";
     private final Context mContext;
     private final DevicePolicyManager mDpm;
+    private final Executor mBgExecutor;
+    private final UserManager mUserManager;
 
-    LockTaskModePolicyHandler(Context context, DevicePolicyManager dpm) {
+    LockTaskModePolicyHandler(Context context, DevicePolicyManager dpm, Executor bgExecutor) {
         mContext = context;
         mDpm = dpm;
-    }
-
-    private static IntentFilter getHomeIntentFilter() {
-        final IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
-        filter.addCategory(Intent.CATEGORY_HOME);
-        filter.addCategory(Intent.CATEGORY_DEFAULT);
-        return filter;
+        mBgExecutor = bgExecutor;
+        mUserManager = Objects.requireNonNull(mContext.getSystemService(UserManager.class));
     }
 
     @Override
-    @ResultType
-    public ListenableFuture<@ResultType Integer> setPolicyForState(@DeviceState int state) {
-        switch (state) {
-            case PSEUDO_UNLOCKED:
-            case PSEUDO_LOCKED:
-            case UNPROVISIONED:
-                return Futures.immediateFuture(SUCCESS);
-            case SETUP_FAILED:
-            case UNLOCKED:
-            case CLEARED:
-                return disableLockTaskMode();
-            case SETUP_IN_PROGRESS:
-            case SETUP_SUCCEEDED:
-            case KIOSK_SETUP:
-            case LOCKED:
-                return Futures.transformAsync(composeAllowlist(), empty -> enableLockTaskMode(),
-                        MoreExecutors.directExecutor());
-            default:
-                return Futures.immediateFailedFuture(
-                        new IllegalStateException(String.valueOf(state)));
-        }
+    public ListenableFuture<Boolean> onProvisionInProgress() {
+        return enableLockTaskModeSafely(/* forController= */ true);
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisioned() {
+        return enableLockTaskModeSafely(/* forController= */ false);
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisionPaused() {
+        return disableLockTaskMode();
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisionFailed() {
+        return disableLockTaskMode();
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onLocked() {
+        return enableLockTaskModeSafely(/* forController= */ false);
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onUnlocked() {
+        return disableLockTaskMode();
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onCleared() {
+        return disableLockTaskMode();
     }
 
     /**
-     * Sets the activity as the preferred activity for home intent. Activity is cleared when the
-     * device leaves lock task mode.
+     * Updates the allowlist for lock task mode
+     *
+     * @param includeKiosk true if the kiosk app and the kiosk-specified allowlist should be added
+     * @return future for when the lock task mode allowlist has been updated
      */
-    public boolean setPreferredActivityForHome(ComponentName activity) {
-        if (!mDpm.isLockTaskPermitted(activity.getPackageName())) {
-            LogUtil.e(TAG, String.format(Locale.US, "%s is not permitted in lock task mode",
-                    activity.getPackageName()));
-
-            return false;
-        }
-
-        final String currentPackage = UserParameters.getPackageOverridingHome(mContext);
-        if (currentPackage != null) {
-            mDpm.clearPackagePersistentPreferredActivities(null /* admin */, currentPackage);
-        }
-        mDpm.addPersistentPreferredActivity(null /* admin */, getHomeIntentFilter(), activity);
-        UserParameters.setPackageOverridingHome(mContext, activity.getPackageName());
-
-        return true;
-    }
-
-    private ListenableFuture<Void> updateAllowlist() {
-        return Futures.transform(GlobalParametersClient.getInstance().getLockTaskAllowlist(),
+    private ListenableFuture<Void> updateAllowlist(boolean includeKiosk) {
+        return Futures.transform(composeAllowlist(includeKiosk),
                 allowlist -> {
-                    if (allowlist.isEmpty()) {
-                        allowlist = new ArrayList<>(
-                                Arrays.asList(
-                                        mContext.getResources().getStringArray(
-                                                R.array.lock_task_allowlist)));
-                    }
-
-                    final TelecomManager telecomManager = mContext.getSystemService(
+                    TelecomManager telecomManager = mContext.getSystemService(
                             TelecomManager.class);
-                    final String defaultDialer = telecomManager.getDefaultDialerPackage();
+                    String defaultDialer = telecomManager.getDefaultDialerPackage();
                     if (defaultDialer != null && !allowlist.contains(defaultDialer)) {
                         LogUtil.i(TAG,
                                 String.format(Locale.US, "Adding default dialer %s to allowlist",
                                         defaultDialer));
                         allowlist.add(defaultDialer);
                     }
-                    final String[] allowlistPackages = allowlist.toArray(new String[0]);
+                    String[] allowlistPackages = allowlist.toArray(new String[0]);
                     mDpm.setLockTaskPackages(null /* admin */, allowlistPackages);
                     LogUtil.i(TAG, String.format(Locale.US, "Update Lock task allowlist %s",
                             Arrays.toString(allowlistPackages)));
                     return null;
-                }, mContext.getMainExecutor());
+                }, mBgExecutor);
     }
 
-    private @ResultType ListenableFuture<@ResultType Integer> enableLockTaskMode() {
+    /**
+     * Safely initiate Lock Task Mode
+     *
+     * @param forController Whether the Device Lock Controller itself (true) or the Kiosk (false)
+     *                      is in charge of this instance of Lock Task Mode
+     */
+    private ListenableFuture<Boolean> enableLockTaskModeSafely(boolean forController) {
+        // Disabling lock task mode before enabling it prevents vulnerabilities if another app
+        // has already initiated lock task mode
+        return Futures.transformAsync(disableLockTaskMode(),
+                unused -> {
+                    if (forController) {
+                        return enableLockTaskModeForController();
+                    }
+                    return enableLockTaskModeForKiosk();
+                }, mBgExecutor);
+    }
+
+    private ListenableFuture<Boolean> enableLockTaskModeForController() {
+        return Futures.transform(updateAllowlist(/* includeKiosk= */ false),
+                unused -> {
+                    mDpm.setLockTaskFeatures(/* admin= */ null, DEFAULT_LOCK_TASK_FEATURES_FOR_DLC);
+                    return true;
+                }, mBgExecutor);
+    }
+
+    private ListenableFuture<Boolean> enableLockTaskModeForKiosk() {
         ListenableFuture<Boolean> notificationsInLockTaskModeEnabled =
                 SetupParametersClient.getInstance().isNotificationsInLockTaskModeEnabled();
         return Futures.whenAllSucceed(
                         notificationsInLockTaskModeEnabled,
-                        updateAllowlist())
-                .call(
-                        () -> {
-                            int flags = DEFAULT_LOCK_TASK_FEATURES;
-                            if (Futures.getDone(notificationsInLockTaskModeEnabled)) {
-                                flags |= LOCK_TASK_FEATURE_NOTIFICATIONS;
-                            }
-                            mDpm.setLockTaskFeatures(null, flags);
-                            return SUCCESS;
-                        }, mContext.getMainExecutor());
+                        updateAllowlist(/* includeKiosk= */ true))
+                .call(() -> {
+                    int flags = DEFAULT_LOCK_TASK_FEATURES_FOR_KIOSK;
+                    if (Futures.getDone(notificationsInLockTaskModeEnabled)) {
+                        flags |= LOCK_TASK_FEATURE_NOTIFICATIONS;
+                    }
+                    mDpm.setLockTaskFeatures(/* admin= */ null, flags);
+                    return true;
+                }, mBgExecutor);
     }
 
-    private @ResultType ListenableFuture<@ResultType Integer> disableLockTaskMode() {
-        WorkManager.getInstance(mContext).cancelUniqueWork(START_LOCK_TASK_MODE_WORK_NAME);
-
-        final String currentPackage = UserParameters.getPackageOverridingHome(mContext);
-        // Device Policy Engine treats lock task features and packages as one policy and
-        // therefore we need to set both lock task features (to LOCK_TASK_FEATURE_NONE) and
-        // lock task packages (to an empty string array).
-        mDpm.setLockTaskFeatures(null /* admin */, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
-        // This will stop the lock task mode
-        mDpm.setLockTaskPackages(null /* admin */, new String[0]);
-        LogUtil.i(TAG, "Clear Lock task allowlist");
-        if (currentPackage != null) {
-            mDpm.clearPackagePersistentPreferredActivities(null /* admin */, currentPackage);
-            UserParameters.setPackageOverridingHome(mContext, null /* packageName */);
-        }
-        return Futures.immediateFuture(SUCCESS);
+    private ListenableFuture<Boolean> disableLockTaskMode() {
+        return Futures.submit(() -> {
+            if (mUserManager.isUserUnlocked()) {
+                WorkManager.getInstance(mContext).cancelUniqueWork(START_LOCK_TASK_MODE_WORK_NAME);
+            }
+            final String currentPackage = UserParameters.getPackageOverridingHome(mContext);
+            // Device Policy Engine treats lock task features and packages as one policy and
+            // therefore we need to set both lock task features (to LOCK_TASK_FEATURE_NONE) and
+            // lock task packages (to an empty string array).
+            mDpm.setLockTaskFeatures(null /* admin */, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
+            // This is a hacky workaround to stop the lock task mode by enforcing that no apps
+            // can be in lock task mode
+            // TODO(b/288886570): Fix this in the framework so we don't have to do this workaround
+            mDpm.setLockTaskPackages(null /* admin */, new String[]{""});
+            // This will remove the DLC policy and allow other admins to enforce their policy
+            mDpm.setLockTaskPackages(null /* admin */, new String[0]);
+            if (currentPackage != null) {
+                mDpm.clearPackagePersistentPreferredActivities(null /* admin */, currentPackage);
+                UserParameters.setPackageOverridingHome(mContext, null /* packageName */);
+            }
+            return true;
+        }, mBgExecutor);
     }
 
     /*
@@ -199,35 +203,35 @@
      *      required for essential services to work.
      *   2. Find the default app used as dialer (should be a System App).
      *   3. Find the default app used for Settings (should be a System App).
-     *   4. Find the default InputMethod.
-     *   4. Kiosk app
-     *   5. Append the packages allow-listed through setup parameters.
+     *   4. Find the default app used for permissions (should be a System App).
+     *   5. Find the default InputMethod.
+     *   6. Add the DLC app.
+     *   7. Append the kiosk and packages allow-listed through setup parameters if applicable.
      */
-    private ListenableFuture<Void> composeAllowlist() {
-        final String[] allowlistArray =
-                mContext.getResources().getStringArray(R.array.lock_task_allowlist);
-        final ArrayList<String> allowlistPackages = new ArrayList<>(Arrays.asList(allowlistArray));
-        allowlistSystemAppForAction(Intent.ACTION_DIAL, allowlistPackages);
-        allowlistSystemAppForAction(Settings.ACTION_SETTINGS, allowlistPackages);
-        allowlistInputMethod(allowlistPackages);
-        allowlistCellBroadcastReceiver(allowlistPackages);
-        final ListenableFuture<String> kioskPackageTask =
-                SetupParametersClient.getInstance().getKioskPackage();
-        final ListenableFuture<List<String>> kioskAllowlistTask =
-                SetupParametersClient.getInstance().getKioskAllowlist();
-        return Futures.transformAsync(
-                Futures.whenAllSucceed(kioskPackageTask, kioskAllowlistTask).call(
-                        () -> {
-                            allowlistPackages.add(Futures.getDone(kioskPackageTask));
-                            allowlistPackages.addAll(Futures.getDone(kioskAllowlistTask));
-                            return allowlistPackages;
-                        }, mContext.getMainExecutor()),
-                packagesList ->
-                        GlobalParametersClient.getInstance().setLockTaskAllowlist(packagesList),
-                mContext.getMainExecutor());
+    private ListenableFuture<ArraySet<String>> composeAllowlist(boolean includeKiosk) {
+        return Futures.submit(() -> {
+            String[] allowlistArray =
+                    mContext.getResources().getStringArray(R.array.lock_task_allowlist);
+            ArraySet<String> allowlistPackages = new ArraySet<>(allowlistArray);
+            allowlistSystemAppForAction(Intent.ACTION_DIAL, allowlistPackages);
+            allowlistSystemAppForAction(Settings.ACTION_SETTINGS, allowlistPackages);
+            allowlistSystemAppForAction(PackageManager.ACTION_REQUEST_PERMISSIONS,
+                    allowlistPackages);
+            allowlistInputMethod(allowlistPackages);
+            allowlistCellBroadcastReceiver(allowlistPackages);
+            allowlistPackages.add(mContext.getPackageName());
+            if (includeKiosk) {
+                SetupParametersClient setupParametersClient = SetupParametersClient.getInstance();
+                allowlistPackages.add(
+                        Futures.getUnchecked(setupParametersClient.getKioskPackage()));
+                allowlistPackages.addAll(
+                        Futures.getUnchecked(setupParametersClient.getKioskAllowlist()));
+            }
+            return allowlistPackages;
+        }, mBgExecutor);
     }
 
-    private void allowlistSystemAppForAction(String action, List<String> allowlistPackages) {
+    private void allowlistSystemAppForAction(String action, ArraySet<String> allowlistPackages) {
         final PackageManager pm = mContext.getPackageManager();
         final Intent intent = new Intent(action);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
@@ -244,7 +248,7 @@
         allowlistPackages.add(packageName);
     }
 
-    private void allowlistInputMethod(List<String> allowlistPackages) {
+    private void allowlistInputMethod(ArraySet<String> allowlistPackages) {
         final String defaultIme = Secure.getString(mContext.getContentResolver(),
                 Secure.DEFAULT_INPUT_METHOD);
         if (defaultIme == null) {
@@ -262,7 +266,7 @@
         allowlistPackages.add(imeComponent.getPackageName());
     }
 
-    private void allowlistCellBroadcastReceiver(List<String> allowlistPackages) {
+    private void allowlistCellBroadcastReceiver(ArraySet<String> allowlistPackages) {
         final String packageName =
                 CellBroadcastUtils.getDefaultCellBroadcastReceiverPackageName(mContext);
         if (packageName == null) {
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/NotificationsPolicyHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/NotificationsPolicyHandler.java
new file mode 100644
index 0000000..775e102
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/NotificationsPolicyHandler.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.devicelockcontroller.policy;
+
+import android.os.OutcomeReceiver;
+
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.concurrent.Executor;
+
+/** Handles setting POST_NOTIFICATIONS as SYSTEM_FIXED. */
+public final class NotificationsPolicyHandler implements PolicyHandler {
+    private static final String TAG = "NotificationsPolicyHandler";
+
+    private final SystemDeviceLockManager mSystemDeviceLockManager;
+    private final Executor mBgExecutor;
+
+    NotificationsPolicyHandler(SystemDeviceLockManager systemDeviceLockManager,
+            Executor bgExecutor) {
+        mSystemDeviceLockManager = systemDeviceLockManager;
+        mBgExecutor = bgExecutor;
+    }
+
+    private ListenableFuture<Boolean> setPostNotificationsSystemFixedFuture(boolean systemFixed) {
+        return CallbackToFutureAdapter.getFuture(
+                completer -> {
+                    mSystemDeviceLockManager.setPostNotificationsSystemFixed(
+                            systemFixed,
+                            mBgExecutor,
+                            new OutcomeReceiver<>() {
+                                @Override
+                                public void onResult(Void result) {
+                                    completer.set(true);
+                                }
+
+                                @Override
+                                public void onError(Exception ex) {
+                                    LogUtil.e(TAG, "Failed to set POST_NOTIFICATIONS system fixed "
+                                            + "flag to: " + systemFixed, ex);
+                                    // Return true since we don't want to fail the transition
+                                    completer.set(true);
+                                }
+                            });
+                    // Used only for debugging.
+                    return "setPostNotificationsSystemFixedFuture";
+                });
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onProvisionInProgress() {
+        return setPostNotificationsSystemFixedFuture(/* systemFixed= */ true);
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onCleared() {
+        return setPostNotificationsSystemFixedFuture(/* systemFixed= */ false);
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/PackagePolicyHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/PackagePolicyHandler.java
index 39afc29..97db153 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/PackagePolicyHandler.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/PackagePolicyHandler.java
@@ -16,30 +16,18 @@
 
 package com.android.devicelockcontroller.policy;
 
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.KIOSK_SETUP;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_FAILED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_IN_PROGRESS;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_SUCCEEDED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNPROVISIONED;
-
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.util.LogUtil;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /** Enforces restrictions on Kiosk app and controller. */
 final class PackagePolicyHandler implements PolicyHandler {
@@ -47,47 +35,36 @@
 
     private final Context mContext;
     private final DevicePolicyManager mDpm;
+    private final Executor mBgExecutor;
 
-    PackagePolicyHandler(Context context, DevicePolicyManager dpm) {
+    PackagePolicyHandler(Context context, DevicePolicyManager dpm, Executor bgExecutor) {
         mContext = context;
         mDpm = dpm;
+        mBgExecutor = bgExecutor;
     }
 
     @Override
-    public ListenableFuture<@ResultType Integer> setPolicyForState(@DeviceState int state) {
-        switch (state) {
-            case KIOSK_SETUP:
-            case UNLOCKED:
-            case LOCKED:
-                return enablePackageProtection(true /* enableForKiosk */, state);
-            case CLEARED:
-            case UNPROVISIONED:
-                return enablePackageProtection(false /* enableForKiosk */, state);
-            case SETUP_IN_PROGRESS:
-            case SETUP_SUCCEEDED:
-            case SETUP_FAILED:
-            case PSEUDO_LOCKED:
-            case PSEUDO_UNLOCKED:
-                return Futures.immediateFuture(SUCCESS);
-            default:
-                return Futures.immediateFailedFuture(
-                        new IllegalStateException(String.valueOf(state)));
-        }
+    public ListenableFuture<Boolean> onProvisioned() {
+        return enablePackageProtection(/* enableForKiosk= */ true);
     }
 
-    private ListenableFuture<@ResultType Integer> enablePackageProtection(boolean enableForKiosk,
-            @DeviceState int state) {
+    @Override
+    public ListenableFuture<Boolean> onCleared() {
+        return enablePackageProtection(/* enableForKiosk= */ false);
+    }
+
+    private ListenableFuture<Boolean> enablePackageProtection(boolean enableForKiosk) {
         return Futures.transform(SetupParametersClient.getInstance().getKioskPackage(),
                 kioskPackageName -> {
                     if (kioskPackageName == null) {
-                        LogUtil.d(TAG, "Kiosk package is not set for state: " + state);
+                        LogUtil.d(TAG, "Kiosk package is not set");
                     } else {
                         try {
                             mDpm.setUninstallBlocked(null /* admin */, kioskPackageName,
                                     enableForKiosk);
                         } catch (SecurityException e) {
                             LogUtil.e(TAG, "Unable to set device policy", e);
-                            return FAILURE;
+                            return false;
                         }
                     }
 
@@ -104,10 +81,10 @@
                         mDpm.setUserControlDisabledPackages(null /* admin */, pkgList);
                     } catch (SecurityException e) {
                         LogUtil.e(TAG, "Failed to setUserControlDisabledPackages", e);
-                        return FAILURE;
+                        return false;
                     }
 
-                    return SUCCESS;
-                }, MoreExecutors.directExecutor());
+                    return true;
+                }, mBgExecutor);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyHandler.java
index 27f4aad..15ce64b 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyHandler.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyHandler.java
@@ -16,35 +16,39 @@
 
 package com.android.devicelockcontroller.policy;
 
-import androidx.annotation.IntDef;
-
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
-
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
 /**
- * Interface used for setting policies for a given state.
+ * A PolicyHandler class is responsible for setting certain policy for a certain state.
  */
-public interface PolicyHandler {
-    /** Result Type for operation */
-    @Target(ElementType.TYPE_USE)
-    @IntDef(value = {SUCCESS, FAILURE})
-    @Retention(RetentionPolicy.SOURCE)
-    @interface ResultType {
+interface PolicyHandler {
+
+    default ListenableFuture<Boolean> onProvisioned() {
+        return Futures.immediateFuture(true);
     }
 
-    int SUCCESS = 0;
-    int FAILURE = 1;
+    default ListenableFuture<Boolean> onProvisionInProgress() {
+        return Futures.immediateFuture(true);
+    }
 
-    /**
-     * Sets the policy state based on the new state. Throws SecurityException when the app is not
-     * privileged.
-     */
-    @ResultType
-    ListenableFuture<@ResultType Integer> setPolicyForState(@DeviceState int state);
+    default ListenableFuture<Boolean> onProvisionPaused() {
+        return Futures.immediateFuture(true);
+    }
+
+    default ListenableFuture<Boolean> onProvisionFailed() {
+        return Futures.immediateFuture(true);
+    }
+
+    default ListenableFuture<Boolean> onLocked() {
+        return Futures.immediateFuture(true);
+    }
+
+    default ListenableFuture<Boolean> onUnlocked() {
+        return Futures.immediateFuture(true);
+    }
+
+    default ListenableFuture<Boolean> onCleared() {
+        return Futures.immediateFuture(true);
+    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyObjectsInterface.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyObjectsProvider.java
similarity index 73%
rename from DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyObjectsInterface.java
rename to DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyObjectsProvider.java
index 5757409..bf11152 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyObjectsInterface.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/PolicyObjectsProvider.java
@@ -19,15 +19,18 @@
 /**
  * Interface to retrieve singleton objects.
  */
-public interface PolicyObjectsInterface {
+public interface PolicyObjectsProvider {
     /** Returns an instance of DeviceStateController. */
-    DeviceStateController getStateController();
+    DeviceStateController getDeviceStateController();
+
+    /** Returns an instance of ProvisionStateController. */
+    ProvisionStateController getProvisionStateController();
 
     /** Returns an instance of DevicePolicyController. */
     DevicePolicyController getPolicyController();
 
-    /** Returns an instance of SetupController. */
-    SetupController getSetupController();
+    /** Returns an instance of {@link FinalizationController}. */
+    FinalizationController getFinalizationController();
 
     /** Destroy all the singleton objects */
     void destroyObjects();
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionHelper.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionHelper.java
new file mode 100644
index 0000000..3d51559
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionHelper.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import androidx.lifecycle.LifecycleOwner;
+
+import com.android.devicelockcontroller.activities.ProvisioningProgressController;
+
+/**
+ * A helper class provides helper functions for certain provision business logic.
+ * Any blocking works should be executed on background thread as the APIs in this class are mostly
+ * used by UI components ane running on the main thread.
+ */
+public interface ProvisionHelper {
+    /** Pause the provision and schedule the resume. */
+    void pauseProvision();
+
+    /**
+     * Start installation and open kiosk when it finish.
+     */
+    void scheduleKioskAppInstallation(LifecycleOwner owner,
+            ProvisioningProgressController progressController,
+            boolean isProvisionMandatory);
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionHelperImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionHelperImpl.java
new file mode 100644
index 0000000..dcc00cf
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionHelperImpl.java
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static androidx.work.WorkInfo.State.FAILED;
+import static androidx.work.WorkInfo.State.SUCCEEDED;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_KIOSK;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_PAUSE;
+import static com.android.devicelockcontroller.provision.worker.IsDeviceInApprovedCountryWorker.BACKOFF_DELAY;
+import static com.android.devicelockcontroller.provision.worker.IsDeviceInApprovedCountryWorker.KEY_IS_IN_APPROVED_COUNTRY;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.sqlite.SQLiteException;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.work.BackoffPolicy;
+import androidx.work.Constraints;
+import androidx.work.Data;
+import androidx.work.ExistingWorkPolicy;
+import androidx.work.ListenableWorker;
+import androidx.work.NetworkType;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.Operation;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+
+import com.android.devicelockcontroller.PlayInstallPackageTaskClassProvider;
+import com.android.devicelockcontroller.activities.DeviceLockNotificationManager;
+import com.android.devicelockcontroller.activities.ProvisioningProgress;
+import com.android.devicelockcontroller.activities.ProvisioningProgressController;
+import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason;
+import com.android.devicelockcontroller.provision.worker.IsDeviceInApprovedCountryWorker;
+import com.android.devicelockcontroller.provision.worker.PauseProvisioningWorker;
+import com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker;
+import com.android.devicelockcontroller.receivers.ResumeProvisionReceiver;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.time.LocalDateTime;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * An implementation of {@link ProvisionHelper}.
+ */
+public final class ProvisionHelperImpl implements ProvisionHelper {
+    private static final String TAG = "ProvisionHelperImpl";
+    private static final String FILENAME = "device-lock-controller-provisioning-preferences";
+    private static final String USE_PREINSTALLED_KIOSK_PREF =
+            "debug.devicelock.usepreinstalledkiosk";
+    private static volatile SharedPreferences sSharedPreferences;
+
+    @VisibleForTesting
+    static synchronized SharedPreferences getSharedPreferences(Context context) {
+        if (sSharedPreferences == null) {
+            sSharedPreferences = context.createDeviceProtectedStorageContext().getSharedPreferences(
+                    FILENAME, Context.MODE_PRIVATE);
+        }
+        return sSharedPreferences;
+    }
+
+    private final Context mContext;
+    private final ProvisionStateController mStateController;
+    private final Executor mExecutor;
+    private final DeviceLockControllerScheduler mScheduler;
+
+    public ProvisionHelperImpl(Context context, ProvisionStateController stateController) {
+        this(context, stateController, Executors.newCachedThreadPool());
+    }
+
+    @VisibleForTesting
+    ProvisionHelperImpl(Context context, ProvisionStateController stateController,
+            Executor executor) {
+        mContext = context;
+        mStateController = stateController;
+        DeviceLockControllerSchedulerProvider schedulerProvider =
+                (DeviceLockControllerSchedulerProvider) mContext.getApplicationContext();
+        mScheduler = schedulerProvider.getDeviceLockControllerScheduler();
+        mExecutor = executor;
+    }
+
+    @Override
+    public void pauseProvision() {
+        Futures.addCallback(Futures.transformAsync(
+                        GlobalParametersClient.getInstance().setProvisionForced(true),
+                        unused -> mStateController.setNextStateForEvent(PROVISION_PAUSE),
+                        mExecutor),
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Void unused) {
+                        createNotification();
+                        WorkManager workManager = WorkManager.getInstance(mContext);
+                        PauseProvisioningWorker.reportProvisionPausedByUser(workManager);
+                        mScheduler.scheduleResumeProvisionAlarm();
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        throw new RuntimeException("Failed to delay setup", t);
+                    }
+                }, mExecutor);
+    }
+
+    @Override
+    public void scheduleKioskAppInstallation(LifecycleOwner owner,
+            ProvisioningProgressController progressController, boolean isMandatory) {
+        LogUtil.v(TAG, "Schedule installation work");
+        progressController.setProvisioningProgress(ProvisioningProgress.GETTING_DEVICE_READY);
+        WorkManager workManager = WorkManager.getInstance(mContext);
+        OneTimeWorkRequest isDeviceInApprovedCountryWork = getIsDeviceInApprovedCountryWork();
+
+        final ListenableFuture<Operation.State.SUCCESS> enqueueResult =
+                workManager.enqueueUniqueWork(IsDeviceInApprovedCountryWorker.class.getSimpleName(),
+                ExistingWorkPolicy.REPLACE, isDeviceInApprovedCountryWork).getResult();
+        Futures.addCallback(enqueueResult, new FutureCallback<Operation.State.SUCCESS>() {
+                    @Override
+                    public void onSuccess(Operation.State.SUCCESS result) {
+                        // Enqueued
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        LogUtil.e(TAG, "Failed to enqueue 'device in approved country' work",
+                                t);
+                        if (t instanceof SQLiteException) {
+                            mStateController.getDevicePolicyController().wipeDevice();
+                        } else {
+                            LogUtil.e(TAG, "Not wiping device (non SQL exception)");
+                        }
+                    }
+                }, mExecutor);
+
+        FutureCallback<String> isInApprovedCountryCallback = new FutureCallback<>() {
+            @Override
+            public void onSuccess(String kioskPackage) {
+                progressController.setProvisioningProgress(
+                        ProvisioningProgress.INSTALLING_KIOSK_APP);
+                if (getPreinstalledKioskAllowed(mContext)) {
+                    try {
+                        mContext.getPackageManager().getPackageInfo(kioskPackage,
+                                ApplicationInfo.FLAG_INSTALLED);
+                        LogUtil.i(TAG, "Kiosk app is pre-installed");
+                        progressController.setProvisioningProgress(
+                                ProvisioningProgress.OPENING_KIOSK_APP);
+                        ReportDeviceProvisionStateWorker.reportSetupCompleted(workManager);
+                        mStateController.postSetNextStateForEventRequest(PROVISION_KIOSK);
+                    } catch (NameNotFoundException e) {
+                        LogUtil.i(TAG, "Kiosk app is not pre-installed");
+                        installFromPlay(owner, kioskPackage, isMandatory, progressController);
+                    }
+                } else {
+                    installFromPlay(owner, kioskPackage, isMandatory, progressController);
+                }
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LogUtil.w(TAG, "Failed to install kiosk app!", t);
+                handleFailure(ProvisionFailureReason.PLAY_INSTALLATION_FAILED, isMandatory,
+                        progressController);
+            }
+        };
+
+        workManager.getWorkInfoByIdLiveData(isDeviceInApprovedCountryWork.getId())
+                .observe(owner, workInfo -> {
+                    if (workInfo == null) return;
+                    WorkInfo.State state = workInfo.getState();
+                    LogUtil.d(TAG, "WorkInfo changed: " + workInfo);
+                    if (state == SUCCEEDED) {
+                        if (workInfo.getOutputData().getBoolean(KEY_IS_IN_APPROVED_COUNTRY,
+                                false)) {
+                            Futures.addCallback(
+                                    SetupParametersClient.getInstance().getKioskPackage(),
+                                    isInApprovedCountryCallback, mExecutor);
+                        } else {
+                            LogUtil.i(TAG, "Not in eligible country");
+                            handleFailure(ProvisionFailureReason.NOT_IN_ELIGIBLE_COUNTRY,
+                                    isMandatory, progressController);
+                        }
+                    } else if (state == FAILED) {
+                        LogUtil.w(TAG, "Failed to get country eligibility!");
+                        handleFailure(ProvisionFailureReason.COUNTRY_INFO_UNAVAILABLE, isMandatory,
+                                progressController);
+                    }
+                });
+    }
+
+    private void installFromPlay(LifecycleOwner owner, String kioskPackage, boolean isMandatory,
+            ProvisioningProgressController progressController) {
+        Context applicationContext = mContext.getApplicationContext();
+        final Class<? extends ListenableWorker> playInstallTaskClass =
+                ((PlayInstallPackageTaskClassProvider) applicationContext)
+                        .getPlayInstallPackageTaskClass();
+        if (playInstallTaskClass == null) {
+            LogUtil.w(TAG, "Play installation not supported!");
+            handleFailure(
+                    ProvisionFailureReason.PLAY_TASK_UNAVAILABLE, isMandatory, progressController);
+            return;
+        }
+        OneTimeWorkRequest playInstallPackageTask =
+                getPlayInstallPackageTask(playInstallTaskClass, kioskPackage);
+        WorkManager workManager = WorkManager.getInstance(mContext);
+        final ListenableFuture<Operation.State.SUCCESS> enqueueResult =
+                workManager.enqueueUniqueWork(playInstallTaskClass.getSimpleName(),
+                        ExistingWorkPolicy.REPLACE, playInstallPackageTask).getResult();
+        Futures.addCallback(enqueueResult, new FutureCallback<Operation.State.SUCCESS>() {
+            @Override
+            public void onSuccess(Operation.State.SUCCESS result) {
+                // Enqueued
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LogUtil.e(TAG, "Failed to enqueue 'play install' work", t);
+                if (t instanceof SQLiteException) {
+                    mStateController.getDevicePolicyController().wipeDevice();
+                } else {
+                    LogUtil.e(TAG, "Not wiping device (non SQL exception)");
+                }
+            }
+        }, mExecutor);
+
+        mContext.getMainExecutor().execute(
+                () -> workManager.getWorkInfoByIdLiveData(playInstallPackageTask.getId())
+                        .observe(owner, workInfo -> {
+                            if (workInfo == null) return;
+                            WorkInfo.State state = workInfo.getState();
+                            LogUtil.d(TAG, "WorkInfo changed: " + workInfo);
+                            if (state == SUCCEEDED) {
+                                progressController.setProvisioningProgress(
+                                        ProvisioningProgress.OPENING_KIOSK_APP);
+                                ReportDeviceProvisionStateWorker.reportSetupCompleted(workManager);
+                                mStateController.postSetNextStateForEventRequest(PROVISION_KIOSK);
+                            } else if (state == FAILED) {
+                                LogUtil.w(TAG, "Play installation failed!");
+                                handleFailure(ProvisionFailureReason.PLAY_INSTALLATION_FAILED,
+                                        isMandatory, progressController);
+                            }
+                        }));
+    }
+
+    private void handleFailure(@ProvisionFailureReason int reason, boolean isMandatory,
+            ProvisioningProgressController progressController) {
+        StatsLogger logger =
+                ((StatsLoggerProvider) mContext.getApplicationContext()).getStatsLogger();
+        switch (reason) {
+            case ProvisionFailureReason.PLAY_TASK_UNAVAILABLE -> {
+                logger.logProvisionFailure(
+                        StatsLogger.ProvisionFailureReasonStats.PLAY_TASK_UNAVAILABLE);
+            }
+            case ProvisionFailureReason.PLAY_INSTALLATION_FAILED -> {
+                logger.logProvisionFailure(
+                        StatsLogger.ProvisionFailureReasonStats.PLAY_INSTALLATION_FAILED);
+            }
+            case ProvisionFailureReason.COUNTRY_INFO_UNAVAILABLE -> {
+                logger.logProvisionFailure(
+                        StatsLogger.ProvisionFailureReasonStats.COUNTRY_INFO_UNAVAILABLE);
+            }
+            case ProvisionFailureReason.NOT_IN_ELIGIBLE_COUNTRY -> {
+                logger.logProvisionFailure(
+                        StatsLogger.ProvisionFailureReasonStats.NOT_IN_ELIGIBLE_COUNTRY);
+            }
+            case ProvisionFailureReason.POLICY_ENFORCEMENT_FAILED -> {
+                logger.logProvisionFailure(
+                        StatsLogger.ProvisionFailureReasonStats.POLICY_ENFORCEMENT_FAILED);
+            }
+            default -> {
+                logger.logProvisionFailure(StatsLogger.ProvisionFailureReasonStats.UNKNOWN);
+            }
+        }
+        if (isMandatory) {
+            ReportDeviceProvisionStateWorker.reportSetupFailed(
+                    WorkManager.getInstance(mContext), reason);
+            progressController.setProvisioningProgress(
+                    ProvisioningProgress.getMandatoryProvisioningFailedProgress(reason));
+            mScheduler.scheduleMandatoryResetDeviceAlarm();
+        } else {
+            // For non-mandatory provisioning, failure should only be reported after
+            // user exits the provisioning UI; otherwise, it could be reported
+            // multiple times if user choose to retry, which can break the
+            // 7-days failure flow.
+            progressController.setProvisioningProgress(
+                    ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(reason));
+        }
+    }
+
+    @NonNull
+    private static OneTimeWorkRequest getIsDeviceInApprovedCountryWork() {
+        return new OneTimeWorkRequest.Builder(IsDeviceInApprovedCountryWorker.class)
+                .setConstraints(new Constraints.Builder().setRequiredNetworkType(
+                        NetworkType.CONNECTED).build())
+                .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, BACKOFF_DELAY)
+                .build();
+    }
+
+    @NonNull
+    private static OneTimeWorkRequest getPlayInstallPackageTask(
+            Class<? extends ListenableWorker> playInstallTaskClass, String kioskPackageName) {
+        return new OneTimeWorkRequest.Builder(playInstallTaskClass)
+                .setInputData(new Data.Builder().putString(
+                        EXTRA_KIOSK_PACKAGE, kioskPackageName).build())
+                .setConstraints(new Constraints.Builder().setRequiredNetworkType(
+                        NetworkType.CONNECTED).build())
+                .build();
+    }
+
+    private void createNotification() {
+        LogUtil.d(TAG, "createNotification");
+        Context context = mContext;
+
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
+                /* requestCode= */ 0, new Intent(context, ResumeProvisionReceiver.class),
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
+        LocalDateTime resumeDateTime = LocalDateTime.now().plusHours(1);
+        DeviceLockNotificationManager.sendDeferredProvisioningNotification(context, resumeDateTime,
+                pendingIntent);
+    }
+
+    /**
+     * Sets whether provisioning should skip play install if there is already a preinstalled kiosk
+     * app.
+     */
+    public static void setPreinstalledKioskAllowed(Context context, boolean enabled) {
+        getSharedPreferences(context).edit().putBoolean(USE_PREINSTALLED_KIOSK_PREF, enabled)
+                .apply();
+    }
+
+    /**
+     * Returns true if provisioning should skip play install if there is already a preinstalled
+     * kiosk app. By default, this returns true for debuggable build.
+     */
+    private static boolean getPreinstalledKioskAllowed(Context context) {
+        return Build.isDebuggable() && getSharedPreferences(context).getBoolean(
+                USE_PREINSTALLED_KIOSK_PREF, Build.isDebuggable());
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionStateController.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionStateController.java
new file mode 100644
index 0000000..14f4698
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionStateController.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import androidx.annotation.IntDef;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Interface for the provision flow state machine.
+ * Different user may have different provision states.
+ */
+public interface ProvisionStateController {
+
+    /**
+     * Returns the latest state of the provision.
+     *
+     * @return A {@link ListenableFuture} that will complete when pre-existing state changes, if
+     * any, are done. The result is the latest provision state.
+     */
+    ListenableFuture<@ProvisionState Integer> getState();
+
+    /**
+     * A convenience method that calls {@link this#setNextStateForEvent} for callers that does not
+     * need to know the result.
+     *
+     * @param event A {@link ProvisionEvent} that is used to identify the next state to move.
+     */
+    void postSetNextStateForEventRequest(@ProvisionEvent int event);
+
+    /**
+     * Move to next {@link ProvisionState} based on the input event {@link ProvisionEvent}.
+     *
+     * @param event A {@link ProvisionEvent} that is used to identify the next state to move.
+     * @return A {@link ListenableFuture} that will complete when both the state change and policies
+     * enforcement for next state are done. The result is the new state.
+     */
+    ListenableFuture<Void> setNextStateForEvent(@ProvisionEvent int event);
+
+    /**
+     * Notify that the device is ready for provisioning.
+     */
+    void notifyProvisioningReady();
+
+    /** Get the instance for {@link DeviceStateController} */
+    DeviceStateController getDeviceStateController();
+
+    /** Get the instance for {@link DevicePolicyController} */
+    DevicePolicyController getDevicePolicyController();
+
+    /**
+     * Called after user has unlocked to trigger provision or enforce policies.
+     */
+    ListenableFuture<Void> onUserUnlocked();
+
+    /**
+     * Called when a user has completed set-up wizard.
+     */
+    ListenableFuture<Void> onUserSetupCompleted();
+
+    /**
+     * State definitions related to provisioning flow.
+     */
+    @Target(ElementType.TYPE_USE)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            ProvisionState.UNPROVISIONED,
+            ProvisionState.PROVISION_IN_PROGRESS,
+            ProvisionState.PROVISION_SUCCEEDED,
+            ProvisionState.PROVISION_PAUSED,
+            ProvisionState.PROVISION_FAILED,
+            ProvisionState.KIOSK_PROVISIONED,
+    })
+    @interface ProvisionState {
+
+        /* Not provisioned */
+        int UNPROVISIONED = 0;
+
+        /* Provisioning flow is in progress. This is where kiosk app will be installed. */
+        int PROVISION_IN_PROGRESS = 1;
+
+        /* Provisioning is paused */
+        int PROVISION_PAUSED = 2;
+
+        /* Kiosk app provisioned */
+        int KIOSK_PROVISIONED = 3;
+
+        /* Provisioning has succeeded */
+        int PROVISION_SUCCEEDED = 4;
+
+        /* Provisioning has failed */
+        int PROVISION_FAILED = 5;
+    }
+
+    /**
+     * Provision event definitions
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            ProvisionEvent.PROVISION_READY,
+            ProvisionEvent.PROVISION_PAUSE,
+            ProvisionEvent.PROVISION_SUCCESS,
+            ProvisionEvent.PROVISION_FAILURE,
+            ProvisionEvent.PROVISION_KIOSK,
+            ProvisionEvent.PROVISION_RESUME,
+            ProvisionEvent.PROVISION_RETRY,
+    })
+    @interface ProvisionEvent {
+
+        /* Ready for provisioning */
+        int PROVISION_READY = 0;
+
+        /* Pause provisioning */
+        int PROVISION_PAUSE = 1;
+
+        /* Provisioning completed successfully */
+        int PROVISION_SUCCESS = 2;
+
+        /* Provisioning failed to complete */
+        int PROVISION_FAILURE = 3;
+
+        /* Provision Kiosk app */
+        int PROVISION_KIOSK = 4;
+
+        /* Resume provisioning */
+        int PROVISION_RESUME = 5;
+
+        /* Retry provision after failure */
+        int PROVISION_RETRY = 6;
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionStateControllerImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionStateControllerImpl.java
new file mode 100644
index 0000000..4618895
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/ProvisionStateControllerImpl.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_FAILURE;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_KIOSK;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_PAUSE;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_READY;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_RESUME;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_RETRY;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_SUCCESS;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.KIOSK_PROVISIONED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_FAILED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_IN_PROGRESS;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_PAUSED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.devicelockcontroller.SystemDeviceLockManagerImpl;
+import com.android.devicelockcontroller.receivers.LockedBootCompletedReceiver;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.UserParameters;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * An implementation of the {@link ProvisionStateController}. This class guarantees thread safety
+ * by synchronizing read/write operations of the state value on background threads in the order of
+ * when the API calls happen. That is, a pre-exist state value read/write operation will always
+ * block an incoming read/write request until the former completes.
+ */
+public final class ProvisionStateControllerImpl implements ProvisionStateController {
+
+    public static final String TAG = "ProvisionStateControllerImpl";
+    private final Context mContext;
+    private final DevicePolicyController mPolicyController;
+    private final DeviceStateController mDeviceStateController;
+    private final Executor mBgExecutor;
+
+    @GuardedBy("this")
+    private ListenableFuture<@ProvisionState Integer> mCurrentStateFuture;
+
+    public ProvisionStateControllerImpl(Context context) {
+        mContext = context;
+        mBgExecutor = Executors.newCachedThreadPool();
+        mPolicyController =
+                new DevicePolicyControllerImpl(context,
+                        context.getSystemService(DevicePolicyManager.class),
+                        context.getSystemService(UserManager.class),
+                        SystemDeviceLockManagerImpl.getInstance(),
+                        this,
+                        mBgExecutor);
+        mDeviceStateController = new DeviceStateControllerImpl(mPolicyController, this,
+                mBgExecutor);
+    }
+
+    @VisibleForTesting
+    ProvisionStateControllerImpl(Context context, DevicePolicyController policyController,
+            DeviceStateController stateController, Executor bgExecutor) {
+        mContext = context;
+        mPolicyController = policyController;
+        mDeviceStateController = stateController;
+        mBgExecutor = bgExecutor;
+    }
+
+    @Override
+    public ListenableFuture<@ProvisionState Integer> getState() {
+        synchronized (this) {
+            if (mCurrentStateFuture == null) {
+                mCurrentStateFuture = Futures.submit(
+                        () -> UserParameters.getProvisionState(mContext),
+                        mBgExecutor);
+            }
+            return mCurrentStateFuture;
+        }
+    }
+
+    @Override
+    public void postSetNextStateForEventRequest(@ProvisionEvent int event) {
+        Futures.addCallback(setNextStateForEvent(event),
+                getFutureCallback("Set state for event: " + event),
+                MoreExecutors.directExecutor());
+    }
+
+    @Override
+    public ListenableFuture<Void> setNextStateForEvent(@ProvisionEvent int event) {
+        synchronized (this) {
+            // getState() must be called here and assigned to a local variable, otherwise, if
+            // retrieved down the execution flow, it will be returning the new state after
+            // execution.
+            ListenableFuture<@ProvisionState Integer> currentStateFuture = getState();
+            ListenableFuture<@ProvisionState Integer> stateTransitionFuture =
+                    Futures.transform(
+                            currentStateFuture,
+                            currentState -> {
+                                int newState = getNextState(currentState, event);
+                                UserParameters.setProvisionState(mContext, newState);
+                                handleNewState(newState);
+                                // We treat when the event is PROVISION_READY as the start of the
+                                // provisioning time.
+                                if (PROVISION_READY == event) {
+                                    UserParameters.setProvisioningStartTimeMillis(mContext,
+                                            SystemClock.elapsedRealtime());
+                                }
+                                if (PROVISION_SUCCESS == event) {
+                                    ((StatsLoggerProvider) mContext.getApplicationContext())
+                                            .getStatsLogger().logSuccessfulProvisioning();
+                                }
+                                return newState;
+                            }, mBgExecutor);
+            // To prevent exception propagate to future state transitions, catch any exceptions
+            // that might happen during the execution and fallback to previous state if exception
+            // happens.
+            mCurrentStateFuture = Futures.catchingAsync(stateTransitionFuture, Exception.class,
+                    input -> currentStateFuture, mBgExecutor);
+            return Futures.transformAsync(stateTransitionFuture,
+                    newState -> Futures.catchingAsync(mPolicyController.enforceCurrentPolicies(),
+                            Exception.class, ex -> {
+                                // Policy enforcement failed, try to restore previous policies and
+                                // report critical error.
+                                synchronized (this) {
+                                    mCurrentStateFuture = currentStateFuture;
+                                    LogUtil.e(TAG, "Enforcement failed so restoring previous state "
+                                            + currentStateFuture, ex);
+                                }
+                                return Futures.transformAsync(mPolicyController
+                                                .enforceCurrentPoliciesForCriticalFailure(),
+                                        unused -> Futures.immediateFailedFuture(ex),
+                                        mBgExecutor);
+                            }, mBgExecutor),
+                    mBgExecutor);
+        }
+    }
+
+    @Override
+    public void notifyProvisioningReady() {
+        if (isUserSetupComplete()) {
+            postSetNextStateForEventRequest(PROVISION_READY);
+        }
+    }
+
+    @NonNull
+    private FutureCallback<Void> getFutureCallback(String message) {
+        return new FutureCallback<>() {
+            @Override
+            public void onSuccess(Void unused) {
+                LogUtil.i(TAG, message);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                throw new RuntimeException(t);
+            }
+        };
+    }
+
+    private void handleNewState(@ProvisionState int state) {
+        if (state == PROVISION_IN_PROGRESS) {
+            mContext.getPackageManager().setComponentEnabledSetting(
+                    new ComponentName(mContext, LockedBootCompletedReceiver.class),
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+        }
+    }
+
+    @VisibleForTesting
+    @ProvisionState
+    static int getNextState(@ProvisionState int state, @ProvisionEvent int event) {
+        switch (event) {
+            case PROVISION_READY:
+                if (state == UNPROVISIONED) {
+                    return PROVISION_IN_PROGRESS;
+                }
+                throw new StateTransitionException(state, event);
+            case ProvisionEvent.PROVISION_PAUSE:
+                if (state == PROVISION_IN_PROGRESS) {
+                    return PROVISION_PAUSED;
+                }
+                throw new StateTransitionException(state, event);
+            case PROVISION_RESUME:
+                if (state == PROVISION_PAUSED) {
+                    return PROVISION_IN_PROGRESS;
+                }
+                throw new StateTransitionException(state, event);
+            case ProvisionEvent.PROVISION_KIOSK:
+                if (state == PROVISION_IN_PROGRESS) {
+                    return KIOSK_PROVISIONED;
+                }
+                throw new StateTransitionException(state, event);
+            case ProvisionEvent.PROVISION_FAILURE:
+                if (state == PROVISION_IN_PROGRESS) {
+                    return PROVISION_FAILED;
+                }
+                throw new StateTransitionException(state, event);
+            case ProvisionEvent.PROVISION_RETRY:
+                if (state == PROVISION_FAILED) {
+                    return PROVISION_IN_PROGRESS;
+                }
+                throw new StateTransitionException(state, event);
+            case ProvisionEvent.PROVISION_SUCCESS:
+                if (state == KIOSK_PROVISIONED) {
+                    return PROVISION_SUCCEEDED;
+                }
+                throw new StateTransitionException(state, event);
+            default:
+                throw new IllegalArgumentException("Input state is invalid");
+        }
+    }
+
+    @Override
+    public DeviceStateController getDeviceStateController() {
+        return mDeviceStateController;
+    }
+
+    @Override
+    public DevicePolicyController getDevicePolicyController() {
+        return mPolicyController;
+    }
+
+    @Override
+    public ListenableFuture<Void> onUserUnlocked() {
+        return Futures.transformAsync(getState(),
+                state -> {
+                    if (state == UNPROVISIONED) {
+                        return checkReadyToStartProvisioning();
+                    } else {
+                        return mPolicyController.enforceCurrentPolicies();
+                    }
+                },
+                mBgExecutor);
+    }
+
+    @Override
+    public ListenableFuture<Void> onUserSetupCompleted() {
+        return checkReadyToStartProvisioning();
+    }
+
+
+    private ListenableFuture<Void> checkReadyToStartProvisioning() {
+        if (!isUserSetupComplete()) {
+            return Futures.immediateVoidFuture();
+        }
+        return Futures.transformAsync(getState(),
+                state -> {
+                    if (state != UNPROVISIONED) {
+                        return Futures.immediateVoidFuture();
+                    }
+                    GlobalParametersClient globalParametersClient =
+                            GlobalParametersClient.getInstance();
+                    return Futures.transformAsync(globalParametersClient.isProvisionReady(),
+                            isReady -> {
+                                if (isReady) {
+                                    notifyProvisioningReady();
+                                }
+                                return Futures.immediateVoidFuture();
+                            },
+                            mBgExecutor);
+                },
+                mBgExecutor);
+    }
+
+    private boolean isUserSetupComplete() {
+        return Settings.Secure.getInt(
+                mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
+    }
+
+    /**
+     * A RuntimeException thrown when state transition is  not allowed
+     */
+    public static class StateTransitionException extends RuntimeException {
+        public StateTransitionException(@ProvisionState int currentState,
+                @ProvisionEvent int event) {
+            super("Can not handle event: " + eventToString(event)
+                    + " in state: " + stateToString(currentState));
+        }
+
+        private static String stateToString(@ProvisionState int state) {
+            switch (state) {
+                case UNPROVISIONED:
+                    return "UNPROVISIONED";
+                case PROVISION_IN_PROGRESS:
+                    return "PROVISION_IN_PROGRESS";
+                case PROVISION_PAUSED:
+                    return "PROVISION_PAUSED";
+                case PROVISION_FAILED:
+                    return "PROVISION_FAILED";
+                case PROVISION_SUCCEEDED:
+                    return "PROVISION_SUCCEEDED";
+                case KIOSK_PROVISIONED:
+                    return "KIOSK_PROVISIONED";
+                default:
+                    return "UNKNOWN_STATE";
+            }
+        }
+
+        private static String eventToString(@ProvisionEvent int event) {
+            switch (event) {
+                case PROVISION_READY:
+                    return "PROVISION_READY";
+                case PROVISION_PAUSE:
+                    return "PROVISION_PAUSE";
+                case PROVISION_SUCCESS:
+                    return "PROVISION_SUCCESS";
+                case PROVISION_FAILURE:
+                    return "PROVISION_FAILURE";
+                case PROVISION_KIOSK:
+                    return "PROVISION_KIOSK";
+                case PROVISION_RESUME:
+                    return "PROVISION_RESUME";
+                case PROVISION_RETRY:
+                    return "PROVISION_RETRY";
+                default:
+                    return "UNKNOWN_EVENT";
+            }
+        }
+
+    }
+
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/RolePolicyHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/RolePolicyHandler.java
index 3245f1d..f19a07a 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/RolePolicyHandler.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/RolePolicyHandler.java
@@ -16,19 +16,6 @@
 
 package com.android.devicelockcontroller.policy;
 
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.KIOSK_SETUP;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_FAILED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_IN_PROGRESS;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_SUCCEEDED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNPROVISIONED;
-
-import android.content.Context;
 import android.os.OutcomeReceiver;
 
 import androidx.concurrent.futures.CallbackToFutureAdapter;
@@ -42,37 +29,38 @@
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
+import java.util.concurrent.Executor;
+
 /** Handles kiosk app role. */
 public final class RolePolicyHandler implements PolicyHandler {
     private static final String TAG = "RolePolicyHandler";
 
-    private final Context mContext;
     private final SystemDeviceLockManager mSystemDeviceLockManager;
     private final SetupParametersClientInterface mSetupParametersClient;
+    private final Executor mBgExecutor;
 
-    RolePolicyHandler(Context context, SystemDeviceLockManager systemDeviceLockManager) {
-        mContext = context;
+    RolePolicyHandler(SystemDeviceLockManager systemDeviceLockManager, Executor bgExecutor) {
         mSystemDeviceLockManager = systemDeviceLockManager;
+        mBgExecutor = bgExecutor;
         mSetupParametersClient = SetupParametersClient.getInstance();
     }
 
-    private ListenableFuture<@ResultType Integer>
-            getAddFinancedDeviceLockKioskRoleFuture(String packageName) {
+    private ListenableFuture<Boolean> getAddFinancedDeviceLockKioskRoleFuture(String packageName) {
         return CallbackToFutureAdapter.getFuture(
                 completer -> {
                     mSystemDeviceLockManager.addFinancedDeviceKioskRole(packageName,
-                            mContext.getMainExecutor(),
+                            mBgExecutor,
                             new OutcomeReceiver<>() {
                                 @Override
                                 public void onResult(Void result) {
-                                    completer.set(SUCCESS);
+                                    completer.set(true);
                                 }
 
                                 @Override
                                 public void onError(Exception ex) {
                                     LogUtil.e(TAG, "Failed to add financed device kiosk role",
                                             ex);
-                                    completer.set(FAILURE);
+                                    completer.set(false);
                                 }
                             });
                     // Used only for debugging.
@@ -80,32 +68,31 @@
                 });
     }
 
-    private ListenableFuture<@ResultType Integer>
-            getAddFinancedDeviceLockKioskRoleFuture() {
+    private ListenableFuture<Boolean> getAddFinancedDeviceLockKioskRoleFuture() {
         return Futures.transformAsync(mSetupParametersClient.getKioskPackage(),
                 kioskPackageName -> kioskPackageName == null
-                        ? Futures.immediateFuture(FAILURE)
+                        ? Futures.immediateFuture(false)
                         : getAddFinancedDeviceLockKioskRoleFuture(kioskPackageName),
                 MoreExecutors.directExecutor());
     }
 
-    private ListenableFuture<@ResultType Integer>
-            getRemoveFinancedDeviceLockKioskRoleFuture(String packageName) {
+    private ListenableFuture<Boolean> getRemoveFinancedDeviceLockKioskRoleFuture(
+            String packageName) {
         return CallbackToFutureAdapter.getFuture(
                 completer -> {
                     mSystemDeviceLockManager.removeFinancedDeviceKioskRole(packageName,
-                            mContext.getMainExecutor(),
+                            mBgExecutor,
                             new OutcomeReceiver<>() {
                                 @Override
                                 public void onResult(Void result) {
-                                    completer.set(SUCCESS);
+                                    completer.set(true);
                                 }
 
                                 @Override
                                 public void onError(Exception ex) {
                                     LogUtil.e(TAG, "Failed to remove financed device kiosk role",
                                             ex);
-                                    completer.set(FAILURE);
+                                    completer.set(false);
                                 }
                             });
                     // Used only for debugging.
@@ -113,34 +100,21 @@
                 });
     }
 
-    private ListenableFuture<@ResultType Integer>
-            getRemoveFinancedDeviceLockKioskRoleFuture() {
+    private ListenableFuture<Boolean> getRemoveFinancedDeviceLockKioskRoleFuture() {
         return Futures.transformAsync(mSetupParametersClient.getKioskPackage(),
                 kioskPackageName -> kioskPackageName == null
-                        ? Futures.immediateFuture(FAILURE)
+                        ? Futures.immediateFuture(false)
                         : getRemoveFinancedDeviceLockKioskRoleFuture(kioskPackageName),
                 MoreExecutors.directExecutor());
     }
 
     @Override
-    public ListenableFuture<@ResultType Integer> setPolicyForState(@DeviceState int state) {
-        switch (state) {
-            case UNPROVISIONED:
-            case KIOSK_SETUP:
-            case UNLOCKED:
-            case LOCKED:
-            case SETUP_IN_PROGRESS:
-            case SETUP_FAILED:
-            case PSEUDO_LOCKED:
-            case PSEUDO_UNLOCKED:
-                return Futures.immediateFuture(SUCCESS);
-            case SETUP_SUCCEEDED:
-                return getAddFinancedDeviceLockKioskRoleFuture();
-            case CLEARED:
-                return getRemoveFinancedDeviceLockKioskRoleFuture();
-            default:
-                return Futures.immediateFailedFuture(
-                        new IllegalStateException(String.valueOf(state)));
-        }
+    public ListenableFuture<Boolean> onProvisioned() {
+        return getAddFinancedDeviceLockKioskRoleFuture();
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onCleared() {
+        return getRemoveFinancedDeviceLockKioskRoleFuture();
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupController.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupController.java
deleted file mode 100644
index fd08eb6..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupController.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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 com.android.devicelockcontroller.policy;
-
-import androidx.annotation.IntDef;
-import androidx.lifecycle.LifecycleOwner;
-
-import com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Controller managing communication between setup tasks and UI layer.
- *
- * Note that some APIs return a listenable future because the underlying calls to
- * {@link com.android.devicelockcontroller.storage.SetupParametersClient} return a listenable future
- * for inter process calls.
- */
-public interface SetupController {
-
-    /** Definitions for status of the setup. */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            SetupStatus.SETUP_NOT_STARTED,
-            SetupStatus.SETUP_IN_PROGRESS,
-            SetupStatus.SETUP_FAILED,
-            SetupStatus.SETUP_FINISHED})
-    @interface SetupStatus {
-        /** Setup has not started and will be triggered from the activity. */
-        int SETUP_NOT_STARTED = 0;
-        /** Setup is in progress */
-        int SETUP_IN_PROGRESS = 1;
-        /** Setup has failed. */
-        int SETUP_FAILED = 2;
-        /** Setup has finished successfully. */
-        int SETUP_FINISHED = 3;
-    }
-
-    /** Registers a callback listener. */
-    void addListener(SetupUpdatesCallbacks cb);
-
-    /** Removes a callback listener. */
-    void removeListener(SetupUpdatesCallbacks cb);
-
-    /** Returns the status of Setup progress. */
-    @SetupStatus
-    int getSetupState();
-
-    /** Triggers the setup flow process. */
-    ListenableFuture<Void> startSetupFlow(LifecycleOwner owner);
-
-    /** Callback interface for updates on setup tasks */
-    interface SetupUpdatesCallbacks {
-
-        /** Method called when setup has failed. */
-        void setupFailed(@SetupFailureReason int reason);
-
-        /** Method called when setup tasks have completed successfully. */
-        void setupCompleted();
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupControllerImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupControllerImpl.java
deleted file mode 100644
index c617da4..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupControllerImpl.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
-
-import static androidx.work.WorkInfo.State.CANCELLED;
-import static androidx.work.WorkInfo.State.FAILED;
-import static androidx.work.WorkInfo.State.SUCCEEDED;
-
-import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason.INSTALL_EXISTING_FAILED;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason.INSTALL_FAILED;
-import static com.android.devicelockcontroller.policy.AbstractTask.ERROR_CODE_GET_PENDING_INTENT_FAILED;
-import static com.android.devicelockcontroller.policy.AbstractTask.ERROR_CODE_NO_PACKAGE_NAME;
-import static com.android.devicelockcontroller.policy.AbstractTask.TASK_RESULT_ERROR_CODE_KEY;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Build;
-
-import androidx.annotation.MainThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.work.Data;
-import androidx.work.ExistingWorkPolicy;
-import androidx.work.ListenableWorker;
-import androidx.work.OneTimeWorkRequest;
-import androidx.work.WorkContinuation;
-import androidx.work.WorkInfo;
-import androidx.work.WorkInfo.State;
-import androidx.work.WorkManager;
-
-import com.android.devicelockcontroller.DeviceLockControllerApplication;
-import com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason;
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent;
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
-import com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker;
-import com.android.devicelockcontroller.storage.SetupParametersClient;
-import com.android.devicelockcontroller.util.LogUtil;
-
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Controller managing communication between setup tasks and UI layer.
- */
-public final class SetupControllerImpl implements SetupController {
-
-    private static final String SETUP_PLAY_INSTALL_TASKS_NAME =
-            "devicelock_setup_play_install_tasks";
-    public static final String SETUP_PRE_INSTALLED_PACKAGE_TASK =
-            "devicelock_setup_pre_installed_package_task";
-    public static final String TAG = "SetupController";
-    public static final String SETUP_INSTALL_EXISTING_PACKAGE_TASK =
-            "devicelock_setup_install_existing_package_task";
-
-    private final List<SetupUpdatesCallbacks> mCallbacks = new ArrayList<>();
-    @SetupStatus
-    private int mCurrentSetupState;
-    private final Context mContext;
-    private final DevicePolicyController mPolicyController;
-    private final DeviceStateController mStateController;
-    private SetupUpdatesCallbacks mReportStateCallbacks;
-
-    public SetupControllerImpl(
-            Context context,
-            DeviceStateController stateController,
-            DevicePolicyController policyController) {
-        this.mContext = context;
-        this.mStateController = stateController;
-        this.mPolicyController = policyController;
-        int state = stateController.getState();
-        if (state == DeviceState.SETUP_IN_PROGRESS || state == DeviceState.UNPROVISIONED
-                || state == DeviceState.PSEUDO_UNLOCKED || state == DeviceState.PSEUDO_LOCKED) {
-            mCurrentSetupState = SetupStatus.SETUP_NOT_STARTED;
-        } else if (state == DeviceState.SETUP_FAILED) {
-            mCurrentSetupState = SetupStatus.SETUP_FAILED;
-        } else {
-            mCurrentSetupState = SetupStatus.SETUP_FINISHED;
-        }
-        LogUtil.v(TAG,
-                String.format(Locale.US, "Setup started with state = %d", mCurrentSetupState));
-    }
-
-    @Override
-    public void addListener(SetupUpdatesCallbacks cb) {
-        synchronized (mCallbacks) {
-            mCallbacks.add(cb);
-        }
-    }
-
-    @Override
-    public void removeListener(SetupUpdatesCallbacks cb) {
-        synchronized (mCallbacks) {
-            mCallbacks.remove(cb);
-        }
-    }
-
-    @Override
-    @SetupStatus
-    public int getSetupState() {
-        LogUtil.v(TAG, String.format(Locale.US, "Setup state returned = %d", mCurrentSetupState));
-        return mCurrentSetupState;
-    }
-
-    @Override
-    public ListenableFuture<Void> startSetupFlow(LifecycleOwner owner) {
-        LogUtil.v(TAG, "Trigger setup flow");
-        WorkManager workManager = WorkManager.getInstance(mContext);
-        mReportStateCallbacks =
-                ReportDeviceProvisionStateWorker.getSetupUpdatesCallbacks(workManager);
-        mCallbacks.add(mReportStateCallbacks);
-        return Futures.transformAsync(isKioskAppPreInstalled(),
-                isPreinstalled -> {
-                    if (isPreinstalled) {
-                        setupFlowTaskSuccessCallbackHandler();
-                        return Futures.immediateVoidFuture();
-                    } else if (mContext.getUser().isSystem()) {
-                        final Class<? extends ListenableWorker> playInstallTaskClass =
-                                ((DeviceLockControllerApplication) mContext.getApplicationContext())
-                                        .getPlayInstallPackageTaskClass();
-                        if (playInstallTaskClass != null) {
-                            return installKioskAppFromPlay(workManager, owner,
-                                    playInstallTaskClass);
-                        } else {
-                            setupFlowTaskFailureCallbackHandler(INSTALL_FAILED);
-                            return Futures.immediateFailedFuture(
-                                    new IllegalStateException("Kiosk app installation failed"));
-                        }
-                    } else {
-                        return installKioskAppForSecondaryUser(workManager, owner);
-                    }
-                }, MoreExecutors.directExecutor());
-    }
-
-    @VisibleForTesting
-    ListenableFuture<Boolean> isKioskAppPreInstalled() {
-        return !Build.isDebuggable() ? Futures.immediateFuture(false)
-                : Futures.transform(SetupParametersClient.getInstance().getKioskPackage(),
-                        packageName -> {
-                            try {
-                                mContext.getPackageManager().getPackageInfo(
-                                        packageName,
-                                        ApplicationInfo.FLAG_INSTALLED);
-                                LogUtil.i(TAG, "Kiosk app is pre-installed");
-                                return true;
-                            } catch (NameNotFoundException e) {
-                                LogUtil.i(TAG, "Kiosk app is not pre-installed");
-                                return false;
-                            }
-                        }, MoreExecutors.directExecutor());
-    }
-
-    @VisibleForTesting
-    ListenableFuture<Void> installKioskAppFromPlay(WorkManager workManager, LifecycleOwner owner,
-            Class<? extends ListenableWorker> playInstallTaskClass) {
-
-        final SetupParametersClient setupParametersClient = SetupParametersClient.getInstance();
-        final ListenableFuture<String> getPackageNameTask = setupParametersClient.getKioskPackage();
-
-        return Futures.whenAllSucceed(getPackageNameTask)
-                .call(() -> {
-                    LogUtil.v(TAG, "Installing kiosk app from play");
-
-                    final String kioskPackageName = Futures.getDone(getPackageNameTask);
-
-                    final OneTimeWorkRequest playInstallPackageTask =
-                            getPlayInstallPackageTask(playInstallTaskClass, kioskPackageName);
-                    createAndRunTasks(workManager, owner, SETUP_PLAY_INSTALL_TASKS_NAME,
-                            playInstallPackageTask);
-                    return null;
-                }, mContext.getMainExecutor());
-    }
-
-    ListenableFuture<Void> installKioskAppForSecondaryUser(WorkManager workManager,
-            LifecycleOwner owner) {
-        LogUtil.v(TAG, "Installing existing package");
-        final SetupParametersClient setupParametersClient = SetupParametersClient.getInstance();
-        final ListenableFuture<String> kioskPackageTask = setupParametersClient.getKioskPackage();
-        return Futures.whenAllSucceed(kioskPackageTask)
-                .call(() -> {
-                    final String kioskPackageName = Futures.getDone(kioskPackageTask);
-
-                    createAndRunTasks(workManager, owner, SETUP_INSTALL_EXISTING_PACKAGE_TASK,
-                            getInstallExistingPackageTask(Futures.getDone(kioskPackageTask)));
-                    return null;
-                }, mContext.getMainExecutor());
-    }
-
-    @NonNull
-    private static OneTimeWorkRequest getInstallExistingPackageTask(String kioskPackageName) {
-        return new OneTimeWorkRequest.Builder(
-                InstallExistingPackageTask.class).setInputData(
-                new Data.Builder().putString(EXTRA_KIOSK_PACKAGE,
-                        kioskPackageName).build()).build();
-    }
-
-    @NonNull
-    private static OneTimeWorkRequest getPlayInstallPackageTask(
-            Class<? extends ListenableWorker> playInstallTaskClass, String kioskPackageName) {
-        return new OneTimeWorkRequest.Builder(
-                playInstallTaskClass).setInputData(
-                new Data.Builder().putString(
-                        EXTRA_KIOSK_PACKAGE, kioskPackageName).build()).build();
-    }
-
-    @MainThread
-    private void createAndRunTasks(WorkManager workManager, LifecycleOwner owner,
-            String uniqueWorkName, OneTimeWorkRequest... works) {
-
-        WorkContinuation workChain = workManager.beginUniqueWork(
-                uniqueWorkName,
-                ExistingWorkPolicy.KEEP,
-                works[0]);
-        for (int i = 1, len = works.length; i < len; i++) {
-            workChain = workChain.then(works[i]);
-        }
-        workChain.enqueue();
-        workManager.getWorkInfosForUniqueWorkLiveData(
-                        uniqueWorkName)
-                .observe(owner, workInfo -> {
-                    if (areAllTasksSucceeded(workInfo)) {
-                        setupFlowTaskSuccessCallbackHandler();
-                    } else if (isAtLeastOneTaskFailedOrCancelled(workInfo)) {
-                        setupFlowTaskFailureCallbackHandler(getTaskFailureType(workInfo));
-                    }
-                });
-    }
-
-    @VisibleForTesting
-    ListenableFuture<Void> finishSetup() {
-        mCallbacks.remove(mReportStateCallbacks);
-        if (mCurrentSetupState == SetupStatus.SETUP_FINISHED) {
-            return Futures.transformAsync(mStateController.setNextStateForEvent(
-                            DeviceEvent.SETUP_COMPLETE),
-                    empty -> Futures.transform(mPolicyController.launchActivityInLockedMode(),
-                            isLaunched -> {
-                                if (!isLaunched) {
-                                    throw new IllegalStateException(
-                                            "Launching kiosk setup activity failed!");
-                                }
-                                return null;
-                            }, MoreExecutors.directExecutor()), MoreExecutors.directExecutor());
-        } else if (mCurrentSetupState == SetupStatus.SETUP_FAILED) {
-            return Futures.transform(
-                    SetupParametersClient.getInstance().isProvisionMandatory(),
-                    isMandatory -> {
-                        if (isMandatory) mPolicyController.wipeData();
-                        return null;
-                    }, MoreExecutors.directExecutor());
-        } else {
-            return Futures.immediateFailedFuture(new IllegalStateException(
-                    "Can not finish setup when setup state is NOT_STARTED/IN_PROGRESS!"));
-        }
-    }
-
-    @VisibleForTesting
-    void setupFlowTaskSuccessCallbackHandler() {
-        setupFlowTaskCallbackHandler(true, /* Ignored parameter */ SetupFailureReason.SETUP_FAILED);
-    }
-
-    @VisibleForTesting
-    void setupFlowTaskFailureCallbackHandler(@SetupFailureReason int failReason) {
-        setupFlowTaskCallbackHandler(false, failReason);
-    }
-
-    /**
-     * Handles the setup result and invokes registered {@link SetupUpdatesCallbacks}.
-     *
-     * @param result     true if the setup succeed, otherwise false
-     * @param failReason why the setup failed, the value will be ignored if {@code result} is true
-     */
-    private void setupFlowTaskCallbackHandler(
-            boolean result, @SetupFailureReason int failReason) {
-        Futures.addCallback(
-                Futures.transformAsync(mStateController.setNextStateForEvent(
-                                result ? DeviceEvent.SETUP_SUCCESS : DeviceEvent.SETUP_FAILURE),
-                        input -> {
-                            if (result) {
-                                LogUtil.i(TAG, "Handling successful setup");
-                                mCurrentSetupState = SetupStatus.SETUP_FINISHED;
-                                synchronized (mCallbacks) {
-                                    for (int i = 0, cbSize = mCallbacks.size(); i < cbSize; i++) {
-                                        mCallbacks.get(i).setupCompleted();
-                                    }
-                                }
-                            } else {
-                                LogUtil.i(TAG, "Handling failed setup");
-                                mCurrentSetupState = SetupStatus.SETUP_FAILED;
-                                synchronized (mCallbacks) {
-                                    for (int i = 0, cbSize = mCallbacks.size(); i < cbSize; i++) {
-                                        mCallbacks.get(i).setupFailed(failReason);
-                                    }
-                                }
-                            }
-                            return finishSetup();
-                        }, MoreExecutors.directExecutor()),
-                new FutureCallback<>() {
-                    @Override
-                    public void onSuccess(Void result) {
-                        LogUtil.v(TAG, "Successfully handled setup callbacks");
-                    }
-
-                    @Override
-                    public void onFailure(Throwable t) {
-                        LogUtil.e(TAG, "Failed to handle setup callbacks!", t);
-                    }
-                }, MoreExecutors.directExecutor());
-    }
-
-    @VisibleForTesting
-    @SetupFailureReason
-    static int transformErrorCodeToFailureType(@AbstractTask.ErrorCode int errorCode) {
-        int failReason = SetupFailureReason.SETUP_FAILED;
-        if (errorCode <= ERROR_CODE_GET_PENDING_INTENT_FAILED) {
-            failReason = INSTALL_FAILED;
-        } else if (errorCode == ERROR_CODE_NO_PACKAGE_NAME) {
-            failReason = INSTALL_EXISTING_FAILED;
-        }
-        return failReason;
-    }
-
-    private static boolean areAllTasksSucceeded(List<WorkInfo> workInfoList) {
-        for (WorkInfo workInfo : workInfoList) {
-            if (workInfo.getState() != SUCCEEDED) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private static boolean isAtLeastOneTaskFailedOrCancelled(List<WorkInfo> workInfoList) {
-        for (WorkInfo workInfo : workInfoList) {
-            State state = workInfo.getState();
-            if (state == FAILED || state == CANCELLED) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @SetupFailureReason
-    private static int getTaskFailureType(List<WorkInfo> workInfoList) {
-        for (WorkInfo workInfo : workInfoList) {
-            int errorCode = workInfo.getOutputData().getInt(TASK_RESULT_ERROR_CODE_KEY, -1);
-            if (errorCode != -1) {
-                return transformErrorCodeToFailureType(errorCode);
-            }
-        }
-        return SetupFailureReason.SETUP_FAILED;
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/StartLockTaskModeWorker.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/StartLockTaskModeWorker.java
new file mode 100644
index 0000000..6bde4bf
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/StartLockTaskModeWorker.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.policy.DevicePolicyControllerImpl.ACTION_DEVICE_LOCK_KIOSK_SETUP;
+
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.SystemClock;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.work.ListenableWorker;
+import androidx.work.WorkerParameters;
+
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+import com.android.devicelockcontroller.storage.UserParameters;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+import java.time.Duration;
+import java.util.Objects;
+
+/**
+ * A worker class dedicated to start lock task mode when device is locked.
+ */
+public final class StartLockTaskModeWorker extends ListenableWorker {
+
+    private static final String TAG = "StartLockTaskModeWorker";
+    static final String START_LOCK_TASK_MODE_WORK_NAME = "start-lock-task-mode";
+    private final Context mContext;
+    private final ListeningExecutorService mExecutorService;
+
+    static final Duration START_LOCK_TASK_MODE_WORKER_RETRY_INTERVAL_SECONDS =
+            Duration.ofSeconds(30);
+    private final ActivityManager mAm;
+    private final DevicePolicyManager mDpm;
+
+    public StartLockTaskModeWorker(
+            @NonNull Context context,
+            @NonNull WorkerParameters workerParams,
+            ListeningExecutorService executorService) {
+        this(context,
+                context.getSystemService(DevicePolicyManager.class),
+                context.getSystemService(ActivityManager.class),
+                workerParams,
+                executorService);
+    }
+
+    @VisibleForTesting
+    StartLockTaskModeWorker(
+            @NonNull Context context,
+            @NonNull DevicePolicyManager dpm,
+            @NonNull ActivityManager am,
+            @NonNull WorkerParameters workerParams,
+            ListeningExecutorService executorService) {
+        super(context, workerParams);
+        mContext = context;
+        mExecutorService = executorService;
+        mDpm = Objects.requireNonNull(dpm);
+        mAm = Objects.requireNonNull(am);
+    }
+
+    @NonNull
+    @Override
+    public ListenableFuture<Result> startWork() {
+        DevicePolicyController devicePolicyController =
+                ((PolicyObjectsProvider) mContext.getApplicationContext())
+                        .getProvisionStateController().getDevicePolicyController();
+        ListenableFuture<Boolean> isInLockTaskModeFuture =
+                Futures.submit(
+                        () -> mAm.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED,
+                        mExecutorService);
+        final ListenableFuture<Result> lockTaskFuture =
+                Futures.transformAsync(isInLockTaskModeFuture, isInLockTaskMode -> {
+            if (isInLockTaskMode) {
+                LogUtil.i(TAG, "Lock task mode is active now");
+                return Futures.immediateFuture(Result.success());
+            }
+
+            return Futures.transform(
+                    devicePolicyController.getLaunchIntentForCurrentState(),
+                    launchIntent -> {
+                        if (launchIntent == null) {
+                            LogUtil.e(TAG, "Failed to enter lock task mode: no intent to launch");
+                            return Result.failure();
+                        }
+                        ComponentName launchIntentComponent = launchIntent.getComponent();
+                        String packageName = launchIntentComponent.getPackageName();
+                        if (!Objects.requireNonNull(mDpm).isLockTaskPermitted(packageName)) {
+                            LogUtil.e(TAG, packageName + " is not permitted in lock task mode");
+                            return Result.failure();
+                        }
+                        setPreferredActivityForHome(launchIntentComponent);
+                        launchIntent.addFlags(
+                                Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+                        LogUtil.i(TAG, "Launching activity for intent: " + launchIntent);
+                        mContext.startActivity(launchIntent,
+                                ActivityOptions.makeBasic().setLockTaskEnabled(true).toBundle());
+                        // If the intent of the activity to be launched is the Kiosk app, we treat
+                        // this as the end of the provisioning time.
+                        if (launchIntent.getAction() == ACTION_DEVICE_LOCK_KIOSK_SETUP) {
+                            long provisioningStartTime = UserParameters
+                                    .getProvisioningStartTimeMillis(mContext);
+                            if (provisioningStartTime > 0) {
+                                ((StatsLoggerProvider) mContext.getApplicationContext())
+                                        .getStatsLogger()
+                                        .logProvisioningComplete(SystemClock.elapsedRealtime()
+                                                - provisioningStartTime);
+                            }
+                        }
+                        if (mAm.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED) {
+                            LogUtil.i(TAG, "Successfully entered lock task mode");
+                            return Result.success();
+                        } else {
+                            LogUtil.i(TAG, "Retry entering lock task mode");
+                            return Result.retry();
+                        }
+                    }, mExecutorService);
+        }, mExecutorService);
+        return Futures.catchingAsync(lockTaskFuture, Exception.class,
+                ex -> Futures.transform(devicePolicyController
+                        .enforceCurrentPoliciesForCriticalFailure(),
+                        unused -> {
+                            LogUtil.e(TAG, "Failed to lock task: ", ex);
+                            return Result.failure();
+                        }, mExecutorService),
+                mExecutorService);
+    }
+
+    private void setPreferredActivityForHome(ComponentName activity) {
+
+        final String currentPackage = UserParameters.getPackageOverridingHome(mContext);
+        if (currentPackage != null && !currentPackage.equals(activity.getPackageName())) {
+            mDpm.clearPackagePersistentPreferredActivities(null /* admin */, currentPackage);
+        } else {
+            mDpm.addPersistentPreferredActivity(null /* admin */, getHomeIntentFilter(), activity);
+            UserParameters.setPackageOverridingHome(mContext, activity.getPackageName());
+        }
+    }
+
+    private static IntentFilter getHomeIntentFilter() {
+        final IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
+        filter.addCategory(Intent.CATEGORY_HOME);
+        filter.addCategory(Intent.CATEGORY_DEFAULT);
+        return filter;
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/StateTransitionException.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/StateTransitionException.java
deleted file mode 100644
index ce2d9ac..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/StateTransitionException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 com.android.devicelockcontroller.policy;
-
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent;
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
-
-/** Exception caused when a DeviceEvent cannot be handled for a DeviceState. */
-public final class StateTransitionException extends Exception {
-
-    public StateTransitionException(@DeviceState int state, @DeviceEvent int event) {
-        super("Cannot handle event " + event + " in state " + state);
-    }
-}
-
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/TaskWorkerFactory.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/TaskWorkerFactory.java
deleted file mode 100644
index e56581a..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/TaskWorkerFactory.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
-
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.work.ListenableWorker;
-import androidx.work.WorkerFactory;
-import androidx.work.WorkerParameters;
-
-import com.android.devicelockcontroller.util.LogUtil;
-
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.concurrent.Executors;
-
-/** A factory which produces {@link AbstractTask}s with parameters. */
-public final class TaskWorkerFactory extends WorkerFactory {
-    private static final String TAG = "TaskWorkerFactory";
-
-    private final ListeningExecutorService mExecutorService;
-
-    public TaskWorkerFactory() {
-        mExecutorService = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
-    }
-
-    @Nullable
-    @Override
-    public ListenableWorker createWorker(
-            @NonNull Context context,
-            @NonNull String workerClassName,
-            @NonNull WorkerParameters workerParameters) {
-        try {
-            Class<?> clazz = Class.forName(workerClassName);
-            return (ListenableWorker) clazz.getDeclaredConstructor(
-                            Context.class, WorkerParameters.class, ListeningExecutorService.class)
-                    .newInstance(context, workerParameters, mExecutorService);
-        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException
-                | InvocationTargetException | ClassNotFoundException e) {
-            // Unable to create an instance of the ListenableWorker.
-            LogUtil.e(TAG, "Cannot create worker: " + workerClassName, e);
-            return null;
-        }
-        // unreachable
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/UserRestrictionsPolicyHandler.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/UserRestrictionsPolicyHandler.java
index f12191a..d709272 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/UserRestrictionsPolicyHandler.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/UserRestrictionsPolicyHandler.java
@@ -16,35 +16,21 @@
 
 package com.android.devicelockcontroller.policy;
 
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.KIOSK_SETUP;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_FAILED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_IN_PROGRESS;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_SUCCEEDED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNPROVISIONED;
-
 import android.app.admin.DevicePolicyManager;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
 import android.os.UserManager;
 import android.util.ArraySet;
 
-import androidx.annotation.MainThread;
-
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.util.LogUtil;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 
 import java.util.Collections;
 import java.util.Locale;
+import java.util.concurrent.Executor;
 
 /**
  * Enforces UserRestriction policies.
@@ -54,6 +40,7 @@
     private static final String TAG = "UserRestrictionsPolicyHandler";
 
     private final ArraySet<String> mAlwaysOnRestrictions = new ArraySet<>();
+    private final Executor mBgExecutor;
 
     /**
      * A list of restrictions that will be always active, it is optional, partners can config the
@@ -68,10 +55,11 @@
     private final boolean mIsDebug;
 
     UserRestrictionsPolicyHandler(DevicePolicyManager dpm, UserManager userManager,
-            boolean isDebug) {
+            boolean isDebug, Executor bgExecutor) {
         mDpm = dpm;
         mUserManager = userManager;
         mIsDebug = isDebug;
+        mBgExecutor = bgExecutor;
 
         LogUtil.i(TAG, String.format(Locale.US, "Build type DEBUG = %s", isDebug));
 
@@ -82,50 +70,42 @@
     }
 
     @Override
-    @ResultType
-    public ListenableFuture<@ResultType Integer> setPolicyForState(@DeviceState int state) {
-        final Handler mainHandler = new Handler(Looper.getMainLooper());
-        LogUtil.v(TAG, String.format(Locale.US, "Setting restrictions for %d", state));
-        switch (state) {
-            case SETUP_IN_PROGRESS:
-            case SETUP_SUCCEEDED:
-            case UNLOCKED:
-            case KIOSK_SETUP:
-                setupRestrictions(mAlwaysOnRestrictions, true);
-                return Futures.whenAllSucceed(
-                                setupRestrictions(retrieveOptionalAlwaysOnRestrictions(), true),
-                                setupRestrictions(retrieveLockModeRestrictions(), false))
-                        .call(
-                                () -> SUCCESS, mainHandler::post);
-            case LOCKED:
-                setupRestrictions(mAlwaysOnRestrictions, true);
-                return Futures.whenAllSucceed(
-                                setupRestrictions(retrieveOptionalAlwaysOnRestrictions(), true),
-                                setupRestrictions(retrieveLockModeRestrictions(), true))
-                        .call(
-                                () -> SUCCESS, mainHandler::post);
-            case UNPROVISIONED:
-            case SETUP_FAILED:
-            case CLEARED:
-                setupRestrictions(mAlwaysOnRestrictions, false);
-                return Futures.whenAllSucceed(
-                                setupRestrictions(retrieveOptionalAlwaysOnRestrictions(), false),
-                                setupRestrictions(retrieveLockModeRestrictions(), false))
-                        .call(
-                                () -> SUCCESS, mainHandler::post);
-            case PSEUDO_LOCKED:
-            case PSEUDO_UNLOCKED:
-                return Futures.immediateFuture(SUCCESS);
-            default:
-                return Futures.immediateFailedFuture(
-                        new IllegalStateException(String.valueOf(state)));
-        }
-
-
+    public ListenableFuture<Boolean> onProvisionInProgress() {
+        setupRestrictions(mAlwaysOnRestrictions, true);
+        return Futures.whenAllSucceed(
+                        setupRestrictions(retrieveOptionalAlwaysOnRestrictions(), true),
+                        setupRestrictions(retrieveLockModeRestrictions(), false))
+                .call(() -> true, MoreExecutors.directExecutor());
     }
 
-    @MainThread
-    public ListenableFuture<ArraySet<String>> retrieveLockModeRestrictions() {
+    @Override
+    public ListenableFuture<Boolean> onLocked() {
+        setupRestrictions(mAlwaysOnRestrictions, true);
+        return Futures.whenAllSucceed(
+                        setupRestrictions(retrieveOptionalAlwaysOnRestrictions(), true),
+                        setupRestrictions(retrieveLockModeRestrictions(), true))
+                .call(() -> true, MoreExecutors.directExecutor());
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onUnlocked() {
+        setupRestrictions(mAlwaysOnRestrictions, true);
+        return Futures.whenAllSucceed(
+                        setupRestrictions(retrieveOptionalAlwaysOnRestrictions(), true),
+                        setupRestrictions(retrieveLockModeRestrictions(), false))
+                .call(() -> true, MoreExecutors.directExecutor());
+    }
+
+    @Override
+    public ListenableFuture<Boolean> onCleared() {
+        setupRestrictions(mAlwaysOnRestrictions, false);
+        return Futures.whenAllSucceed(
+                        setupRestrictions(retrieveOptionalAlwaysOnRestrictions(), false),
+                        setupRestrictions(retrieveLockModeRestrictions(), false))
+                .call(() -> true, MoreExecutors.directExecutor());
+    }
+
+    private ListenableFuture<ArraySet<String>> retrieveLockModeRestrictions() {
         if (mLockModeRestrictions != null) return Futures.immediateFuture(mLockModeRestrictions);
         final SetupParametersClient parameters = SetupParametersClient.getInstance();
         final ListenableFuture<String> kioskPackageTask = parameters.getKioskPackage();
@@ -144,7 +124,7 @@
                         }
                     }
                     return mLockModeRestrictions;
-                }, new Handler(Looper.getMainLooper())::post);
+                }, mBgExecutor);
     }
 
     private ListenableFuture<ArraySet<String>> retrieveOptionalAlwaysOnRestrictions() {
@@ -171,11 +151,10 @@
                         }
                     }
                     return mOptionalAlwaysOnRestrictions;
-                }, new Handler(Looper.getMainLooper())::post);
+                }, mBgExecutor);
     }
 
-    @ResultType
-    private int setupRestrictions(ArraySet<String> restrictions, boolean enable) {
+    private boolean setupRestrictions(ArraySet<String> restrictions, boolean enable) {
         Bundle userRestrictionBundle = mUserManager.getUserRestrictions();
 
         for (int i = 0, size = restrictions.size(); i < size; i++) {
@@ -190,44 +169,13 @@
                 }
             }
         }
-        // clear the adb access restriction if we added it before
-        if (!mIsDebug
-                && enable
-                && restrictions.contains(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
-            mDpm.clearUserRestriction(null /* admin */, UserManager.DISALLOW_DEBUGGING_FEATURES);
-            LogUtil.v(TAG, String.format(Locale.US, "clear %s restriction",
-                    UserManager.DISALLOW_DEBUGGING_FEATURES));
-        }
-        return SUCCESS;
-    }
-
-    @ResultType
-    private ListenableFuture<@ResultType Integer> setupRestrictions(
-            ListenableFuture<ArraySet<String>> restrictionsFuture, boolean enable) {
-        return Futures.transform(restrictionsFuture,
-                restrictions -> setupRestrictions(restrictions, enable),
-                new Handler(Looper.getMainLooper())::post);
-    }
-
-    private boolean checkRestrictions(ArraySet<String> restrictions, boolean value) {
-        Bundle userRestrictionBundle = mUserManager.getUserRestrictions();
-
-        for (int i = 0, size = restrictions.size(); i < size; i++) {
-            String restriction = restrictions.valueAt(i);
-            if (value != userRestrictionBundle.getBoolean(restriction, false)) {
-                LogUtil.i(TAG, String.format(Locale.US, "%s restriction is not %b",
-                        restriction, value));
-                return false;
-            }
-        }
-
         return true;
     }
 
-    private ListenableFuture<Boolean> checkRestrictions(
-            ListenableFuture<ArraySet<String>> restrictionsFuture, boolean value) {
+    private ListenableFuture<Boolean> setupRestrictions(
+            ListenableFuture<ArraySet<String>> restrictionsFuture, boolean enable) {
         return Futures.transform(restrictionsFuture,
-                restrictions -> checkRestrictions(restrictions, value),
-                new Handler(Looper.getMainLooper())::post);
+                restrictions -> setupRestrictions(restrictions, enable),
+                mBgExecutor);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceCheckInClient.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceCheckInClient.java
index 4f9c6d9..f060c5c 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceCheckInClient.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceCheckInClient.java
@@ -16,8 +16,10 @@
 
 package com.android.devicelockcontroller.provision.grpc;
 
+import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.Build;
-import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.Pair;
 
@@ -27,7 +29,7 @@
 import com.android.devicelockcontroller.common.DeviceId;
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
 import com.android.devicelockcontroller.common.DeviceLockConstants.PauseDeviceProvisioningReason;
-import com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason;
+import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason;
 import com.android.devicelockcontroller.util.LogUtil;
 
 /**
@@ -36,8 +38,12 @@
  */
 public abstract class DeviceCheckInClient {
     private static final String TAG = "DeviceCheckInClient";
+    private static final String FILENAME = "debug-check-in-preferences";
+
     public static final String DEVICE_CHECK_IN_CLIENT_DEBUG_CLASS_NAME =
             "com.android.devicelockcontroller.debug.DeviceCheckInClientDebug";
+    protected static final String DEBUG_DEVICELOCK_CHECKIN = "debug.devicelock.checkin";
+    private static final String HOST_NAME_OVERRIDE = "host.name.override";
     private static volatile DeviceCheckInClient sClient;
 
     @Nullable
@@ -45,38 +51,74 @@
     protected static String sHostName = "";
     protected static int sPortNumber = 0;
     protected static Pair<String, String> sApiKey = new Pair<>("", "");
+    private static volatile boolean sUseDebugClient;
+
+    @Nullable
+    private static volatile SharedPreferences sSharedPreferences;
+
+    @Nullable
+    protected static synchronized SharedPreferences getSharedPreferences(
+            @Nullable Context context) {
+        if (sSharedPreferences == null && context != null) {
+            sSharedPreferences =
+                    context.createContextAsUser(UserHandle.SYSTEM, /* flags= */
+                            0).createDeviceProtectedStorageContext().getSharedPreferences(FILENAME,
+                            Context.MODE_PRIVATE);
+        }
+        return sSharedPreferences;
+    }
 
     /**
-     * Get a instance of DeviceCheckInClient object.
+     * Override the host name so that the client always connects to it instead
+     */
+    public static void setHostNameOverride(Context context, String override) {
+        getSharedPreferences(context).edit().putString(HOST_NAME_OVERRIDE, override).apply();
+    }
+
+    /**
+     * Get an instance of DeviceCheckInClient object.
      */
     public static DeviceCheckInClient getInstance(
+            Context context,
             String className,
             String hostName,
             int portNumber,
             Pair<String, String> apiKey,
             @Nullable String registeredId) {
-        if (sClient == null) {
-            synchronized (DeviceCheckInClient.class) {
-                try {
-                    // In case the initialization is already done by other thread use existing
-                    // instance.
-                    if (sClient != null) {
-                        return sClient;
-                    }
+        boolean useDebugClient = false;
+        String hostNameOverride = "";
+        if (Build.isDebuggable()) {
+            useDebugClient = getSharedPreferences(context).getBoolean(
+                    DEBUG_DEVICELOCK_CHECKIN, /* def= */ false);
+            hostNameOverride = getSharedPreferences(context).getString(
+                    HOST_NAME_OVERRIDE, /* def= */ "");
+            if (!hostNameOverride.isEmpty()) {
+                hostName = hostNameOverride;
+            }
+        }
+        synchronized (DeviceCheckInClient.class) {
+            try {
+                boolean createRequired =
+                        (sClient == null || sUseDebugClient != useDebugClient)
+                                || (registeredId != null && !registeredId.equals(sRegisteredId))
+                                || (hostName != null && !hostName.equals(sHostName))
+                                || (apiKey != null && !apiKey.equals(sApiKey));
+
+                if (createRequired) {
                     sHostName = hostName;
                     sPortNumber = portNumber;
                     sRegisteredId = registeredId;
                     sApiKey = apiKey;
-                    if (Build.isDebuggable() && SystemProperties.getBoolean(
-                            "debug.devicelock.checkin", true)) {
+                    sUseDebugClient = useDebugClient;
+                    if (Build.isDebuggable() && sUseDebugClient) {
                         className = DEVICE_CHECK_IN_CLIENT_DEBUG_CLASS_NAME;
                     }
                     LogUtil.d(TAG, "Creating instance for " + className);
                     Class<?> clazz = Class.forName(className);
                     sClient = (DeviceCheckInClient) clazz.getDeclaredConstructor().newInstance();
-                } catch (Exception e) {
-                    throw new RuntimeException("Failed to get DeviceCheckInClient instance", e);
                 }
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to get DeviceCheckInClient instance", e);
             }
         }
         return sClient;
@@ -106,6 +148,7 @@
      *                    DeviceLock program. Could be null if unavailable.
      * @return A class that encapsulate the response from the backend server.
      */
+    @WorkerThread
     public abstract IsDeviceInApprovedCountryGrpcResponse isDeviceInApprovedCountry(
             @Nullable String carrierInfo);
 
@@ -122,7 +165,6 @@
     /**
      * Reports the current provision state of the device.
      *
-     * @param reasonOfFailure            one of {@link SetupFailureReason}
      * @param lastReceivedProvisionState one of {@link DeviceProvisionState}.
      *                                   It must be the value from the response when this API
      *                                   was called last time. If this API is called for the first
@@ -136,7 +178,6 @@
      */
     @WorkerThread
     public abstract ReportDeviceProvisionStateGrpcResponse reportDeviceProvisionState(
-            @SetupFailureReason int reasonOfFailure,
             @DeviceProvisionState int lastReceivedProvisionState,
-            boolean isSuccessful);
+            boolean isSuccessful, @ProvisionFailureReason int failureReason);
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceFinalizeClient.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceFinalizeClient.java
index 00f1cac..c0ccf3b 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceFinalizeClient.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceFinalizeClient.java
@@ -16,11 +16,16 @@
 
 package com.android.devicelockcontroller.provision.grpc;
 
+import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.Build;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.util.Pair;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
 
 import com.android.devicelockcontroller.util.LogUtil;
 
@@ -32,41 +37,74 @@
  */
 public abstract class DeviceFinalizeClient {
     public static final String TAG = "DeviceFinalizeClient";
+    private static final String FILENAME = "debug-finalize-preferences";
+    private static final String HOST_NAME_OVERRIDE = "host.name.override";
     public static final String DEVICE_FINALIZE_CLIENT_DEBUG_CLASS_NAME =
             "com.android.devicelockcontroller.debug.DeviceFinalizeClientDebug";
     private static volatile DeviceFinalizeClient sClient;
-    protected static String sEnrollmentToken = "";
     protected static String sRegisteredId = "";
     protected static String sHostName = "";
     protected static int sPortNumber = 0;
     protected static Pair<String, String> sApiKey = new Pair<>("", "");
+    private static volatile boolean sUseDebugClient;
+    @Nullable
+    private static volatile SharedPreferences sSharedPreferences;
+
+    @Nullable
+    private static synchronized SharedPreferences getSharedPreferences(
+            @Nullable Context context) {
+        if (sSharedPreferences == null && context != null) {
+            sSharedPreferences =
+                    context.createContextAsUser(UserHandle.SYSTEM, /* flags= */
+                            0).createDeviceProtectedStorageContext().getSharedPreferences(FILENAME,
+                            Context.MODE_PRIVATE);
+        }
+        return sSharedPreferences;
+    }
 
     /**
-     * Get a instance of {@link DeviceFinalizeClient} object.
+     * Override the host name so that the client always connects to it instead
+     */
+    public static void setHostNameOverride(Context context, String override) {
+        getSharedPreferences(context).edit().putString(HOST_NAME_OVERRIDE, override).apply();
+    }
+
+    /**
+     * Get an instance of {@link DeviceFinalizeClient} object.
      * Note that, the arguments will be ignored after first initialization.
      */
     public static DeviceFinalizeClient getInstance(
+            Context context,
             String className,
             String hostName,
             int portNumber,
             Pair<String, String> apiKey,
-            String registeredId,
-            String enrollmentToken) {
-        if (sClient == null) {
+            String registeredId) {
+        boolean useDebugClient = false;
+        String hostNameOverride = "";
+        if (Build.isDebuggable()) {
+            useDebugClient =
+                    SystemProperties.getBoolean("debug.devicelock.finalize", /* def= */ false);
+            hostNameOverride = getSharedPreferences(context).getString(
+                    HOST_NAME_OVERRIDE, /* def= */ "");
+            if (!hostNameOverride.isEmpty()) {
+                hostName = hostNameOverride;
+            }
+        }
+        if (sClient == null || sUseDebugClient != useDebugClient) {
             synchronized (DeviceFinalizeClient.class) {
                 // In case the initialization is already done by other thread use existing
                 // instance.
-                if (sClient != null) {
+                if (sClient != null && sUseDebugClient == useDebugClient) {
                     return sClient;
                 }
                 sHostName = hostName;
                 sPortNumber = portNumber;
                 sRegisteredId = registeredId;
-                sEnrollmentToken = enrollmentToken;
                 sApiKey = apiKey;
+                sUseDebugClient = useDebugClient;
                 try {
-                    if (Build.isDebuggable() && SystemProperties.getBoolean(
-                            "debug.devicelock.finalize", true)) {
+                    if (Build.isDebuggable() && sUseDebugClient) {
                         className = DEVICE_FINALIZE_CLIENT_DEBUG_CLASS_NAME;
                     }
                     LogUtil.d(TAG, "Creating instance for " + className);
@@ -83,13 +121,14 @@
     /**
      * Reports that a device completed a Device Lock program.
      */
+    @WorkerThread
     public abstract ReportDeviceProgramCompleteResponse reportDeviceProgramComplete();
 
     /**
      * Class that used to indicate the successfulness / failure status of the response.
      */
     public static final class ReportDeviceProgramCompleteResponse extends
-            DeviceCheckInGrpcResponse {
+            GrpcResponse {
         public ReportDeviceProgramCompleteResponse() {
             super();
         }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/GetDeviceCheckInStatusGrpcResponse.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/GetDeviceCheckInStatusGrpcResponse.java
index 0e244b1..ead3a50 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/GetDeviceCheckInStatusGrpcResponse.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/GetDeviceCheckInStatusGrpcResponse.java
@@ -22,14 +22,14 @@
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceCheckInStatus;
 import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType;
 
-import java.time.Instant;
-
 import io.grpc.Status;
 
+import java.time.Instant;
+
 /**
  * An abstract class that is used to encapsulate the response for getting device check in status.
  */
-public abstract class GetDeviceCheckInStatusGrpcResponse extends DeviceCheckInGrpcResponse {
+public abstract class GetDeviceCheckInStatusGrpcResponse extends GrpcResponse {
     public GetDeviceCheckInStatusGrpcResponse() {
     }
 
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceCheckInGrpcResponse.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/GrpcResponse.java
similarity index 60%
rename from DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceCheckInGrpcResponse.java
rename to DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/GrpcResponse.java
index 16d8b00..c62271a 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/DeviceCheckInGrpcResponse.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/GrpcResponse.java
@@ -26,34 +26,41 @@
  * Base class for encapsulating a device check in server response. This class handles the Grpc
  * status response, subclasses will handle request specific responses.
  */
-abstract class DeviceCheckInGrpcResponse {
+abstract class GrpcResponse {
     @Nullable
     Status mStatus;
 
-    DeviceCheckInGrpcResponse() {
+    GrpcResponse() {
         mStatus = null;
     }
 
-    DeviceCheckInGrpcResponse(@NonNull Status status) {
+    GrpcResponse(@NonNull Status status) {
         mStatus = status;
     }
 
     public boolean hasRecoverableError() {
-        return mStatus != null && mStatus.getCode() == Code.UNAVAILABLE;
+        return mStatus != null
+                && (mStatus.getCode() == Code.UNAVAILABLE
+                || mStatus.getCode() == Code.UNKNOWN
+                || mStatus.getCode() == Code.INVALID_ARGUMENT
+                || mStatus.getCode() == Code.PERMISSION_DENIED
+                || mStatus.getCode() == Code.DEADLINE_EXCEEDED
+                || mStatus.getCode() == Code.RESOURCE_EXHAUSTED
+                || mStatus.getCode() == Code.ABORTED
+                || mStatus.getCode() == Code.DATA_LOSS
+                || mStatus.getCode() == Code.UNAUTHENTICATED);
     }
 
     public boolean isSuccessful() {
-        return mStatus == null;
-    }
-
-    public boolean isStatusAlreadyExists() {
-        return mStatus != null && mStatus.getCode() == Code.ALREADY_EXISTS;
+        return mStatus == null || mStatus.isOk();
     }
 
     public boolean hasFatalError() {
-        return mStatus != null
-                && mStatus.getCode() != Code.OK
-                && mStatus.getCode() != Code.UNAVAILABLE;
+        return !isSuccessful() && !hasRecoverableError() && !isInterrupted();
+    }
+
+    public boolean isInterrupted() {
+        return mStatus != null && (mStatus.getCause() instanceof InterruptedException);
     }
 
     @Override
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/IsDeviceInApprovedCountryGrpcResponse.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/IsDeviceInApprovedCountryGrpcResponse.java
index d2bb570..3298f18 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/IsDeviceInApprovedCountryGrpcResponse.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/IsDeviceInApprovedCountryGrpcResponse.java
@@ -25,7 +25,7 @@
  * device is in an approved country.
  */
 public abstract class IsDeviceInApprovedCountryGrpcResponse extends
-        DeviceCheckInGrpcResponse {
+        GrpcResponse {
     public IsDeviceInApprovedCountryGrpcResponse(@NonNull Status status) {
         super(status);
     }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/PauseDeviceProvisioningGrpcResponse.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/PauseDeviceProvisioningGrpcResponse.java
index 9ff2582..87f34ef 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/PauseDeviceProvisioningGrpcResponse.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/PauseDeviceProvisioningGrpcResponse.java
@@ -21,20 +21,14 @@
 import io.grpc.Status;
 
 /**
- * An abstract class that is used to encapsulate the response of pausing device provisioning
- * request.
+ * A class that is used to indicate the successfulness / failure status of the response of pausing
+ * device provisioning request.
  */
-public abstract class PauseDeviceProvisioningGrpcResponse extends DeviceCheckInGrpcResponse {
+public class PauseDeviceProvisioningGrpcResponse extends GrpcResponse {
     public PauseDeviceProvisioningGrpcResponse() {
     }
 
     public PauseDeviceProvisioningGrpcResponse(@NonNull Status status) {
         super(status);
     }
-
-    /**
-     * Check if provisioning should be forced.
-     * @return True if user can delay provisioning; false if user can not delay provisioning.
-     */
-    public abstract boolean shouldForceProvisioning();
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/ProvisioningConfiguration.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/ProvisioningConfiguration.java
index 252dcf3..27a981c 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/ProvisioningConfiguration.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/ProvisioningConfiguration.java
@@ -22,7 +22,6 @@
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_DISABLE_OUTGOING_CALLS;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_SETUP_ACTIVITY;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_SUPPORT_URL;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_TERMS_AND_CONDITIONS_URL;
 
@@ -42,10 +41,6 @@
     // The name of the provider of the kiosk app, e.g. "Foo Bar Inc".
 
     private final String mKioskAppPackageName;
-    // The package component of the activity of the kiosk app that the user
-    // would interact when the device is locked (i.e. this activity allows the
-    // user to make a payment), e.g. "com.foo.bar/com.foo.bar.MainActivity".
-    private final String mKioskAppMainActivity;
     // The list of apps that a user can use when the device is locked.
     private final List<String> mKioskAppAllowlistPackages;
     // Whether the user can make phone calls when the device is locked.
@@ -68,13 +63,12 @@
     public ProvisioningConfiguration(
             String kioskAppProviderName,
             String kioskAppPackageName,
-            String kioskAppMainActivity, List<String> kioskAppAllowlistPackages,
+            List<String> kioskAppAllowlistPackages,
             boolean kioskAppEnableOutgoingCalls, boolean kioskAppEnableEnableNotifications,
             boolean disallowInstallingFromUnknownSources, String termsAndConditionsUrl,
             String supportUrl) {
         mKioskAppProviderName = kioskAppProviderName;
         mKioskAppPackageName = kioskAppPackageName;
-        mKioskAppMainActivity = kioskAppMainActivity;
         mKioskAppAllowlistPackages = kioskAppAllowlistPackages;
         mKioskAppEnableOutgoingCalls = kioskAppEnableOutgoingCalls;
         mKioskAppEnableEnableNotifications = kioskAppEnableEnableNotifications;
@@ -89,8 +83,7 @@
     public Bundle toBundle() {
         final Bundle bundle = new Bundle();
         bundle.putString(EXTRA_KIOSK_PACKAGE, mKioskAppPackageName);
-        bundle.putString(EXTRA_KIOSK_SETUP_ACTIVITY, mKioskAppMainActivity);
-        bundle.putBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS, mKioskAppEnableOutgoingCalls);
+        bundle.putBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS, !mKioskAppEnableOutgoingCalls);
         bundle.putBoolean(EXTRA_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE,
                 mKioskAppEnableEnableNotifications);
         bundle.putStringArrayList(EXTRA_KIOSK_ALLOWLIST,
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/ReportDeviceProvisionStateGrpcResponse.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/ReportDeviceProvisionStateGrpcResponse.java
index 3beb8a6..b9b7006 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/ReportDeviceProvisionStateGrpcResponse.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/ReportDeviceProvisionStateGrpcResponse.java
@@ -17,7 +17,6 @@
 package com.android.devicelockcontroller.provision.grpc;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
 
@@ -27,7 +26,7 @@
  * An abstract class that is used to encapsulate the response for reporting the current state of
  * device provisioning.
  */
-public abstract class ReportDeviceProvisionStateGrpcResponse extends DeviceCheckInGrpcResponse {
+public abstract class ReportDeviceProvisionStateGrpcResponse extends GrpcResponse {
     public ReportDeviceProvisionStateGrpcResponse() {
         mStatus = null;
     }
@@ -47,15 +46,6 @@
     public abstract int getNextClientProvisionState();
 
     /**
-     * An enrollment token the device can use for future communication with the Device Lock backend
-     * server post-provisioning. This is only provided if device provisioning was a success.
-     *
-     * @return The enrollment token string.
-     */
-    @Nullable
-    public abstract String getEnrollmentToken();
-
-    /**
      * Get the number of days left until the device should factory reset because of a failed
      * provision. This number will be used to show a dismissible notification to the user.
      *
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/DeviceCheckInClientImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/DeviceCheckInClientImpl.java
index cee9244..a538428 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/DeviceCheckInClientImpl.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/DeviceCheckInClientImpl.java
@@ -16,23 +16,24 @@
 
 package com.android.devicelockcontroller.provision.grpc.impl;
 
-import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.CLIENT_PROVISION_FAILURE_REASON_DELETE_PACKAGE_FAILED;
-import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.CLIENT_PROVISION_FAILURE_REASON_DOWNLOAD_FAILED;
-import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.CLIENT_PROVISION_FAILURE_REASON_INSTALL_EXISTING_FAILED;
-import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.CLIENT_PROVISION_FAILURE_REASON_INSTALL_FAILED;
-import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.CLIENT_PROVISION_FAILURE_REASON_PACKAGE_DOES_NOT_EXIST;
-import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.CLIENT_PROVISION_FAILURE_REASON_SETUP_FAILED;
-import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.CLIENT_PROVISION_FAILURE_REASON_VERIFICATION_FAILED;
+import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.PROVISION_FAILURE_REASON_COUNTRY_INFO_UNAVAILABLE;
+import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.PROVISION_FAILURE_REASON_DEADLINE_PASSED;
+import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.PROVISION_FAILURE_REASON_NOT_IN_ELIGIBLE_COUNTRY;
+import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.PROVISION_FAILURE_REASON_PLAY_INSTALLATION_FAILED;
+import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.PROVISION_FAILURE_REASON_PLAY_TASK_UNAVAILABLE;
+import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.PROVISION_FAILURE_REASON_POLICY_ENFORCEMENT_FAILED;
+import static com.android.devicelockcontroller.proto.ClientProvisionFailureReason.PROVISION_FAILURE_REASON_UNSPECIFIED;
 
 import android.util.ArraySet;
 
 import androidx.annotation.Keep;
+import androidx.annotation.Nullable;
 
 import com.android.devicelockcontroller.common.DeviceId;
 import com.android.devicelockcontroller.common.DeviceLockConstants;
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceIdType;
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
-import com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason;
+import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason;
 import com.android.devicelockcontroller.proto.ClientDeviceIdentifier;
 import com.android.devicelockcontroller.proto.ClientProvisionFailureReason;
 import com.android.devicelockcontroller.proto.ClientProvisionState;
@@ -49,8 +50,7 @@
 import com.android.devicelockcontroller.provision.grpc.IsDeviceInApprovedCountryGrpcResponse;
 import com.android.devicelockcontroller.provision.grpc.PauseDeviceProvisioningGrpcResponse;
 import com.android.devicelockcontroller.provision.grpc.ReportDeviceProvisionStateGrpcResponse;
-
-import javax.annotation.Nullable;
+import com.android.devicelockcontroller.util.ThreadAsserts;
 
 import io.grpc.StatusRuntimeException;
 import io.grpc.okhttp.OkHttpChannelBuilder;
@@ -75,6 +75,7 @@
     public GetDeviceCheckInStatusGrpcResponse getDeviceCheckInStatus(
             ArraySet<DeviceId> deviceIds, String carrierInfo,
             @Nullable String fcmRegistrationToken) {
+        ThreadAsserts.assertWorkerThread("getDeviceCheckInStatus");
         try {
             final GetDeviceCheckInStatusGrpcResponse response =
                     new GetDeviceCheckInStatusGrpcResponseWrapper(
@@ -97,6 +98,7 @@
     @Override
     public IsDeviceInApprovedCountryGrpcResponse isDeviceInApprovedCountry(
             @Nullable String carrierInfo) {
+        ThreadAsserts.assertWorkerThread("isDeviceInApprovedCountry");
         try {
             return new IsDeviceInApprovedCountryGrpcResponseWrapper(
                     mBlockingStub.isDeviceInApprovedCountry(
@@ -108,20 +110,19 @@
 
     @Override
     public PauseDeviceProvisioningGrpcResponse pauseDeviceProvisioning(int reason) {
+        ThreadAsserts.assertWorkerThread("pauseDeviceProvisioning");
         try {
-            return new PauseDeviceProvisioningGrpcResponseWrapper(
-                    mBlockingStub.pauseDeviceProvisioning(
-                            createPauseDeviceProvisioningRequest(sRegisteredId, reason)));
-
+            mBlockingStub.pauseDeviceProvisioning(
+                    createPauseDeviceProvisioningRequest(sRegisteredId, reason));
+            return new PauseDeviceProvisioningGrpcResponse();
         } catch (StatusRuntimeException e) {
-            return new PauseDeviceProvisioningGrpcResponseWrapper(e.getStatus());
+            return new PauseDeviceProvisioningGrpcResponse(e.getStatus());
         }
     }
 
     /**
      * Reports the current provision state of the device.
      *
-     * @param reasonOfFailure            one of {@link SetupFailureReason}
      * @param lastReceivedProvisionState one of {@link DeviceProvisionState}.
      *                                   It must be the value from the response when this API
      *                                   was called last time. If this API is called for the first
@@ -134,13 +135,15 @@
      * @return A class that encapsulate the response from the backend server.
      */
     @Override
-    public ReportDeviceProvisionStateGrpcResponse reportDeviceProvisionState(int reasonOfFailure,
-            int lastReceivedProvisionState, boolean isSuccessful) {
+    public ReportDeviceProvisionStateGrpcResponse reportDeviceProvisionState(
+            int lastReceivedProvisionState, boolean isSuccessful,
+            @ProvisionFailureReason int reason) {
+        ThreadAsserts.assertWorkerThread("reportDeviceProvisionState");
         try {
             return new ReportDeviceProvisionStateGrpcResponseWrapper(
                     mBlockingStub.reportDeviceProvisionState(
-                            createReportDeviceProvisionStateRequest(reasonOfFailure,
-                                    lastReceivedProvisionState, isSuccessful, sRegisteredId)));
+                            createReportDeviceProvisionStateRequest(lastReceivedProvisionState,
+                                    isSuccessful, sRegisteredId, reason)));
         } catch (StatusRuntimeException e) {
             return new ReportDeviceProvisionStateGrpcResponseWrapper(e.getStatus());
         }
@@ -171,6 +174,9 @@
                             .setDeviceIdentifier(deviceId.getId()));
         }
         builder.setCarrierMccmnc(carrierInfo);
+        builder.setDeviceManufacturer(android.os.Build.MANUFACTURER);
+        builder.setDeviceModel(android.os.Build.MODEL);
+        builder.setDeviceInternalName(android.os.Build.DEVICE);
         return builder.build();
     }
 
@@ -193,37 +199,10 @@
     }
 
     private static ReportDeviceProvisionStateRequest createReportDeviceProvisionStateRequest(
-            @SetupFailureReason int reasonOfFailure,
             @DeviceProvisionState int lastReceivedProvisionState,
             boolean isSuccessful,
-            String registeredId) {
-        ClientProvisionFailureReason reason;
-        switch (reasonOfFailure) {
-            case SetupFailureReason.SETUP_FAILED:
-                reason = CLIENT_PROVISION_FAILURE_REASON_SETUP_FAILED;
-                break;
-            case SetupFailureReason.DOWNLOAD_FAILED:
-                reason = CLIENT_PROVISION_FAILURE_REASON_DOWNLOAD_FAILED;
-                break;
-            case SetupFailureReason.VERIFICATION_FAILED:
-                reason = CLIENT_PROVISION_FAILURE_REASON_VERIFICATION_FAILED;
-                break;
-            case SetupFailureReason.INSTALL_FAILED:
-                reason = CLIENT_PROVISION_FAILURE_REASON_INSTALL_FAILED;
-                break;
-            case SetupFailureReason.PACKAGE_DOES_NOT_EXIST:
-                reason = CLIENT_PROVISION_FAILURE_REASON_PACKAGE_DOES_NOT_EXIST;
-                break;
-            case SetupFailureReason.DELETE_PACKAGE_FAILED:
-                reason = CLIENT_PROVISION_FAILURE_REASON_DELETE_PACKAGE_FAILED;
-                break;
-            case SetupFailureReason.INSTALL_EXISTING_FAILED:
-                reason = CLIENT_PROVISION_FAILURE_REASON_INSTALL_EXISTING_FAILED;
-                break;
-            default:
-                throw new IllegalStateException(
-                        "Unexpected provision failure reason value: " + reasonOfFailure);
-        }
+            String registeredId,
+            @ProvisionFailureReason int reason) {
         ClientProvisionState state;
         switch (lastReceivedProvisionState) {
             case DeviceProvisionState.PROVISION_STATE_UNSPECIFIED:
@@ -248,12 +227,40 @@
                 throw new IllegalStateException(
                         "Unexpected value: " + lastReceivedProvisionState);
         }
-        return ReportDeviceProvisionStateRequest.newBuilder()
-                .setClientProvisionFailureReason(reason)
-                .setPreviousClientProvisionState(state)
-                .setProvisionSuccess(isSuccessful)
-                .setRegisteredDeviceIdentifier(registeredId)
-                .build();
+        ClientProvisionFailureReason reasonProto;
+        switch (reason) {
+            case ProvisionFailureReason.UNKNOWN_REASON:
+                reasonProto = PROVISION_FAILURE_REASON_UNSPECIFIED;
+                break;
+            case ProvisionFailureReason.PLAY_TASK_UNAVAILABLE:
+                reasonProto = PROVISION_FAILURE_REASON_PLAY_TASK_UNAVAILABLE;
+                break;
+            case ProvisionFailureReason.PLAY_INSTALLATION_FAILED:
+                reasonProto = PROVISION_FAILURE_REASON_PLAY_INSTALLATION_FAILED;
+                break;
+            case ProvisionFailureReason.COUNTRY_INFO_UNAVAILABLE:
+                reasonProto = PROVISION_FAILURE_REASON_COUNTRY_INFO_UNAVAILABLE;
+                break;
+            case ProvisionFailureReason.NOT_IN_ELIGIBLE_COUNTRY:
+                reasonProto = PROVISION_FAILURE_REASON_NOT_IN_ELIGIBLE_COUNTRY;
+                break;
+            case ProvisionFailureReason.POLICY_ENFORCEMENT_FAILED:
+                reasonProto = PROVISION_FAILURE_REASON_POLICY_ENFORCEMENT_FAILED;
+                break;
+            case ProvisionFailureReason.DEADLINE_PASSED:
+                reasonProto = PROVISION_FAILURE_REASON_DEADLINE_PASSED;
+                break;
+            default:
+                throw new IllegalArgumentException("Unexpected value: " + reason);
+        }
+        ReportDeviceProvisionStateRequest.Builder builder =
+                ReportDeviceProvisionStateRequest.newBuilder()
+                        .setPreviousClientProvisionState(state)
+                        .setProvisionSuccess(isSuccessful)
+                        .setRegisteredDeviceIdentifier(registeredId);
+        if (!isSuccessful) {
+            builder.setClientProvisionFailureReason(reasonProto);
+        }
+        return builder.build();
     }
-
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/DeviceFinalizeClientImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/DeviceFinalizeClientImpl.java
index 8d5b8ef..3e2cd9b 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/DeviceFinalizeClientImpl.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/DeviceFinalizeClientImpl.java
@@ -21,6 +21,7 @@
 import com.android.devicelockcontroller.proto.DeviceLockFinalizeServiceGrpc;
 import com.android.devicelockcontroller.proto.ReportDeviceProgramCompleteRequest;
 import com.android.devicelockcontroller.provision.grpc.DeviceFinalizeClient;
+import com.android.devicelockcontroller.util.ThreadAsserts;
 
 import io.grpc.StatusRuntimeException;
 import io.grpc.okhttp.OkHttpChannelBuilder;
@@ -45,10 +46,11 @@
      */
     @Override
     public ReportDeviceProgramCompleteResponse reportDeviceProgramComplete() {
+        ThreadAsserts.assertWorkerThread("reportDeviceProgramComplete");
         try {
             mBlockingStub.reportDeviceProgramComplete(
                     ReportDeviceProgramCompleteRequest.newBuilder().setRegisteredDeviceIdentifier(
-                            sRegisteredId).setEnrollmentToken(sEnrollmentToken).build());
+                            sRegisteredId).build());
             return new ReportDeviceProgramCompleteResponse();
         } catch (StatusRuntimeException e) {
             return new ReportDeviceProgramCompleteResponse(e.getStatus());
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/GetDeviceCheckInStatusGrpcResponseWrapper.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/GetDeviceCheckInStatusGrpcResponseWrapper.java
index a3d9173..d177fe2 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/GetDeviceCheckInStatusGrpcResponseWrapper.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/GetDeviceCheckInStatusGrpcResponseWrapper.java
@@ -36,10 +36,10 @@
 
 import com.google.protobuf.Timestamp;
 
-import java.time.Instant;
-
 import io.grpc.Status;
 
+import java.time.Instant;
+
 /**
  * Wrapper for response and status objects for a GetDeviceCheckinStatusResponse.
  */
@@ -108,7 +108,6 @@
         return new ProvisioningConfiguration(
                 info.getKioskAppProviderName(),
                 info.getKioskAppPackage(),
-                info.getKioskAppMainActivity(),
                 info.getKioskAppAllowlistPackagesList(),
                 info.getKioskAppEnableOutgoingCalls(),
                 info.getKioskAppEnableNotifications(),
@@ -124,15 +123,15 @@
             return ProvisioningType.TYPE_UNDEFINED;
         }
 
-        switch (mNextStep.getDeviceProvisioningInformation().getConfigurationType()) {
-            case CONFIGURATION_TYPE_FINANCED:
+        switch (mNextStep.getDeviceProvisioningInformation().getEnrollmentType()) {
+            case ENROLLMENT_TYPE_FINANCE:
                 return ProvisioningType.TYPE_FINANCED;
-            case CONFIGURATION_TYPE_SUBSIDY:
+            case ENROLLMENT_TYPE_SUBSIDY:
                 return ProvisioningType.TYPE_SUBSIDY;
-            case CONFIGURATION_TYPE_UNSPECIFIED:
+            case ENROLLMENT_TYPE_UNSPECIFIED:
                 return ProvisioningType.TYPE_UNDEFINED;
             default:
-                throw new IllegalArgumentException("Unknown configuration type");
+                throw new IllegalArgumentException("Unknown enrollment type");
         }
     }
 
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/PauseDeviceProvisioningGrpcResponseWrapper.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/PauseDeviceProvisioningGrpcResponseWrapper.java
deleted file mode 100644
index 917afb3..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/PauseDeviceProvisioningGrpcResponseWrapper.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.provision.grpc.impl;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.devicelockcontroller.proto.PauseDeviceProvisioningResponse;
-import com.android.devicelockcontroller.provision.grpc.PauseDeviceProvisioningGrpcResponse;
-
-import io.grpc.Status;
-
-/**
- * Wrapper for response and status objects for a PauseDeviceProvisioningResponse.
- */
-final class PauseDeviceProvisioningGrpcResponseWrapper extends PauseDeviceProvisioningGrpcResponse {
-    @Nullable
-    private final PauseDeviceProvisioningResponse mResponse;
-
-    //TODO: Consider to use a builder pattern to ensure at least one of the below fields is
-    // not null value so that we can eliminate the need of two separate constructors.
-    PauseDeviceProvisioningGrpcResponseWrapper(@NonNull Status status) {
-        super(status);
-        mResponse = null;
-    }
-
-    PauseDeviceProvisioningGrpcResponseWrapper(
-            @NonNull PauseDeviceProvisioningResponse response) {
-        mResponse = response;
-    }
-
-    @Override
-    public boolean shouldForceProvisioning() {
-        return mResponse != null && mResponse.getForceProvisioning();
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/ReportDeviceProvisionStateGrpcResponseWrapper.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/ReportDeviceProvisionStateGrpcResponseWrapper.java
index 6b99c43..1811dca 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/ReportDeviceProvisionStateGrpcResponseWrapper.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/grpc/impl/ReportDeviceProvisionStateGrpcResponseWrapper.java
@@ -77,18 +77,6 @@
     }
 
     /**
-     * An enrollment token the device can use for future communication with the Device Lock backend
-     * server post-provisioning. This is only provided if device provisioning was a success.
-     *
-     * @return The enrollment token string.
-     */
-    @Nullable
-    @Override
-    public String getEnrollmentToken() {
-        return mResponse != null ? mResponse.getEnrollmentToken() : null;
-    }
-
-    /**
      * Get the number of days left until the device should factory reset because of a failed
      * provision. This number will be used to show a dismissible notification to the user.
      *
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/AbstractCheckInWorker.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/AbstractCheckInWorker.java
index 8072691..492766f 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/AbstractCheckInWorker.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/AbstractCheckInWorker.java
@@ -21,8 +21,8 @@
 import android.util.Pair;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.work.Worker;
+import androidx.annotation.Nullable;
+import androidx.work.ListenableWorker;
 import androidx.work.WorkerParameters;
 
 import com.android.devicelockcontroller.R;
@@ -31,39 +31,43 @@
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 
+import java.time.Duration;
+
 /**
  * A base class for workers that execute gRPC requests with DeviceLock backend server.
  */
-public abstract class AbstractCheckInWorker extends Worker {
+public abstract class AbstractCheckInWorker extends ListenableWorker {
 
+    public static final Duration BACKOFF_DELAY = Duration.ofMinutes(1);
     static final String TAG = "CheckInWorker";
     final ListenableFuture<DeviceCheckInClient> mClient;
+    final ListeningExecutorService mExecutorService;
     final Context mContext;
 
     AbstractCheckInWorker(@NonNull Context context,
-            @NonNull WorkerParameters workerParams) {
-        super(context, workerParams);
-        Resources resources = context.getResources();
-        String hostName = resources.getString(R.string.check_in_server_host_name);
-        int portNumber = resources.getInteger(R.integer.check_in_server_port_number);
-        String className = resources.getString(R.string.device_check_in_client_class_name);
-        Pair<String, String> apikey = new Pair<>(
-                resources.getString(R.string.check_in_service_api_key_name),
-                resources.getString(R.string.check_in_service_api_key_value));
-        mClient = Futures.transform(GlobalParametersClient.getInstance().getRegisteredDeviceId(),
-                registeredId -> DeviceCheckInClient.getInstance(
-                        className, hostName, portNumber, apikey, registeredId),
-                MoreExecutors.directExecutor());
-        mContext = context;
-    }
-
-    @VisibleForTesting
-    AbstractCheckInWorker(@NonNull Context context,
-            @NonNull WorkerParameters workerParameters, DeviceCheckInClient client) {
+            @NonNull WorkerParameters workerParameters, @Nullable DeviceCheckInClient client,
+            ListeningExecutorService executorService) {
         super(context, workerParameters);
-        mClient = Futures.immediateFuture(client);
+        if (client != null) {
+            mClient = Futures.immediateFuture(client);
+        } else {
+            Resources resources = context.getResources();
+            String hostName = resources.getString(R.string.check_in_server_host_name);
+            int portNumber = resources.getInteger(R.integer.check_in_server_port_number);
+            String className = resources.getString(R.string.device_check_in_client_class_name);
+            Pair<String, String> apikey = new Pair<>(
+                    resources.getString(R.string.check_in_service_api_key_name),
+                    resources.getString(R.string.check_in_service_api_key_value));
+            mClient = Futures.transform(
+                    GlobalParametersClient.getInstance().getRegisteredDeviceId(),
+                    registeredId -> DeviceCheckInClient.getInstance(
+                            context, className, hostName, portNumber, apikey, registeredId),
+                    MoreExecutors.directExecutor());
+        }
         mContext = context;
+        mExecutorService = executorService;
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/AbstractDeviceCheckInHelper.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/AbstractDeviceCheckInHelper.java
index 5cacd62..b39c4d5 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/AbstractDeviceCheckInHelper.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/AbstractDeviceCheckInHelper.java
@@ -18,31 +18,23 @@
 
 import android.util.ArraySet;
 
-import androidx.annotation.NonNull;
 import androidx.annotation.WorkerThread;
 
 import com.android.devicelockcontroller.common.DeviceId;
 import com.android.devicelockcontroller.provision.grpc.GetDeviceCheckInStatusGrpcResponse;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
 
 /**
  * Base class that provides abstraction of utility APIs for device check-in.
  */
 public abstract class AbstractDeviceCheckInHelper {
 
-    /**
-     * Enqueue the DeviceCheckIn work request to WorkManager
-     *
-     * @param isExpedited If true, the work request should be expedited;
-     */
-    public abstract void enqueueDeviceCheckInWork(boolean isExpedited);
-
-    @NonNull
     abstract ArraySet<DeviceId> getDeviceUniqueIds();
 
-    @NonNull
     abstract String getCarrierInfo();
 
     @WorkerThread
     abstract boolean handleGetDeviceCheckInStatusResponse(
-            @NonNull GetDeviceCheckInStatusGrpcResponse response);
+            GetDeviceCheckInStatusGrpcResponse response,
+            DeviceLockControllerScheduler scheduler);
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInHelper.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInHelper.java
index 45a0058..e92d08a 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInHelper.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInHelper.java
@@ -25,31 +25,33 @@
 import static com.android.devicelockcontroller.common.DeviceLockConstants.STATUS_UNSPECIFIED;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.STOP_CHECK_IN;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.TOTAL_DEVICE_ID_TYPES;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.PROVISIONING_SUCCESS;
+import static com.android.devicelockcontroller.receivers.CheckInBootCompletedReceiver.disableCheckInBootCompletedReceiver;
+import static com.android.devicelockcontroller.stats.StatsLogger.CheckInRetryReason.CONFIG_UNAVAILABLE;
+import static com.android.devicelockcontroller.stats.StatsLogger.CheckInRetryReason.NETWORK_TIME_UNAVAILABLE;
+import static com.android.devicelockcontroller.stats.StatsLogger.CheckInRetryReason.RESPONSE_UNSPECIFIED;
 
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
+import android.os.SystemClock;
+import android.os.UserHandle;
 import android.telephony.TelephonyManager;
 import android.util.ArraySet;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 import androidx.annotation.WorkerThread;
-import androidx.work.BackoffPolicy;
-import androidx.work.Constraints;
-import androidx.work.ExistingWorkPolicy;
-import androidx.work.NetworkType;
-import androidx.work.OneTimeWorkRequest;
-import androidx.work.OutOfQuotaPolicy;
-import androidx.work.WorkManager;
 
 import com.android.devicelockcontroller.R;
 import com.android.devicelockcontroller.common.DeviceId;
-import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
 import com.android.devicelockcontroller.provision.grpc.GetDeviceCheckInStatusGrpcResponse;
 import com.android.devicelockcontroller.provision.grpc.ProvisioningConfiguration;
+import com.android.devicelockcontroller.receivers.ProvisionReadyReceiver;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
 import com.android.devicelockcontroller.storage.GlobalParametersClient;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.util.LogUtil;
@@ -59,60 +61,35 @@
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
+import java.time.DateTimeException;
 import java.time.Duration;
-import java.time.Instant;
-import java.util.Locale;
 
 /**
  * Helper class to perform the device check-in process with device lock backend server
  */
 public final class DeviceCheckInHelper extends AbstractDeviceCheckInHelper {
-    @VisibleForTesting
-    public static final String CHECK_IN_WORK_NAME = "checkIn";
     private static final String TAG = "DeviceCheckInHelper";
-    private static final int CHECK_IN_INTERVAL_HOURS = 1;
     private final Context mAppContext;
     private final TelephonyManager mTelephonyManager;
+    private final StatsLogger mStatsLogger;
 
     public DeviceCheckInHelper(Context appContext) {
         mAppContext = appContext;
         mTelephonyManager = mAppContext.getSystemService(TelephonyManager.class);
+        mStatsLogger = ((StatsLoggerProvider) mAppContext).getStatsLogger();
     }
 
-    /**
-     * Enqueue the DeviceCheckIn work request to WorkManager
-     *
-     * @param isExpedited If true, the work request should be expedited;
-     */
-    @Override
-    public void enqueueDeviceCheckInWork(boolean isExpedited) {
-        enqueueDeviceCheckInWork(isExpedited, Duration.ZERO);
+    private boolean hasGsm() {
+        return mAppContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_TELEPHONY_GSM);
     }
 
-    /**
-     * Enqueue the DeviceCheckIn work request to WorkManager
-     *
-     * @param isExpedited If true, the work request should be expedited;
-     * @param delay       The duration that need to be delayed before performing check-in.
-     */
-    private void enqueueDeviceCheckInWork(boolean isExpedited, Duration delay) {
-        LogUtil.i(TAG, "enqueueDeviceCheckInWork with delay: " + delay);
-        final OneTimeWorkRequest.Builder builder =
-                new OneTimeWorkRequest.Builder(DeviceCheckInWorker.class)
-                        .setConstraints(
-                                new Constraints.Builder().setRequiredNetworkType(
-                                        NetworkType.CONNECTED).build())
-                        .setInitialDelay(delay)
-                        .setBackoffCriteria(BackoffPolicy.LINEAR,
-                                Duration.ofHours(CHECK_IN_INTERVAL_HOURS));
-        if (isExpedited) builder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST);
-        WorkManager.getInstance(mAppContext).enqueueUniqueWork(CHECK_IN_WORK_NAME,
-                ExistingWorkPolicy.REPLACE, builder.build());
+    private boolean hasCdma() {
+        return mAppContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_TELEPHONY_CDMA);
     }
 
-
     @Override
-    @NonNull
     ArraySet<DeviceId> getDeviceUniqueIds() {
         final int deviceIdTypeBitmap = mAppContext.getResources().getInteger(
                 R.integer.device_id_type_bitmap);
@@ -133,7 +110,7 @@
         if (maximumIdCount == 0) return deviceIds;
 
         for (int i = 0; i < totalSlotCount; i++) {
-            if ((deviceIdTypeBitmap & (1 << DEVICE_ID_TYPE_IMEI)) != 0) {
+            if (hasGsm() && (deviceIdTypeBitmap & (1 << DEVICE_ID_TYPE_IMEI)) != 0) {
                 final String imei = mTelephonyManager.getImei(i);
 
                 if (imei != null) {
@@ -141,7 +118,7 @@
                 }
             }
 
-            if ((deviceIdTypeBitmap & (1 << DEVICE_ID_TYPE_MEID)) != 0) {
+            if (hasCdma() && (deviceIdTypeBitmap & (1 << DEVICE_ID_TYPE_MEID)) != 0) {
                 final String meid = mTelephonyManager.getMeid(i);
 
                 if (meid != null) {
@@ -154,37 +131,59 @@
     }
 
     @Override
-    @NonNull
     String getCarrierInfo() {
-        // TODO(b/267507927): Figure out if we need carrier info of all sims.
         return mTelephonyManager.getSimOperator();
     }
 
     @Override
     @WorkerThread
     boolean handleGetDeviceCheckInStatusResponse(
-            @NonNull GetDeviceCheckInStatusGrpcResponse response) {
+            GetDeviceCheckInStatusGrpcResponse response,
+            DeviceLockControllerScheduler scheduler) {
         Futures.getUnchecked(GlobalParametersClient.getInstance().setRegisteredDeviceId(
                 response.getRegisteredDeviceIdentifier()));
-        LogUtil.d(TAG, "check in succeed: " + response.getDeviceCheckInStatus());
+        LogUtil.d(TAG, "check in response: " + response.getDeviceCheckInStatus());
         switch (response.getDeviceCheckInStatus()) {
             case READY_FOR_PROVISION:
-                PolicyObjectsInterface policies =
-                        (PolicyObjectsInterface) mAppContext.getApplicationContext();
-                return handleProvisionReadyResponse(
-                        response,
-                        policies.getStateController(),
-                        policies.getPolicyController());
+                boolean result = handleProvisionReadyResponse(response);
+                disableCheckInBootCompletedReceiver(mAppContext);
+                return result;
             case RETRY_CHECK_IN:
-                Duration delay = Duration.between(Instant.now(), response.getNextCheckInTime());
-                delay = delay.isNegative() ? Duration.ZERO : delay;
-                enqueueDeviceCheckInWork(false, delay);
-                return true;
+                try {
+                    Duration delay = Duration.between(
+                            SystemClock.currentNetworkTimeClock().instant(),
+                            response.getNextCheckInTime());
+                    // Retry immediately if next check in time is in the past.
+                    delay = delay.isNegative() ? Duration.ZERO : delay;
+                    scheduler.scheduleRetryCheckInWork(delay);
+                    return true;
+                } catch (DateTimeException e) {
+                    LogUtil.e(TAG, "No network time is available!");
+                    mStatsLogger.logCheckInRetry(NETWORK_TIME_UNAVAILABLE);
+                    return false;
+                }
             case STOP_CHECK_IN:
-                Futures.getUnchecked(GlobalParametersClient.getInstance().setNeedCheckIn(false));
+                final ListenableFuture<Void> clearRestrictionsFuture =
+                        ((PolicyObjectsProvider) mAppContext).getFinalizationController()
+                                .notifyRestrictionsCleared();
+                Futures.addCallback(clearRestrictionsFuture,
+                        new FutureCallback<>() {
+                            @Override
+                            public void onSuccess(Void result) {
+                                // no-op
+                            }
+
+                            @Override
+                            public void onFailure(Throwable t) {
+                                LogUtil.e(TAG, "Failed to clear restrictions", t);
+                            }
+                        }, MoreExecutors.directExecutor()
+                );
+                disableCheckInBootCompletedReceiver(mAppContext);
                 return true;
             case STATUS_UNSPECIFIED:
             default:
+                mStatsLogger.logCheckInRetry(RESPONSE_UNSPECIFIED);
                 return false;
         }
     }
@@ -192,14 +191,14 @@
     @VisibleForTesting
     @WorkerThread
     boolean handleProvisionReadyResponse(
-            @NonNull GetDeviceCheckInStatusGrpcResponse response,
-            DeviceStateController stateController,
-            DevicePolicyController devicePolicyController) {
-        Futures.getUnchecked(GlobalParametersClient.getInstance().setProvisionForced(
+            @NonNull GetDeviceCheckInStatusGrpcResponse response) {
+        GlobalParametersClient globalParametersClient = GlobalParametersClient.getInstance();
+        Futures.getUnchecked(globalParametersClient.setProvisionForced(
                 response.isProvisionForced()));
         final ProvisioningConfiguration configuration = response.getProvisioningConfig();
         if (configuration == null) {
             LogUtil.e(TAG, "Provisioning Configuration is not provided by server!");
+            mStatsLogger.logCheckInRetry(CONFIG_UNAVAILABLE);
             return false;
         }
         final Bundle provisionBundle = configuration.toBundle();
@@ -208,43 +207,10 @@
                 response.isProvisioningMandatory());
         Futures.getUnchecked(
                 SetupParametersClient.getInstance().createPrefs(provisionBundle));
-        setProvisionSucceeded(stateController, devicePolicyController, mAppContext,
-                response.isProvisioningMandatory());
+        Futures.getUnchecked(globalParametersClient.setProvisionReady(true));
+        mAppContext.sendBroadcastAsUser(
+                new Intent(mAppContext, ProvisionReadyReceiver.class),
+                UserHandle.ALL);
         return true;
     }
-
-    /**
-     * Helper method to set the state for PROVISIONING_SUCCESS event.
-     */
-    public static void setProvisionSucceeded(DeviceStateController stateController,
-            DevicePolicyController devicePolicyController,
-            Context mAppContext, final boolean isMandatory) {
-        FutureCallback<Void> futureCallback = new FutureCallback<>() {
-            @Override
-            public void onSuccess(Void result) {
-                LogUtil.i(TAG,
-                        String.format(Locale.US,
-                                "State transition succeeded for event: %s",
-                                DeviceStateController.eventToString(PROVISIONING_SUCCESS)));
-                devicePolicyController.enqueueStartLockTaskModeWorker(isMandatory);
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                //TODO: Reset the state to where it can successfully transition.
-                LogUtil.e(TAG,
-                        String.format(Locale.US,
-                                "State transition failed for event: %s",
-                                DeviceStateController.eventToString(PROVISIONING_SUCCESS)), t);
-            }
-        };
-        mAppContext.getMainExecutor().execute(
-                () -> {
-                    ListenableFuture<Void> tasks = Futures.whenAllSucceed(
-                                    GlobalParametersClient.getInstance().setNeedCheckIn(false),
-                                    stateController.setNextStateForEvent(PROVISIONING_SUCCESS))
-                            .call(() -> null, MoreExecutors.directExecutor());
-                    Futures.addCallback(tasks, futureCallback, MoreExecutors.directExecutor());
-                });
-    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInWorker.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInWorker.java
index 88b3f5a..563c032 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInWorker.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInWorker.java
@@ -16,19 +16,28 @@
 
 package com.android.devicelockcontroller.provision.worker;
 
+import static com.android.devicelockcontroller.receivers.CheckInBootCompletedReceiver.disableCheckInBootCompletedReceiver;
+
 import android.content.Context;
-import android.util.ArraySet;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 import androidx.work.WorkerParameters;
 
-import com.android.devicelockcontroller.common.DeviceId;
+import com.android.devicelockcontroller.FcmRegistrationTokenProvider;
 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
 import com.android.devicelockcontroller.provision.grpc.GetDeviceCheckInStatusGrpcResponse;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
 import com.android.devicelockcontroller.util.LogUtil;
 
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+import java.time.Duration;
 
 /**
  * A worker class dedicated to execute the check-in operation for device lock program.
@@ -37,38 +46,87 @@
 
     private final AbstractDeviceCheckInHelper mCheckInHelper;
 
+    private final StatsLogger mStatsLogger;
+
+    @VisibleForTesting
+    static final Duration RETRY_ON_FAILURE_DELAY = Duration.ofDays(1);
+
     public DeviceCheckInWorker(@NonNull Context context,
-            @NonNull WorkerParameters workerParams) {
-        super(context, workerParams);
-        mCheckInHelper = new DeviceCheckInHelper(context);
+            @NonNull WorkerParameters workerParams, ListeningExecutorService executorService) {
+        this(context, workerParams, new DeviceCheckInHelper(context), null, executorService);
     }
 
     @VisibleForTesting
     DeviceCheckInWorker(@NonNull Context context, @NonNull WorkerParameters workerParameters,
-            AbstractDeviceCheckInHelper helper, DeviceCheckInClient client) {
-        super(context, workerParameters, client);
+            AbstractDeviceCheckInHelper helper, DeviceCheckInClient client,
+            ListeningExecutorService executorService) {
+        super(context, workerParameters, client, executorService);
         mCheckInHelper = helper;
+        StatsLoggerProvider loggerProvider =
+                (StatsLoggerProvider) context.getApplicationContext();
+        mStatsLogger = loggerProvider.getStatsLogger();
     }
 
     @NonNull
     @Override
-    public Result doWork() {
-        LogUtil.i(TAG, "perform check-in request");
-        final ArraySet<DeviceId> deviceIds = mCheckInHelper.getDeviceUniqueIds();
-        final String carrierInfo = mCheckInHelper.getCarrierInfo();
-        if (deviceIds.isEmpty()) {
-            LogUtil.w(TAG, "CheckIn failed. No device identifier available!");
-            return Result.failure();
-        }
-        final GetDeviceCheckInStatusGrpcResponse response =
-                Futures.getUnchecked(mClient).getDeviceCheckInStatus(
-                        deviceIds, carrierInfo, /* fcmRegistrationToken= */ null);
-        if (response.isSuccessful()) {
-            return mCheckInHelper.handleGetDeviceCheckInStatusResponse(response)
-                    ? Result.success()
-                    : Result.retry();
-        }
-        LogUtil.w(TAG, "CheckIn failed: " + response);
-        return Result.failure();
+    public ListenableFuture<Result> startWork() {
+        DeviceLockControllerSchedulerProvider schedulerProvider =
+                (DeviceLockControllerSchedulerProvider) mContext;
+        DeviceLockControllerScheduler scheduler =
+                schedulerProvider.getDeviceLockControllerScheduler();
+        return Futures.transformAsync(
+                mExecutorService.submit(mCheckInHelper::getDeviceUniqueIds),
+                deviceIds -> {
+                    if (deviceIds.isEmpty()) {
+                        LogUtil.w(TAG, "CheckIn failed. No device identifier available!");
+                        // This device cannot be financed since it does not have any suitable
+                        // device identifiers. Similarly to STOP_CHECK_IN, disable the check in
+                        // boot completed receiver.
+                        disableCheckInBootCompletedReceiver(mContext);
+
+                        return Futures.immediateFuture(Result.failure());
+                    }
+                    String carrierInfo = mCheckInHelper.getCarrierInfo();
+                    Context applicationContext = mContext.getApplicationContext();
+                    ListenableFuture<String> fcmRegistrationToken =
+                            ((FcmRegistrationTokenProvider) applicationContext)
+                                    .getFcmRegistrationToken();
+                    return Futures.whenAllSucceed(mClient, fcmRegistrationToken).call(() -> {
+                        DeviceCheckInClient client = Futures.getDone(mClient);
+                        String fcmToken = Futures.getDone(fcmRegistrationToken);
+
+                        GetDeviceCheckInStatusGrpcResponse response =
+                                client.getDeviceCheckInStatus(
+                                        deviceIds, carrierInfo, fcmToken);
+                        mStatsLogger.logGetDeviceCheckInStatus();
+                        if (response.hasRecoverableError()) {
+                            LogUtil.w(TAG, "Check-in failed w/ recoverable error" + response
+                                    + "\nRetrying...");
+                            mStatsLogger.logCheckInRetry(
+                                    StatsLogger.CheckInRetryReason.RPC_FAILURE);
+                            return Result.retry();
+                        }
+                        if (response.isSuccessful()) {
+                            boolean isResponseHandlingSuccessful = mCheckInHelper
+                                    .handleGetDeviceCheckInStatusResponse(response, scheduler);
+                            if (isResponseHandlingSuccessful) {
+                                mStatsLogger.logSuccessfulCheckIn();
+                            }
+                            return isResponseHandlingSuccessful ? Result.success() : Result.retry();
+                        }
+
+                        if (response.isInterrupted()) {
+                            LogUtil.d(TAG, "Check-in interrupted");
+                            return Result.failure();
+                        }
+
+                        LogUtil.e(TAG, "CheckIn failed: " + response + "\nRetry check-in in: "
+                                + RETRY_ON_FAILURE_DELAY);
+                        scheduler.scheduleRetryCheckInWork(RETRY_ON_FAILURE_DELAY);
+                        mStatsLogger.logCheckInRetry(
+                                StatsLogger.CheckInRetryReason.RPC_FAILURE);
+                        return Result.failure();
+                    }, mExecutorService);
+                }, mExecutorService);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/IsDeviceInApprovedCountryWorker.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/IsDeviceInApprovedCountryWorker.java
index b8a935c..b8f3ae4 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/IsDeviceInApprovedCountryWorker.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/IsDeviceInApprovedCountryWorker.java
@@ -17,6 +17,7 @@
 package com.android.devicelockcontroller.provision.worker;
 
 import android.content.Context;
+import android.telephony.TelephonyManager;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
@@ -25,42 +26,59 @@
 
 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
 import com.android.devicelockcontroller.provision.grpc.IsDeviceInApprovedCountryGrpcResponse;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+import com.android.devicelockcontroller.util.LogUtil;
 
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+import java.util.Objects;
 
 /**
  * A worker class dedicated to check whether device is in approved country.
+ * Note that this worker always returns {@link androidx.work.ListenableWorker.Result.Success}
+ * regardless of the success of the underlying rpc.
+ * This worker only returns a successful result if it gets the country eligibility information from
+ * the server.
  */
-public final class IsDeviceInApprovedCountryWorker extends
-        AbstractCheckInWorker {
+public final class IsDeviceInApprovedCountryWorker extends AbstractCheckInWorker {
 
-    public static final String KEY_CARRIER_INFO = "carrier-info";
     public static final String KEY_IS_IN_APPROVED_COUNTRY = "is-in-approved-country";
 
-    IsDeviceInApprovedCountryWorker(@NonNull Context context,
-            @NonNull WorkerParameters workerParams) {
-        super(context, workerParams);
+    public IsDeviceInApprovedCountryWorker(@NonNull Context context,
+            @NonNull WorkerParameters workerParams, ListeningExecutorService executorService) {
+        super(context, workerParams, null, executorService);
     }
 
     @VisibleForTesting
     IsDeviceInApprovedCountryWorker(@NonNull Context context,
             @NonNull WorkerParameters workerParameters,
-            DeviceCheckInClient client) {
-        super(context, workerParameters, client);
+            DeviceCheckInClient client, ListeningExecutorService executorService) {
+        super(context, workerParameters, client, executorService);
     }
 
     @NonNull
     @Override
-    public Result doWork() {
-        String carrierInfo = getInputData().getString(KEY_CARRIER_INFO);
-        IsDeviceInApprovedCountryGrpcResponse response = Futures.getUnchecked(
-                mClient).isDeviceInApprovedCountry(carrierInfo);
-
-        if (response.isSuccessful()) {
-            return Result.success(new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY,
-                    response.isDeviceInApprovedCountry()).build());
-        }
-        return Result.failure();
+    public ListenableFuture<Result> startWork() {
+        return Futures.transform(mClient, client -> {
+            String carrierInfo = Objects.requireNonNull(
+                    mContext.getSystemService(TelephonyManager.class)).getSimOperator();
+            IsDeviceInApprovedCountryGrpcResponse response =
+                    client.isDeviceInApprovedCountry(carrierInfo);
+            ((StatsLoggerProvider) mContext.getApplicationContext()).getStatsLogger()
+                    .logIsDeviceInApprovedCountry();
+            if (response.hasRecoverableError()) {
+                LogUtil.w(TAG, "Is in approve country failed w/ recoverable error" + response
+                        + "\nRetrying...");
+                return Result.retry();
+            }
+            Data.Builder builder = new Data.Builder();
+            if (response.isSuccessful()) {
+                return Result.success(builder.putBoolean(KEY_IS_IN_APPROVED_COUNTRY,
+                        response.isDeviceInApprovedCountry()).build());
+            }
+            return Result.failure();
+        }, mExecutorService);
     }
-
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/PauseProvisioningWorker.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/PauseProvisioningWorker.java
index 3138839..8dae606 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/PauseProvisioningWorker.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/PauseProvisioningWorker.java
@@ -23,36 +23,39 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
+import androidx.work.BackoffPolicy;
 import androidx.work.Constraints;
 import androidx.work.Data;
 import androidx.work.ExistingWorkPolicy;
 import androidx.work.NetworkType;
 import androidx.work.OneTimeWorkRequest;
+import androidx.work.Operation;
 import androidx.work.WorkManager;
 import androidx.work.WorkerParameters;
 
-import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
 import com.android.devicelockcontroller.provision.grpc.PauseDeviceProvisioningGrpcResponse;
-import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
 import com.android.devicelockcontroller.util.LogUtil;
 
+import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
-
-import java.time.Duration;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 
 /**
- * A worker class dedicated to request pause of provisioning for device lock program.
+ * Despite the naming, this worker class is only to report provision has been paused by user to
+ * backend server.
  */
 public final class PauseProvisioningWorker extends AbstractCheckInWorker {
-
     private static final String KEY_PAUSE_DEVICE_PROVISIONING_REASON =
             "PAUSE_DEVICE_PROVISIONING_REASON";
-    private static final String REPORT_PROVISION_PAUSED_BY_USER_WORK =
+    public static final String REPORT_PROVISION_PAUSED_BY_USER_WORK =
             "report-provision-paused-by-user";
-    @VisibleForTesting
-    static final int PROVISION_PAUSED_HOUR = 1;
+
+    private final StatsLogger mStatsLogger;
 
     /**
      * Report provision has been paused by user to backend server by running a work item.
@@ -67,44 +70,61 @@
         OneTimeWorkRequest work =
                 new OneTimeWorkRequest.Builder(PauseProvisioningWorker.class)
                         .setConstraints(constraints)
+                        .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, BACKOFF_DELAY)
                         .setInputData(inputData)
                         .build();
-        workManager.enqueueUniqueWork(REPORT_PROVISION_PAUSED_BY_USER_WORK,
-                ExistingWorkPolicy.REPLACE, work);
+        ListenableFuture<Operation.State.SUCCESS> result =
+                workManager.enqueueUniqueWork(REPORT_PROVISION_PAUSED_BY_USER_WORK,
+                        ExistingWorkPolicy.KEEP, work).getResult();
+        Futures.addCallback(result,
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Operation.State.SUCCESS result) {
+                        // no-op
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        // Log an error but don't reset the device (non critical failure).
+                        LogUtil.e(TAG, "Failed to enqueue 'Report provision paused' work", t);
+                    }
+                },
+                MoreExecutors.directExecutor()
+        );
     }
 
     public PauseProvisioningWorker(@NonNull Context context,
-            @NonNull WorkerParameters workerParams) {
-        super(context, workerParams);
+            @NonNull WorkerParameters workerParams, ListeningExecutorService executorService) {
+        this(context, workerParams, null, executorService);
     }
 
     @VisibleForTesting
     PauseProvisioningWorker(@NonNull Context context, @NonNull WorkerParameters workerParams,
-            DeviceCheckInClient client) {
-        super(context, workerParams, client);
+            DeviceCheckInClient client, ListeningExecutorService executorService) {
+        super(context, workerParams, client, executorService);
+        StatsLoggerProvider loggerProvider =
+                (StatsLoggerProvider) context.getApplicationContext();
+        mStatsLogger = loggerProvider.getStatsLogger();
     }
 
     @NonNull
     @Override
-    public Result doWork() {
-        final int reason = getInputData().getInt(KEY_PAUSE_DEVICE_PROVISIONING_REASON,
-                REASON_UNSPECIFIED);
-        PauseDeviceProvisioningGrpcResponse response =
-                Futures.getUnchecked(mClient).pauseDeviceProvisioning(reason);
-        if (response.isSuccessful()) {
-            boolean shouldForceProvisioning = response.shouldForceProvisioning();
-            Futures.getUnchecked(GlobalParametersClient.getInstance().setProvisionForced(
-                    shouldForceProvisioning));
-            DevicePolicyController policyController =
-                    ((PolicyObjectsInterface) mContext.getApplicationContext())
-                            .getPolicyController();
-            //TODO: Cancel the work if user starts provisioning within 1 hr.
-            policyController.enqueueStartLockTaskModeWorkerWithDelay(
-                    /* isMandatory= */ false,
-                    Duration.ofHours(PROVISION_PAUSED_HOUR));
-            return Result.success();
-        }
-        LogUtil.w(TAG, "Pause provisioning request failed: " + response);
-        return Result.failure();
+    public ListenableFuture<Result> startWork() {
+        return Futures.transform(mClient, client -> {
+            int reason = getInputData().getInt(KEY_PAUSE_DEVICE_PROVISIONING_REASON,
+                    REASON_UNSPECIFIED);
+            PauseDeviceProvisioningGrpcResponse response = client.pauseDeviceProvisioning(reason);
+            if (response.hasRecoverableError()) {
+                LogUtil.w(TAG, "Report paused provisioning failed w/ recoverable error" + response
+                        + "\nRetrying...");
+                return Result.retry();
+            }
+            if (response.isSuccessful()) {
+                mStatsLogger.logPauseDeviceProvisioning();
+                return Result.success();
+            }
+            LogUtil.e(TAG, "Pause provisioning request failed: " + response);
+            return Result.failure();
+        }, mExecutorService);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/ReportDeviceLockProgramCompleteWorker.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/ReportDeviceLockProgramCompleteWorker.java
index bd7edad..b510d08 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/ReportDeviceLockProgramCompleteWorker.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/ReportDeviceLockProgramCompleteWorker.java
@@ -21,88 +21,87 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
-import androidx.work.Constraints;
-import androidx.work.ExistingWorkPolicy;
-import androidx.work.NetworkType;
-import androidx.work.OneTimeWorkRequest;
-import androidx.work.WorkManager;
-import androidx.work.Worker;
+import androidx.work.ListenableWorker;
 import androidx.work.WorkerParameters;
 
 import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.policy.FinalizationController;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
 import com.android.devicelockcontroller.provision.grpc.DeviceFinalizeClient;
 import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.util.LogUtil;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.concurrent.Future;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 
 /**
  * A worker class dedicated to report completion of the device lock program.
  */
-public final class ReportDeviceLockProgramCompleteWorker extends Worker {
+public final class ReportDeviceLockProgramCompleteWorker extends ListenableWorker {
 
-    private static final String REPORT_DEVICE_LOCK_PROGRAM_COMPLETE_WORK_NAME =
+    private static final String TAG = ReportDeviceLockProgramCompleteWorker.class.getSimpleName();
+
+    public static final String REPORT_DEVICE_LOCK_PROGRAM_COMPLETE_WORK_NAME =
             "report-device-lock-program-complete";
-    private final Future<DeviceFinalizeClient> mClient;
-
-    /**
-     * Report that this device has completed the devicelock program by enqueueing a work item.
-     */
-    public static void reportDeviceLockProgramComplete(WorkManager workManager) {
-        Constraints constraints = new Constraints.Builder()
-                .setRequiredNetworkType(NetworkType.CONNECTED)
-                .build();
-        OneTimeWorkRequest work =
-                new OneTimeWorkRequest.Builder(ReportDeviceLockProgramCompleteWorker.class)
-                        .setConstraints(constraints)
-                        .build();
-        workManager.enqueueUniqueWork(
-                REPORT_DEVICE_LOCK_PROGRAM_COMPLETE_WORK_NAME,
-                ExistingWorkPolicy.REPLACE, work);
-    }
+    private final ListenableFuture<DeviceFinalizeClient> mClient;
+    private final PolicyObjectsProvider mPolicyObjectsProvider;
 
     public ReportDeviceLockProgramCompleteWorker(@NonNull Context context,
-            @NonNull WorkerParameters workerParams) {
-        super(context, workerParams);
-        final String hostName = context.getResources().getString(
-                R.string.check_in_server_host_name);
-        final int portNumber = context.getResources().getInteger(
-                R.integer.check_in_server_port_number);
-        final String className = context.getResources().getString(
-                R.string.device_finalize_client_class_name);
-        final Pair<String, String> apikey = new Pair<>(
-                context.getResources().getString(R.string.finalize_service_api_key_name),
-                context.getResources().getString(R.string.finalize_service_api_key_value));
-        ListenableFuture<String> registeredDeviceId =
-                GlobalParametersClient.getInstance().getRegisteredDeviceId();
-        ListenableFuture<String> enrollmentToken =
-                GlobalParametersClient.getInstance().getEnrollmentToken();
-        mClient = Futures.whenAllSucceed(registeredDeviceId, enrollmentToken).call(
-                () -> DeviceFinalizeClient.getInstance(className, hostName, portNumber, apikey,
-                        Futures.getDone(registeredDeviceId), Futures.getDone(enrollmentToken)),
-                context.getMainExecutor());
+            @NonNull WorkerParameters workerParams, ListeningExecutorService executorService) {
+        this(context,
+                workerParams,
+                null,
+                ((PolicyObjectsProvider) context.getApplicationContext()),
+                executorService);
     }
 
     @VisibleForTesting
     ReportDeviceLockProgramCompleteWorker(@NonNull Context context,
-            @NonNull WorkerParameters workerParams, DeviceFinalizeClient client) {
+            @NonNull WorkerParameters workerParams,
+            DeviceFinalizeClient client,
+            PolicyObjectsProvider policyObjectsProvider,
+            ListeningExecutorService executorService) {
         super(context, workerParams);
-        mClient = Futures.immediateFuture(client);
+        if (client == null) {
+            final String hostName = context.getResources().getString(
+                    R.string.finalize_server_host_name);
+            final int portNumber = context.getResources().getInteger(
+                    R.integer.finalize_server_port_number);
+            final String className = context.getResources().getString(
+                    R.string.device_finalize_client_class_name);
+            final Pair<String, String> apikey = new Pair<>(
+                    context.getResources().getString(R.string.finalize_service_api_key_name),
+                    context.getResources().getString(R.string.finalize_service_api_key_value));
+            ListenableFuture<String> registeredDeviceId =
+                    GlobalParametersClient.getInstance().getRegisteredDeviceId();
+            mClient = Futures.transform(registeredDeviceId,
+                    id -> DeviceFinalizeClient.getInstance(context, className, hostName,
+                            portNumber, apikey, id), executorService);
+        } else {
+            mClient = Futures.immediateFuture(client);
+        }
+        mPolicyObjectsProvider = policyObjectsProvider;
     }
 
     @NonNull
     @Override
-    public Result doWork() {
-        DeviceFinalizeClient.ReportDeviceProgramCompleteResponse response =
-                Futures.getUnchecked(mClient).reportDeviceProgramComplete();
-        if (response.isSuccessful()) {
-            return Result.success();
-        } else if (response.hasRecoverableError()) {
-            return Result.retry();
-        } else {
-            return Result.failure();
-        }
+    public ListenableFuture<Result> startWork() {
+        FinalizationController controller = mPolicyObjectsProvider.getFinalizationController();
+        return Futures.transformAsync(mClient, client -> {
+            DeviceFinalizeClient.ReportDeviceProgramCompleteResponse response =
+                    client.reportDeviceProgramComplete();
+            if (response.hasRecoverableError()) {
+                LogUtil.w(TAG, "Report finalization failed w/ recoverable error" + response
+                        + "\nRetrying...");
+                return Futures.immediateFuture(Result.retry());
+            }
+            ListenableFuture<Void> notifyFuture =
+                    controller.notifyFinalizationReportResult(response);
+            return Futures.transform(notifyFuture,
+                    unused -> response.isSuccessful() ? Result.success() : Result.failure(),
+                    MoreExecutors.directExecutor());
+        }, getBackgroundExecutor());
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorker.java b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorker.java
index 01c9b69..35b0bd1 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorker.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorker.java
@@ -16,98 +16,84 @@
 
 package com.android.devicelockcontroller.provision.worker;
 
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_DISMISSIBLE_UI;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_FACTORY_RESET;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_PERSISTENT_UI;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_RETRY;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_SUCCESS;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_UNSPECIFIED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.DEADLINE_PASSED;
 
 import android.content.Context;
-import android.text.TextUtils;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
+import androidx.work.BackoffPolicy;
 import androidx.work.Constraints;
 import androidx.work.Data;
 import androidx.work.ExistingWorkPolicy;
 import androidx.work.NetworkType;
 import androidx.work.OneTimeWorkRequest;
+import androidx.work.Operation;
 import androidx.work.WorkManager;
 import androidx.work.WorkerParameters;
 
-import com.android.devicelockcontroller.activities.DeviceLockNotificationManager;
-import com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason;
-import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
-import com.android.devicelockcontroller.policy.SetupController;
+import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
+import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason;
 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
 import com.android.devicelockcontroller.provision.grpc.ReportDeviceProvisionStateGrpcResponse;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
 import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.UserParameters;
+import com.android.devicelockcontroller.util.LogUtil;
 
+import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
-
-import java.time.Duration;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 
 /**
  * A worker class dedicated to report state of provision for the device lock program.
  */
 public final class ReportDeviceProvisionStateWorker extends AbstractCheckInWorker {
-
-    public static final String KEY_DEVICE_PROVISION_FAILURE_REASON =
-            "device-provision-failure-reason";
     public static final String KEY_IS_PROVISION_SUCCESSFUL = "is-provision-successful";
-    @VisibleForTesting
-    static final String UNEXPECTED_PROVISION_STATE_ERROR_MESSAGE = "Unexpected provision state!";
-
+    public static final String KEY_PROVISION_FAILURE_REASON = "provision-failure-reason";
     public static final String REPORT_PROVISION_STATE_WORK_NAME = "report-provision-state";
-    private static final int NOTIFICATION_REPORT_INTERVAL_DAY = 1;
+
+    private final StatsLogger mStatsLogger;
 
     /**
-     * Get a {@link SetupController.SetupUpdatesCallbacks} which will enqueue this worker to report
-     * provision success / failure.
+     * Report provision failure and get next failed step
      */
-    @NonNull
-    public static SetupController.SetupUpdatesCallbacks getSetupUpdatesCallbacks(
-            WorkManager workManager) {
-        return new SetupController.SetupUpdatesCallbacks() {
-            @Override
-            public void setupFailed(@SetupFailureReason int reason) {
-                reportSetupFailed(reason, workManager);
-            }
-
-            @Override
-            public void setupCompleted() {
-                reportSetupCompleted(workManager);
-            }
-        };
-    }
-
-    private static void reportSetupFailed(@SetupFailureReason int reason, WorkManager workManager) {
-        enqueueReportWork(false, reason, workManager, Duration.ZERO);
-    }
-
-    private static void reportSetupCompleted(WorkManager workManager) {
-        enqueueReportWork(true, /* ignored */ SetupFailureReason.SETUP_FAILED, workManager,
-                Duration.ZERO);
-    }
-
-    private static void reportStateInOneDay(WorkManager workManager) {
-        // Report that we have shown a failure notification to the user for one day and we did
-        // not retry setup between this and the last report. The failure reason and setup result
-        // have been reported in previous report.
-        enqueueReportWork(/* ignored */ false, /* ignored */ SetupFailureReason.SETUP_FAILED,
-                workManager,
-                Duration.ofDays(NOTIFICATION_REPORT_INTERVAL_DAY));
-    }
-
-    private static void enqueueReportWork(boolean isSuccessful, int reason,
-            WorkManager workManager, Duration delay) {
+    public static void reportSetupFailed(WorkManager workManager,
+            @ProvisionFailureReason int reason) {
         Data inputData = new Data.Builder()
-                .putBoolean(KEY_IS_PROVISION_SUCCESSFUL, isSuccessful)
-                .putInt(KEY_DEVICE_PROVISION_FAILURE_REASON, reason)
+                .putBoolean(KEY_IS_PROVISION_SUCCESSFUL, false)
+                .putInt(KEY_PROVISION_FAILURE_REASON, reason)
                 .build();
+        enqueueReportWork(inputData, workManager);
+    }
+
+    /**
+     * Report provision success
+     */
+    public static void reportSetupCompleted(WorkManager workManager) {
+        Data inputData = new Data.Builder()
+                .putBoolean(KEY_IS_PROVISION_SUCCESSFUL, true)
+                .build();
+        enqueueReportWork(inputData, workManager);
+    }
+
+    /**
+     * Schedule a work to report the current provision failed step to server.
+     */
+    public static void reportCurrentFailedStep(WorkManager workManager) {
+        Data inputData = new Data.Builder()
+                .putBoolean(KEY_IS_PROVISION_SUCCESSFUL, false)
+                .putInt(KEY_PROVISION_FAILURE_REASON, DEADLINE_PASSED)
+                .build();
+        enqueueReportWork(inputData, workManager);
+    }
+
+    private static void enqueueReportWork(Data inputData, WorkManager workManager) {
         Constraints constraints = new Constraints.Builder()
                 .setRequiredNetworkType(NetworkType.CONNECTED)
                 .build();
@@ -115,76 +101,99 @@
                 new OneTimeWorkRequest.Builder(ReportDeviceProvisionStateWorker.class)
                         .setConstraints(constraints)
                         .setInputData(inputData)
-                        .setInitialDelay(delay)
+                        .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, BACKOFF_DELAY)
                         .build();
-        workManager.enqueueUniqueWork(
-                REPORT_PROVISION_STATE_WORK_NAME,
-                ExistingWorkPolicy.APPEND_OR_REPLACE, work);
+        ListenableFuture<Operation.State.SUCCESS> result =
+                workManager.enqueueUniqueWork(REPORT_PROVISION_STATE_WORK_NAME,
+                ExistingWorkPolicy.APPEND_OR_REPLACE, work).getResult();
+        Futures.addCallback(result,
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Operation.State.SUCCESS result) {
+                        // no-op
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        // Log an error but don't reset the device (non critical failure).
+                        LogUtil.e(TAG, "Failed to enqueue 'report provision state' work", t);
+                    }
+                },
+                MoreExecutors.directExecutor()
+        );
     }
 
     public ReportDeviceProvisionStateWorker(@NonNull Context context,
-            @NonNull WorkerParameters workerParams) {
-        super(context, workerParams);
+            @NonNull WorkerParameters workerParams, ListeningExecutorService executorService) {
+        this(context, workerParams, /* client= */ null,
+                executorService);
     }
 
     @VisibleForTesting
     ReportDeviceProvisionStateWorker(@NonNull Context context,
-            @NonNull WorkerParameters workerParams, DeviceCheckInClient client) {
-        super(context, workerParams, client);
+            @NonNull WorkerParameters workerParams, DeviceCheckInClient client,
+            ListeningExecutorService executorService) {
+        super(context, workerParams, client, executorService);
+        StatsLoggerProvider loggerProvider =
+                (StatsLoggerProvider) context.getApplicationContext();
+        mStatsLogger = loggerProvider.getStatsLogger();
     }
 
     @NonNull
     @Override
-    public Result doWork() {
-        boolean isSuccessful = getInputData().getBoolean(
-                KEY_IS_PROVISION_SUCCESSFUL, /* defaultValue= */ false);
-        int reason = getInputData().getInt(KEY_DEVICE_PROVISION_FAILURE_REASON,
-                SetupFailureReason.SETUP_FAILED);
+    public ListenableFuture<Result> startWork() {
         GlobalParametersClient globalParametersClient = GlobalParametersClient.getInstance();
-        int lastState = Futures.getUnchecked(
-                globalParametersClient.getLastReceivedProvisionState());
-        final ReportDeviceProvisionStateGrpcResponse response =
-                Futures.getUnchecked(mClient).reportDeviceProvisionState(reason, lastState,
-                        isSuccessful);
-        if (response.hasRecoverableError()) return Result.retry();
-        if (response.hasFatalError()) return Result.failure();
-        String enrollmentToken = response.getEnrollmentToken();
-        if (!TextUtils.isEmpty(enrollmentToken)) {
-            Futures.getUnchecked(globalParametersClient.setEnrollmentToken(enrollmentToken));
-        }
-        // TODO(b/276392181): Handle next state properly
-        int nextState = response.getNextClientProvisionState();
-        Futures.getUnchecked(globalParametersClient.setLastReceivedProvisionState(nextState));
+        ListenableFuture<Integer> lastState =
+                globalParametersClient.getLastReceivedProvisionState();
+        DeviceLockControllerSchedulerProvider schedulerProvider =
+                (DeviceLockControllerSchedulerProvider) mContext;
+        DeviceLockControllerScheduler scheduler =
+                schedulerProvider.getDeviceLockControllerScheduler();
+        return Futures.whenAllSucceed(mClient, lastState).call(() -> {
+            boolean isSuccessful = getInputData().getBoolean(
+                    KEY_IS_PROVISION_SUCCESSFUL, /* defaultValue= */ false);
+            int failureReason = getInputData().getInt(KEY_PROVISION_FAILURE_REASON,
+                    ProvisionFailureReason.UNKNOWN_REASON);
+            if (!isSuccessful && failureReason == ProvisionFailureReason.UNKNOWN_REASON) {
+                LogUtil.e(TAG, "Reporting failure with an unknown reason is not allowed");
+            }
+            ReportDeviceProvisionStateGrpcResponse response =
+                    Futures.getDone(mClient).reportDeviceProvisionState(
+                            Futures.getDone(lastState),
+                            isSuccessful,
+                            failureReason);
+            if (response.hasRecoverableError()) {
+                LogUtil.w(TAG, "Report provision state failed w/ recoverable error" + response
+                        + "\nRetrying...");
+                return Result.retry();
+            }
+            if (response.hasFatalError()) {
+                LogUtil.e(TAG,
+                        "Report provision state failed: " + response + "\nRetry current step");
+                scheduler.scheduleNextProvisionFailedStepAlarm(/* shouldGoOffImmediately= */ false);
+                return Result.failure();
+            }
+            int daysLeftUntilReset = response.getDaysLeftUntilReset();
+            if (daysLeftUntilReset > 0) {
+                UserParameters.setDaysLeftUntilReset(mContext, daysLeftUntilReset);
+            }
+            int nextState = response.getNextClientProvisionState();
+            Futures.getUnchecked(globalParametersClient.setLastReceivedProvisionState(nextState));
+            scheduler.scheduleNextProvisionFailedStepAlarm(
+                    shouldRunNextStepImmediately(Futures.getDone(lastState), nextState));
+            mStatsLogger.logReportDeviceProvisionState();
+            return Result.success();
+        }, mExecutorService);
+    }
 
-        PolicyObjectsInterface policyObjects =
-                (PolicyObjectsInterface) mContext.getApplicationContext();
-        DevicePolicyController devicePolicyController = policyObjects.getPolicyController();
-        DeviceStateController deviceStateController = policyObjects.getStateController();
-        switch (nextState) {
-            case PROVISION_STATE_RETRY:
-                DeviceCheckInHelper.setProvisionSucceeded(deviceStateController,
-                        devicePolicyController, mContext, /* isMandatory= */ false);
-                break;
-            case PROVISION_STATE_DISMISSIBLE_UI:
-                DeviceLockNotificationManager.sendDeviceResetNotification(mContext,
-                        response.getDaysLeftUntilReset());
-                reportStateInOneDay(WorkManager.getInstance(mContext));
-                break;
-            case PROVISION_STATE_PERSISTENT_UI:
-                DeviceLockNotificationManager.sendDeviceResetInOneDayOngoingNotification(mContext);
-                reportStateInOneDay(WorkManager.getInstance(mContext));
-                break;
-            case PROVISION_STATE_FACTORY_RESET:
-                // TODO(b/284003841): Show a count down timer.
-                devicePolicyController.wipeData();
-                break;
-            case PROVISION_STATE_SUCCESS:
-            case PROVISION_STATE_UNSPECIFIED:
-                // no-op
-                break;
-            default:
-                throw new IllegalStateException(UNEXPECTED_PROVISION_STATE_ERROR_MESSAGE);
-        }
-        return Result.success();
+    @VisibleForTesting
+    static boolean shouldRunNextStepImmediately(@DeviceProvisionState int lastState,
+            @DeviceProvisionState int nextState) {
+        // Always wait before performing a retry;
+        if (nextState == DeviceProvisionState.PROVISION_STATE_RETRY) return false;
+        // Otherwise, when the user just goes through the provision UI, we should
+        // perform next step immediately.
+        return lastState == DeviceProvisionState.PROVISION_STATE_UNSPECIFIED
+                || lastState == DeviceProvisionState.PROVISION_STATE_RETRY;
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/BootUtils.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/BootUtils.java
deleted file mode 100644
index 7a8526b..0000000
--- a/DeviceLockController/src/com/android/devicelockcontroller/receivers/BootUtils.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
-
-import android.content.Context;
-
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
-
-/** A utility class used when device is booting. */
-final class BootUtils {
-
-    /**
-     * Checks if the device is in a "locked" state. If yes, enable the lock task mode and launches
-     * applicable activity.
-     */
-    static void startLockTaskModeAtBoot(Context context) {
-        PolicyObjectsInterface policyObjects =
-                (PolicyObjectsInterface) context.getApplicationContext();
-        if (policyObjects.getStateController().isLocked()) {
-            policyObjects.getPolicyController().enqueueStartLockTaskModeWorker(
-                    /* isMandatory= */ true);
-        }
-    }
-}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/CheckInBootCompletedReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/CheckInBootCompletedReceiver.java
index b8a7414..95cb85b 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/receivers/CheckInBootCompletedReceiver.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/receivers/CheckInBootCompletedReceiver.java
@@ -17,51 +17,40 @@
 package com.android.devicelockcontroller.receivers;
 
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.os.UserManager;
+import android.content.pm.PackageManager;
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
-import com.android.devicelockcontroller.provision.worker.DeviceCheckInHelper;
-import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
 import com.android.devicelockcontroller.util.LogUtil;
 
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 
 /**
  * Boot completed broadcast receiver to enqueue the check-in work for provision when device boots
  * for the first time.
- * Note that this boot completed receiver differs with {@link LockTaskBootCompletedReceiver} in the
- * way that it only runs for system user.
+ *
+ * Only runs on system user and is disabled after check-in completes successfully.
  */
 public final class CheckInBootCompletedReceiver extends BroadcastReceiver {
 
     private static final String TAG = "CheckInBootCompletedReceiver";
+    private final Executor mExecutor;
+
+    public CheckInBootCompletedReceiver() {
+        mExecutor = Executors.newSingleThreadExecutor();
+    }
 
     @VisibleForTesting
-    static void checkInIfNeeded(DeviceStateController stateController,
-            DeviceCheckInHelper checkInHelper) {
-        if (stateController.isCheckInNeeded()) {
-            Futures.addCallback(GlobalParametersClient.getInstance().needCheckIn(),
-                    new FutureCallback<>() {
-                        @Override
-                        public void onSuccess(Boolean needCheckIn) {
-                            if (needCheckIn) {
-                                checkInHelper.enqueueDeviceCheckInWork(/* isExpedited= */ false);
-                            }
-                        }
-
-                        @Override
-                        public void onFailure(Throwable t) {
-                            LogUtil.e(TAG, "Failed to know if we need to perform check-in!", t);
-                        }
-                    }, MoreExecutors.directExecutor());
-        }
+    CheckInBootCompletedReceiver(Executor executor) {
+        mExecutor = executor;
     }
 
     @Override
@@ -70,15 +59,35 @@
 
         LogUtil.i(TAG, "Received boot completed intent");
 
-        final boolean isUserProfile =
-                context.getSystemService(UserManager.class).isProfile();
-
-        if (isUserProfile) {
+        if (!context.getUser().isSystem()) {
+            // This is not *supposed* to happen since the receiver is marked systemUserOnly but
+            // there seems to be some edge case where it does. See b/304318606.
+            // In this case, we'll just disable and return early.
+            LogUtil.w(TAG, "Called check in boot receiver on non-system user!");
+            disableCheckInBootCompletedReceiver(context);
             return;
         }
 
-        checkInIfNeeded(
-                ((PolicyObjectsInterface) context.getApplicationContext()).getStateController(),
-                new DeviceCheckInHelper(context));
+        final DeviceLockControllerSchedulerProvider schedulerProvider =
+                (DeviceLockControllerSchedulerProvider) context.getApplicationContext();
+        final DeviceLockControllerScheduler scheduler =
+                schedulerProvider.getDeviceLockControllerScheduler();
+
+        ListenableFuture<Void> scheduleCheckIn = scheduler.maybeScheduleInitialCheckIn();
+
+        final PendingResult pendingResult = goAsync();
+
+        scheduleCheckIn.addListener(pendingResult::finish, mExecutor);
+    }
+
+    /**
+     * Disable the receiver for the current user
+     *
+     * @param context context of current user
+     */
+    public static void disableCheckInBootCompletedReceiver(Context context) {
+        context.getPackageManager().setComponentEnabledSetting(
+                new ComponentName(context, CheckInBootCompletedReceiver.class),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/LockTaskBootCompletedReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/FinalizationBootCompletedReceiver.java
similarity index 69%
rename from DeviceLockController/src/com/android/devicelockcontroller/receivers/LockTaskBootCompletedReceiver.java
rename to DeviceLockController/src/com/android/devicelockcontroller/receivers/FinalizationBootCompletedReceiver.java
index a8e3527..84e6bfe 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/receivers/LockTaskBootCompletedReceiver.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/receivers/FinalizationBootCompletedReceiver.java
@@ -21,15 +21,12 @@
 import android.content.Intent;
 import android.os.UserManager;
 
-/**
- * Boot completed broadcast receiver to start lock task mode if applicable. This broadcast receiver
- * runs for every user on the device.
- * Note that this boot completed receiver differs with {@link CheckInBootCompletedReceiver} in the
- * way that it runs for any users.
- */
-public final class LockTaskBootCompletedReceiver extends BroadcastReceiver {
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
 
-    static final String TAG = "LockTaskBootCompletedReceiver";
+/**
+ * Boot complete receiver to initialize finalization state on device.
+ */
+public final class FinalizationBootCompletedReceiver extends BroadcastReceiver {
 
     @Override
     public void onReceive(Context context, Intent intent) {
@@ -39,9 +36,12 @@
                 context.getSystemService(UserManager.class).isProfile();
 
         if (isUserProfile) {
+            // Not needed as the receiver will run in the parent user
             return;
         }
 
-        BootUtils.startLockTaskModeAtBoot(context);
+        // Initialize finalization controller to apply device finalization state
+        ((PolicyObjectsProvider) context.getApplicationContext())
+                .getFinalizationController().enforceInitialState();
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/LockedBootCompletedReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/LockedBootCompletedReceiver.java
index 60b4ef3..49ebc20 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/receivers/LockedBootCompletedReceiver.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/receivers/LockedBootCompletedReceiver.java
@@ -16,57 +16,46 @@
 
 package com.android.devicelockcontroller.receivers;
 
-import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
-import static android.content.pm.PackageManager.DONT_KILL_APP;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_FAILED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_PAUSED;
 
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.os.UserManager;
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
 import com.android.devicelockcontroller.util.LogUtil;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
 /**
  * Handle {@link  Intent#ACTION_LOCKED_BOOT_COMPLETED}. This receiver runs for any user
  * (singleUser="false").
- *
- * This receiver starts lock task mode if applicable.
+ * <p>
+ * This receiver reschedules alarms if needed.
  */
 public final class LockedBootCompletedReceiver extends BroadcastReceiver {
     private static final String TAG = "LockedBootCompletedReceiver";
+    private final Executor mExecutor;
 
-    private static DeviceStateController getDeviceStateController(Context context) {
-        return ((PolicyObjectsInterface) context.getApplicationContext())
-                .getStateController();
+    public LockedBootCompletedReceiver() {
+        mExecutor = Executors.newSingleThreadExecutor();
     }
 
     @VisibleForTesting
-    static void startLockTaskModeIfApplicable(Context context) {
-        final PackageManager pm = context.getPackageManager();
-        final ComponentName lockTaskBootCompletedReceiver = new ComponentName(context,
-                LockTaskBootCompletedReceiver.class);
-        if (getDeviceStateController(context).isInSetupState()) {
-            // b/172281939: WorkManager is not available at this moment, and we may not launch
-            // lock task mode successfully. Therefore, defer it to LockTaskBootCompletedReceiver.
-            LogUtil.i(TAG,
-                    "Setup has not completed yet when ACTION_LOCKED_BOOT_COMPLETED is received. "
-                            + "We can not start lock task mode here.");
-            pm.setComponentEnabledSetting(lockTaskBootCompletedReceiver,
-                    COMPONENT_ENABLED_STATE_DEFAULT, DONT_KILL_APP);
-            return;
-        }
-
-        BootUtils.startLockTaskModeAtBoot(context);
-        pm.setComponentEnabledSetting(
-                new ComponentName(context, LockTaskBootCompletedReceiver.class),
-                COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP);
+    LockedBootCompletedReceiver(Executor executor) {
+        mExecutor = executor;
     }
 
     @Override
@@ -78,11 +67,33 @@
 
         final boolean isUserProfile =
                 context.getSystemService(UserManager.class).isProfile();
-
         if (isUserProfile) {
             return;
         }
 
-        startLockTaskModeIfApplicable(context);
+        Context applicationContext = context.getApplicationContext();
+        ProvisionStateController stateController = ((PolicyObjectsProvider) applicationContext)
+                .getProvisionStateController();
+
+        DeviceLockControllerSchedulerProvider schedulerProvider =
+                (DeviceLockControllerSchedulerProvider) applicationContext;
+        DeviceLockControllerScheduler scheduler =
+                schedulerProvider.getDeviceLockControllerScheduler();
+        Futures.addCallback(stateController.getState(),
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(@ProvisionState Integer state) {
+                        if (state == PROVISION_PAUSED) {
+                            scheduler.notifyRebootWhenProvisionPaused();
+                        } else if (state == PROVISION_FAILED) {
+                            scheduler.notifyRebootWhenProvisionFailed();
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        throw new RuntimeException(t);
+                    }
+                }, mExecutor);
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/NextProvisionFailedStepReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/NextProvisionFailedStepReceiver.java
new file mode 100644
index 0000000..76fd9c4
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/receivers/NextProvisionFailedStepReceiver.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_DISMISSIBLE_UI;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_FACTORY_RESET;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_PERSISTENT_UI;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_RETRY;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_SUCCESS;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_UNSPECIFIED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_RETRY;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.work.WorkManager;
+
+import com.android.devicelockcontroller.activities.DeviceLockNotificationManager;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.UserParameters;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * A broadcast receiver to perform the next step in the provision failure flow.
+ */
+public final class NextProvisionFailedStepReceiver extends BroadcastReceiver {
+    @VisibleForTesting
+    static final String UNEXPECTED_PROVISION_STATE_ERROR_MESSAGE = "Unexpected provision state!";
+    public static final String TAG = "NextProvisionFailedStepReceiver";
+    private final Executor mExecutor;
+
+    public NextProvisionFailedStepReceiver() {
+        this(Executors.newSingleThreadExecutor());
+    }
+
+    @VisibleForTesting
+    NextProvisionFailedStepReceiver(Executor executor) {
+        mExecutor = executor;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (!NextProvisionFailedStepReceiver.class.getName().equals(
+                intent.getComponent().getClassName())) {
+            throw new IllegalArgumentException("Can not handle implicit intent!");
+        }
+        Context applicationContext = context.getApplicationContext();
+        ProvisionStateController provisionStateController =
+                ((PolicyObjectsProvider) applicationContext)
+                        .getProvisionStateController();
+
+        DeviceLockControllerSchedulerProvider schedulerProvider =
+                (DeviceLockControllerSchedulerProvider) applicationContext;
+        DeviceLockControllerScheduler scheduler =
+                schedulerProvider.getDeviceLockControllerScheduler();
+        GlobalParametersClient globalParameters = GlobalParametersClient.getInstance();
+        ListenableFuture<Boolean> needToReportFuture = Futures.transform(
+                globalParameters.getLastReceivedProvisionState(),
+                provisionState -> {
+                    switch (provisionState) {
+                        case PROVISION_STATE_RETRY:
+                            provisionStateController.postSetNextStateForEventRequest(
+                                    PROVISION_RETRY);
+                            // We can not report the state here, because we do not know the
+                            // result of retry. It will be reported after the retry finishes, no
+                            // matter it succeeds or fails.
+                            return false;
+                        case PROVISION_STATE_DISMISSIBLE_UI:
+                            int daysLeftUntilReset = UserParameters.getDaysLeftUntilReset(context);
+                            DeviceLockNotificationManager.sendDeviceResetNotification(context,
+                                    daysLeftUntilReset);
+                            return true;
+                        case PROVISION_STATE_PERSISTENT_UI:
+                            DeviceLockNotificationManager
+                                    .sendDeviceResetInOneDayOngoingNotification(context);
+                            return true;
+                        case PROVISION_STATE_FACTORY_RESET:
+                            scheduler.scheduleResetDeviceAlarm();
+                            return true;
+                        case PROVISION_STATE_SUCCESS:
+                        case PROVISION_STATE_UNSPECIFIED:
+                            return false;
+                        default:
+                            throw new IllegalStateException(
+                                    UNEXPECTED_PROVISION_STATE_ERROR_MESSAGE);
+                    }
+                }, mExecutor);
+
+        Futures.addCallback(needToReportFuture, new FutureCallback<>() {
+            @Override
+            public void onSuccess(Boolean needToReport) {
+                if (needToReport) {
+                    ReportDeviceProvisionStateWorker.reportCurrentFailedStep(
+                            WorkManager.getInstance(context));
+                }
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LogUtil.e(TAG, "Failed to perform next provision failed step", t);
+            }
+        }, MoreExecutors.directExecutor());
+    }
+
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/ProvisionReadyReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/ProvisionReadyReceiver.java
new file mode 100644
index 0000000..a415fe5
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/receivers/ProvisionReadyReceiver.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+
+/** A receiver to handle explicit provision ready intent */
+public final class ProvisionReadyReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        ((PolicyObjectsProvider) context.getApplicationContext())
+                .getProvisionStateController().notifyProvisioningReady();
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/RecordBootTimestampReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/RecordBootTimestampReceiver.java
new file mode 100644
index 0000000..b76c4e1
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/receivers/RecordBootTimestampReceiver.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.os.UserManager;
+
+import com.android.devicelockcontroller.storage.UserParameters;
+
+import java.time.Clock;
+import java.time.Instant;
+
+/**
+ * A receiver to record the boot timestamp.
+ */
+public final class RecordBootTimestampReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (!intent.getAction().equals(Intent.ACTION_LOCKED_BOOT_COMPLETED)) {
+            // Ignore other intent actions
+            return;
+        }
+        if (context.getSystemService(UserManager.class).isProfile()) {
+            // Not needed as the receiver will run in the parent user
+            return;
+        }
+        Instant bootTimeStamp = Instant.now(Clock.systemUTC()).minusMillis(
+                SystemClock.elapsedRealtime());
+        UserParameters.setBootTimeMillis(context, bootTimeStamp.toEpochMilli());
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/ResetDeviceReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/ResetDeviceReceiver.java
new file mode 100644
index 0000000..177a9a9
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/receivers/ResetDeviceReceiver.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+import com.android.devicelockcontroller.util.LogUtil;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * A broadcast receiver that will factory reset the device when it receives a broadcast.
+ */
+public final class ResetDeviceReceiver extends BroadcastReceiver {
+    private static final String TAG = "ResetDeviceReceiver";
+    private final Executor mExecutor;
+
+    public ResetDeviceReceiver() {
+        mExecutor = Executors.newSingleThreadExecutor();
+    }
+
+    @VisibleForTesting
+    ResetDeviceReceiver(Executor executor) {
+        mExecutor = executor;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (!ResetDeviceReceiver.class.getName().equals(intent.getComponent().getClassName())) {
+            throw new IllegalArgumentException("Can not handle implicit intent!");
+        }
+        Futures.addCallback(SetupParametersClient.getInstance().isProvisionMandatory(),
+                new FutureCallback<Boolean>() {
+                    @Override
+                    public void onSuccess(Boolean isProvisionMandatory) {
+                        StatsLogger logger = ((StatsLoggerProvider) context.getApplicationContext())
+                                .getStatsLogger();
+                        logger.logDeviceReset(isProvisionMandatory);
+                        ((PolicyObjectsProvider) context.getApplicationContext())
+                                .getPolicyController().wipeDevice();
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        // We don't want the statistics event to cancel the device reset, so
+                        // we just log the error here and proceed.
+                        LogUtil.e(TAG, "Error querying isProvisionMandatory", t);
+                        ((PolicyObjectsProvider) context.getApplicationContext())
+                                .getPolicyController().wipeDevice();
+                    }
+                }, mExecutor);
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/ResumeProvisionReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/ResumeProvisionReceiver.java
new file mode 100644
index 0000000..4b18830
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/receivers/ResumeProvisionReceiver.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState;
+
+/**
+ * A broadcast receiver to trigger {@link ProvisionEvent#PROVISION_RESUME} and change state to
+ * {@link ProvisionState#PROVISION_IN_PROGRESS}
+ */
+public final class ResumeProvisionReceiver extends BroadcastReceiver {
+
+    public static final String TAG = "ResumeProvisionReceiver";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (!ResumeProvisionReceiver.class.getName().equals(
+                intent.getComponent().getClassName())) {
+            throw new IllegalArgumentException("Can not handle implicit intent!");
+        }
+        ((PolicyObjectsProvider) context.getApplicationContext()).getProvisionStateController()
+                .postSetNextStateForEventRequest(ProvisionEvent.PROVISION_RESUME);
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/receivers/TimeChangedBroadcastReceiver.java b/DeviceLockController/src/com/android/devicelockcontroller/receivers/TimeChangedBroadcastReceiver.java
new file mode 100644
index 0000000..21954b4
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/receivers/TimeChangedBroadcastReceiver.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserManager;
+
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
+import com.android.devicelockcontroller.util.LogUtil;
+
+/**
+ * Handle {@link Intent#ACTION_TIME_CHANGED}. This receiver runs for every user.
+ * <p>
+ * This receiver is responsible handle system time change and make corrections to the "expected to
+ * run" time for scheduled work / alarm.
+ */
+public final class TimeChangedBroadcastReceiver extends BroadcastReceiver {
+
+    private static final String TAG = "TimeChangedBroadcastReceiver";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (!intent.getAction().equals(Intent.ACTION_TIME_CHANGED)) {
+            return;
+        }
+
+        LogUtil.d(TAG, "Time changed.");
+
+        final boolean isUserProfile =
+                context.getSystemService(UserManager.class).isProfile();
+        if (isUserProfile) {
+            return;
+        }
+        DeviceLockControllerSchedulerProvider schedulerProvider =
+                (DeviceLockControllerSchedulerProvider) context.getApplicationContext();
+
+        schedulerProvider.getDeviceLockControllerScheduler().notifyTimeChanged();
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/schedule/DeviceLockControllerScheduler.java b/DeviceLockController/src/com/android/devicelockcontroller/schedule/DeviceLockControllerScheduler.java
new file mode 100644
index 0000000..ed98290
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/schedule/DeviceLockControllerScheduler.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.schedule;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.time.Duration;
+
+/**
+ * An interface which provides APIs to notify the scheduler to schedule works/alarms based on event
+ * happened.
+ */
+public interface DeviceLockControllerScheduler {
+
+    /**
+     * Notify the scheduler that system time has changed.
+     */
+    void notifyTimeChanged();
+
+    /**
+     * Notify the scheduler that reschedule might be required for check-in work
+     */
+    ListenableFuture<Void> notifyNeedRescheduleCheckIn();
+
+    /**
+     * Schedule an alarm to resume the provision flow.
+     */
+    void scheduleResumeProvisionAlarm();
+
+    /**
+     * Notify the scheduler that device reboot when provision is paused.
+     */
+    void notifyRebootWhenProvisionPaused();
+
+    /**
+     * Schedule the initial check-in work when device first boot.
+     */
+    ListenableFuture<Void> scheduleInitialCheckInWork();
+
+    /**
+     * Schedule the retry check-in work with a delay.
+     *
+     * @param delay The delayed duration to wait for performing retry check-in work.
+     */
+    ListenableFuture<Void> scheduleRetryCheckInWork(Duration delay);
+
+    /**
+     * Schedule the initial check in (if not already done).
+     * Otherwise, if provision is not ready, reschedule the check in.
+     */
+    ListenableFuture<Void> maybeScheduleInitialCheckIn();
+
+    /**
+     * Schedule an alarm to perform next provision failed step.
+     *
+     * @param shouldRunImmediately true, if the alarm should go off immediately; false, if the
+     *                             alarm should go off after a default delay.
+     */
+    void scheduleNextProvisionFailedStepAlarm(boolean shouldRunImmediately);
+
+    /**
+     * Notify the scheduler that device reboot when provision has failed.
+     */
+    void notifyRebootWhenProvisionFailed();
+
+    /**
+     * Schedule an alarm to factory reset the device in case of provision is failed.
+     */
+    void scheduleResetDeviceAlarm();
+
+    /**
+     * Schedule an alarm to factory reset the device in case of mandatory provision is failed.
+     */
+    void scheduleMandatoryResetDeviceAlarm();
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/schedule/DeviceLockControllerSchedulerImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/schedule/DeviceLockControllerSchedulerImpl.java
new file mode 100644
index 0000000..56934d4
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/schedule/DeviceLockControllerSchedulerImpl.java
@@ -0,0 +1,522 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.schedule;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.NON_MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_FAILED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_PAUSED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED;
+import static com.android.devicelockcontroller.provision.worker.AbstractCheckInWorker.BACKOFF_DELAY;
+import static com.android.devicelockcontroller.WorkManagerExceptionHandler.AlarmReason;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.os.SystemClock;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.work.BackoffPolicy;
+import androidx.work.Constraints;
+import androidx.work.ExistingWorkPolicy;
+import androidx.work.NetworkType;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.Operation;
+import androidx.work.OutOfQuotaPolicy;
+import androidx.work.WorkManager;
+
+import com.android.devicelockcontroller.DeviceLockControllerApplication;
+import com.android.devicelockcontroller.WorkManagerExceptionHandler;
+import com.android.devicelockcontroller.activities.DeviceLockNotificationManager;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState;
+import com.android.devicelockcontroller.provision.worker.DeviceCheckInWorker;
+import com.android.devicelockcontroller.receivers.NextProvisionFailedStepReceiver;
+import com.android.devicelockcontroller.receivers.ResetDeviceReceiver;
+import com.android.devicelockcontroller.receivers.ResumeProvisionReceiver;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.UserParameters;
+import com.android.devicelockcontroller.util.LogUtil;
+import com.android.devicelockcontroller.util.ThreadUtils;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.time.Clock;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Implementation of {@link DeviceLockControllerScheduler}.
+ * WARNING: Do not create an instance directly, instead you should retrieve it using the
+ * {@link DeviceLockControllerApplication#getDeviceLockControllerScheduler()} API.
+ */
+public final class DeviceLockControllerSchedulerImpl implements DeviceLockControllerScheduler {
+    private static final String TAG = "DeviceLockControllerSchedulerImpl";
+    private static final String FILENAME = "device-lock-controller-scheduler-preferences";
+    public static final String DEVICE_CHECK_IN_WORK_NAME = "device-check-in";
+    private static final String DEBUG_DEVICELOCK_PAUSED_MINUTES = "debug.devicelock.paused-minutes";
+    private static final String DEBUG_DEVICELOCK_REPORT_INTERVAL_MINUTES =
+            "debug.devicelock.report-interval-minutes";
+    private static final String DEBUG_DEVICELOCK_RESET_DEVICE_MINUTES =
+            "debug.devicelock.reset-device-minutes";
+    private static final String DEBUG_DEVICELOCK_MANDATORY_RESET_DEVICE_MINUTES =
+            "debug.devicelock.mandatory-reset-device-minutes";
+
+    // The default minute value of the duration that provision UI can be paused.
+    public static final int PROVISION_PAUSED_MINUTES_DEFAULT = 60;
+    // The default minute value of the interval between steps of provision failed flow.
+    public static final long PROVISION_STATE_REPORT_INTERVAL_DEFAULT_MINUTES =
+            TimeUnit.DAYS.toMinutes(1);
+    private final Context mContext;
+    private final Clock mClock;
+    private final Executor mSequentialExecutor;
+    private final ProvisionStateController mProvisionStateController;
+
+    private static volatile SharedPreferences sSharedPreferences;
+
+    private static synchronized SharedPreferences getSharedPreferences(
+            Context context) {
+        if (sSharedPreferences == null) {
+            sSharedPreferences = context.createDeviceProtectedStorageContext().getSharedPreferences(
+                    FILENAME,
+                    Context.MODE_PRIVATE);
+        }
+        return sSharedPreferences;
+    }
+
+    /**
+     * Set how long provision should be paused after user hit the "Do it in 1 hour" button, in
+     * minutes.
+     */
+    public static void setDebugProvisionPausedMinutes(Context context, int minutes) {
+        getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_PAUSED_MINUTES,
+                minutes).apply();
+    }
+
+    /**
+     * Set the length of the interval of provisioning failure reporting for debugging purpose.
+     */
+    public static void setDebugReportIntervalMinutes(Context context, long minutes) {
+        getSharedPreferences(context).edit().putLong(DEBUG_DEVICELOCK_REPORT_INTERVAL_MINUTES,
+                minutes).apply();
+    }
+
+    /**
+     * Set the length of the countdown minutes when device is about to factory reset in
+     * non-mandatory provisioning case for debugging purpose.
+     */
+    public static void setDebugResetDeviceMinutes(Context context, int minutes) {
+        getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_RESET_DEVICE_MINUTES,
+                minutes).apply();
+    }
+
+    /**
+     * Set the length of the countdown minutes when device is about to factory reset in mandatory
+     * provisioning case for debugging purpose.
+     */
+    public static void setDebugMandatoryResetDeviceMinutes(Context context, int minutes) {
+        getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_MANDATORY_RESET_DEVICE_MINUTES,
+                minutes).apply();
+    }
+
+    /**
+     * Dump current debugging setup to logcat.
+     */
+    public static void dumpDebugScheduler(Context context) {
+        LogUtil.d(TAG,
+                "Current Debug Scheduler setups:\n" + getSharedPreferences(context).getAll());
+    }
+
+    /**
+     * Clear current debugging setup.
+     */
+    public static void clear(Context context) {
+        getSharedPreferences(context).edit().clear().apply();
+    }
+
+    public DeviceLockControllerSchedulerImpl(Context context,
+            ProvisionStateController provisionStateController) {
+        this(context, Clock.systemUTC(), provisionStateController);
+    }
+
+    @VisibleForTesting
+    DeviceLockControllerSchedulerImpl(Context context, Clock clock,
+            ProvisionStateController provisionStateController) {
+        mContext = context;
+        mProvisionStateController = provisionStateController;
+        mClock = clock;
+        mSequentialExecutor = ThreadUtils.getSequentialSchedulerExecutor();
+    }
+
+    @Override
+    public void notifyTimeChanged() {
+        Futures.addCallback(mProvisionStateController.getState(),
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(@ProvisionState Integer currentState) {
+                        correctStoredTime(currentState);
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        throw new RuntimeException(t);
+                    }
+                }, mSequentialExecutor);
+    }
+
+    /**
+     * Correct the stored time for when a scheduled work/alarm should execute based on the
+     * difference between current time and stored time.
+     *
+     * @param currentState The current {@link ProvisionState} used to determine which work/alarm may
+     *                     be possibly scheduled.
+     */
+    @VisibleForTesting
+    void correctStoredTime(@ProvisionState Integer currentState) {
+        long bootTimestamp = UserParameters.getBootTimeMillis(mContext);
+        long delta =
+                mClock.millis() - (bootTimestamp + SystemClock.elapsedRealtime());
+        UserParameters.setBootTimeMillis(mContext,
+                UserParameters.getBootTimeMillis(mContext) + delta);
+        if (currentState == UNPROVISIONED) {
+            long before = UserParameters.getNextCheckInTimeMillis(mContext);
+            if (before > 0) {
+                UserParameters.setNextCheckInTimeMillis(mContext,
+                        before + delta);
+            }
+            // We have to reschedule (update) the check-in work, because, otherwise, if device
+            // reboots, WorkManager will reschedule the work based on the changed system clock,
+            // which will result in inaccurate schedule. (see b/285221785)
+            rescheduleRetryCheckInWork();
+        } else if (currentState == PROVISION_PAUSED) {
+            long before = UserParameters.getResumeProvisionTimeMillis(mContext);
+            if (before > 0) {
+                UserParameters.setResumeProvisionTimeMillis(mContext,
+                        before + delta);
+            }
+        } else if (currentState == PROVISION_FAILED) {
+            long before = UserParameters.getNextProvisionFailedStepTimeMills(
+                    mContext);
+            if (before > 0) {
+                UserParameters.setNextProvisionFailedStepTimeMills(mContext,
+                        before + delta);
+            }
+            before = UserParameters.getResetDeviceTimeMillis(mContext);
+            if (before > 0) {
+                UserParameters.setResetDeviceTimeMillis(mContext,
+                        before + delta);
+            }
+        }
+    }
+
+    @Override
+    public void scheduleResumeProvisionAlarm() {
+        Duration delay = Duration.ofMinutes(PROVISION_PAUSED_MINUTES_DEFAULT);
+        if (Build.isDebuggable()) {
+            delay = Duration.ofMinutes(
+                    getSharedPreferences(mContext).getInt(DEBUG_DEVICELOCK_PAUSED_MINUTES,
+                            PROVISION_PAUSED_MINUTES_DEFAULT));
+        }
+        LogUtil.i(TAG, "Scheduling resume provision work with delay: " + delay);
+        scheduleResumeProvisionAlarm(delay);
+        Instant whenExpectedToRun = Instant.now(mClock).plus(delay);
+        UserParameters.setResumeProvisionTimeMillis(mContext,
+                whenExpectedToRun.toEpochMilli());
+    }
+
+    @Override
+    public void notifyRebootWhenProvisionPaused() {
+        dispatchFuture(this::rescheduleResumeProvisionAlarmIfNeeded,
+                "notifyRebootWhenProvisionPaused");
+    }
+
+    @Override
+    public ListenableFuture<Void> scheduleInitialCheckInWork() {
+        LogUtil.i(TAG, "Scheduling initial check-in work");
+        final Operation operation =
+                enqueueCheckInWorkRequest(/* isExpedited= */ true, Duration.ZERO);
+        final ListenableFuture<Operation.State.SUCCESS> result = operation.getResult();
+
+        return FluentFuture.from(result)
+                .transform((Function<Operation.State.SUCCESS, Void>) ignored -> {
+                    UserParameters.initialCheckInScheduled(mContext);
+                    return null;
+                }, mSequentialExecutor)
+                .catching(Throwable.class, (e) -> {
+                    LogUtil.e(TAG, "Failed to enqueue initial check in work", e);
+                    WorkManagerExceptionHandler.scheduleAlarm(mContext,
+                            AlarmReason.INITIAL_CHECK_IN);
+                    throw new RuntimeException(e);
+                }, mSequentialExecutor);
+    }
+
+    @Override
+    public ListenableFuture<Void> scheduleRetryCheckInWork(Duration delay) {
+        LogUtil.i(TAG, "Scheduling retry check-in work with delay: " + delay);
+        final Operation operation =
+                enqueueCheckInWorkRequest(/* isExpedited= */ false, delay);
+        final ListenableFuture<Operation.State.SUCCESS> result = operation.getResult();
+
+        return FluentFuture.from(result)
+                .transform((Function<Operation.State.SUCCESS, Void>) ignored -> {
+                    Instant whenExpectedToRun = Instant.now(mClock).plus(delay);
+                    UserParameters.setNextCheckInTimeMillis(mContext,
+                            whenExpectedToRun.toEpochMilli());
+                    return null;
+                }, mSequentialExecutor)
+                .catching(Throwable.class, (e) -> {
+                    LogUtil.e(TAG, "Failed to enqueue retry check in work", e);
+                    WorkManagerExceptionHandler.scheduleAlarm(mContext,
+                            AlarmReason.RETRY_CHECK_IN);
+                    throw new RuntimeException(e);
+                }, mSequentialExecutor);
+    }
+
+    @Override
+    public ListenableFuture<Void> notifyNeedRescheduleCheckIn() {
+        final ListenableFuture<Void> result =
+                Futures.submit(this::rescheduleRetryCheckInWork, mSequentialExecutor);
+        Futures.addCallback(result,
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Void unused) {
+                        LogUtil.i(TAG, "Successfully called notifyNeedRescheduleCheckIn");
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        throw new RuntimeException("failed to call notifyNeedRescheduleCheckIn", t);
+                    }
+                }, MoreExecutors.directExecutor());
+        return result;
+    }
+
+    @VisibleForTesting
+    void rescheduleRetryCheckInWork() {
+        long nextCheckInTimeMillis = UserParameters.getNextCheckInTimeMillis(mContext);
+        if (nextCheckInTimeMillis > 0) {
+            Duration delay = Duration.between(
+                    Instant.now(mClock),
+                    Instant.ofEpochMilli(nextCheckInTimeMillis));
+            LogUtil.i(TAG, "Rescheduling retry check-in work with delay: " + delay);
+            final Operation operation =
+                    enqueueCheckInWorkRequest(/* isExpedited= */ false, delay);
+            Futures.addCallback(operation.getResult(), new FutureCallback<>() {
+                @Override
+                public void onSuccess(Operation.State.SUCCESS result) {
+                    // No-op
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                    LogUtil.e(TAG, "Failed to reschedule retry check in work", t);
+                    WorkManagerExceptionHandler.scheduleAlarm(mContext,
+                            AlarmReason.RESCHEDULE_CHECK_IN);
+                }
+            }, mSequentialExecutor);
+        }
+    }
+
+    @Override
+    public ListenableFuture<Void> maybeScheduleInitialCheckIn() {
+        return FluentFuture.from(Futures.submit(() -> UserParameters.needInitialCheckIn(mContext),
+                        mSequentialExecutor))
+                .transformAsync(needCheckIn -> {
+                    if (needCheckIn) {
+                        return Futures.transform(scheduleInitialCheckInWork(),
+                                input -> false /* reschedule */, mSequentialExecutor);
+                    } else {
+                        return Futures.transform(
+                                GlobalParametersClient.getInstance().isProvisionReady(),
+                                ready -> !ready, mSequentialExecutor);
+                    }
+                }, mSequentialExecutor)
+                .transformAsync(reschedule -> {
+                    if (reschedule) {
+                        return notifyNeedRescheduleCheckIn();
+                    }
+                    return Futures.immediateVoidFuture();
+                }, mSequentialExecutor);
+    }
+
+    @Override
+    public void scheduleNextProvisionFailedStepAlarm(boolean shouldRunImmediately) {
+        LogUtil.d(TAG,
+                "Scheduling next provision failed step alarm. Run immediately: "
+                        + shouldRunImmediately);
+        long lastTimestamp = UserParameters.getNextProvisionFailedStepTimeMills(mContext);
+        long nextTimestamp;
+        if (lastTimestamp == 0) {
+            lastTimestamp = Instant.now(mClock).toEpochMilli();
+        }
+        long minutes = Build.isDebuggable() ? getSharedPreferences(mContext).getLong(
+                DEBUG_DEVICELOCK_REPORT_INTERVAL_MINUTES,
+                PROVISION_STATE_REPORT_INTERVAL_DEFAULT_MINUTES)
+                : PROVISION_STATE_REPORT_INTERVAL_DEFAULT_MINUTES;
+        Duration delay = shouldRunImmediately ? Duration.ZERO : Duration.ofMinutes(minutes);
+        nextTimestamp = lastTimestamp + delay.toMillis();
+        scheduleNextProvisionFailedStepAlarm(
+                Duration.between(Instant.now(mClock), Instant.ofEpochMilli(nextTimestamp)));
+        UserParameters.setNextProvisionFailedStepTimeMills(mContext, nextTimestamp);
+    }
+
+    @Override
+    public void notifyRebootWhenProvisionFailed() {
+        dispatchFuture(() -> {
+            rescheduleNextProvisionFailedStepAlarmIfNeeded();
+            rescheduleResetDeviceAlarmIfNeeded();
+        }, "notifyRebootWhenProvisionFailed");
+    }
+
+
+    @Override
+    public void scheduleResetDeviceAlarm() {
+        Duration delay = Duration.ofMinutes(NON_MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE);
+        if (Build.isDebuggable()) {
+            delay = Duration.ofMinutes(
+                    getSharedPreferences(mContext)
+                            .getInt(DEBUG_DEVICELOCK_RESET_DEVICE_MINUTES,
+                                    NON_MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE));
+        }
+        scheduleResetDeviceAlarm(delay);
+    }
+
+    @Override
+    public void scheduleMandatoryResetDeviceAlarm() {
+        Duration delay = Duration.ofMinutes(MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE);
+        if (Build.isDebuggable()) {
+            delay = Duration.ofMinutes(
+                    getSharedPreferences(mContext)
+                            .getInt(DEBUG_DEVICELOCK_MANDATORY_RESET_DEVICE_MINUTES,
+                                    MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE));
+        }
+        scheduleResetDeviceAlarm(delay);
+    }
+
+    private void scheduleResetDeviceAlarm(Duration delay) {
+        scheduleResetDeviceAlarmInternal(delay);
+        Instant whenExpectedToRun = Instant.now(mClock).plus(delay);
+        DeviceLockNotificationManager.sendDeviceResetTimerNotification(mContext,
+                SystemClock.elapsedRealtime() + delay.toMillis());
+        UserParameters.setResetDeviceTimeMillis(mContext, whenExpectedToRun.toEpochMilli());
+    }
+
+    @VisibleForTesting
+    void rescheduleNextProvisionFailedStepAlarmIfNeeded() {
+        long timestamp = UserParameters.getNextProvisionFailedStepTimeMills(mContext);
+        if (timestamp > 0) {
+            Duration delay = Duration.between(
+                    Instant.now(mClock),
+                    Instant.ofEpochMilli(timestamp));
+            scheduleNextProvisionFailedStepAlarm(delay);
+        }
+    }
+
+    @VisibleForTesting
+    void rescheduleResetDeviceAlarmIfNeeded() {
+        long timestamp = UserParameters.getResetDeviceTimeMillis(mContext);
+        if (timestamp > 0) {
+            Duration delay = Duration.between(
+                    Instant.now(mClock),
+                    Instant.ofEpochMilli(timestamp));
+            scheduleResetDeviceAlarmInternal(delay);
+        }
+    }
+
+    @VisibleForTesting
+    void rescheduleResumeProvisionAlarmIfNeeded() {
+        long resumeProvisionTimeMillis = UserParameters.getResumeProvisionTimeMillis(mContext);
+        if (resumeProvisionTimeMillis > 0) {
+            Duration delay = Duration.between(
+                    Instant.now(mClock),
+                    Instant.ofEpochMilli(resumeProvisionTimeMillis));
+            scheduleResumeProvisionAlarm(delay);
+        }
+    }
+
+    /**
+     * Run the input runnable in order on the scheduler's sequential executor
+     *
+     * @param runnable   The runnable to run on worker thread.
+     * @param methodName The name of the method that requested to run runnable.
+     */
+    private void dispatchFuture(Runnable runnable, String methodName) {
+        Futures.addCallback(Futures.submit(runnable, mSequentialExecutor),
+                new FutureCallback<>() {
+                    @Override
+                    public void onSuccess(Void unused) {
+                        LogUtil.i(TAG, "Successfully called " + methodName);
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                        throw new RuntimeException("failed to call " + methodName, t);
+                    }
+                }, MoreExecutors.directExecutor());
+    }
+
+    private Operation enqueueCheckInWorkRequest(boolean isExpedited, Duration delay) {
+        OneTimeWorkRequest.Builder builder =
+                new OneTimeWorkRequest.Builder(DeviceCheckInWorker.class)
+                        .setConstraints(
+                                new Constraints.Builder().setRequiredNetworkType(
+                                        NetworkType.CONNECTED).build())
+                        .setInitialDelay(delay)
+                        .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, BACKOFF_DELAY);
+        if (isExpedited) builder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST);
+
+        return WorkManager.getInstance(mContext).enqueueUniqueWork(DEVICE_CHECK_IN_WORK_NAME,
+                ExistingWorkPolicy.REPLACE, builder.build());
+    }
+
+    private void scheduleResumeProvisionAlarm(Duration delay) {
+        scheduleAlarmWithPendingIntentAndDelay(ResumeProvisionReceiver.class, delay);
+    }
+
+    private void scheduleNextProvisionFailedStepAlarm(Duration delay) {
+        scheduleAlarmWithPendingIntentAndDelay(NextProvisionFailedStepReceiver.class, delay);
+    }
+
+    private void scheduleResetDeviceAlarmInternal(Duration delay) {
+        scheduleAlarmWithPendingIntentAndDelay(ResetDeviceReceiver.class, delay);
+    }
+
+    private void scheduleAlarmWithPendingIntentAndDelay(
+            Class<? extends BroadcastReceiver> receiverClass, Duration delay) {
+        long countDownBase = SystemClock.elapsedRealtime() + delay.toMillis();
+        AlarmManager alarmManager = mContext.getSystemService(AlarmManager.class);
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, /* ignored */ 0,
+                new Intent(mContext, receiverClass),
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
+        Objects.requireNonNull(alarmManager).setExactAndAllowWhileIdle(
+                AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                countDownBase,
+                pendingIntent);
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/schedule/DeviceLockControllerSchedulerProvider.java b/DeviceLockController/src/com/android/devicelockcontroller/schedule/DeviceLockControllerSchedulerProvider.java
new file mode 100644
index 0000000..4dfde89
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/schedule/DeviceLockControllerSchedulerProvider.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.schedule;
+
+/**
+ * A provider interface that provides API to retrieve the instance of
+ * {@link DeviceLockControllerScheduler}
+ */
+public interface DeviceLockControllerSchedulerProvider {
+    /**
+     * Get the instance of {@link DeviceLockControllerScheduler} that is initialized at the
+     * application level.
+     */
+    DeviceLockControllerScheduler getDeviceLockControllerScheduler();
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/services/DeviceLockKeepAliveService.java b/DeviceLockController/src/com/android/devicelockcontroller/services/DeviceLockKeepAliveService.java
new file mode 100644
index 0000000..da75a37
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/services/DeviceLockKeepAliveService.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.services;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+
+import androidx.annotation.Nullable;
+
+import com.android.devicelockcontroller.util.LogUtil;
+
+/**
+ * Used to determine if the controller crashed while in lock task mode.
+ * Device lock system service component will restart the controller as needed.
+ */
+public final class DeviceLockKeepAliveService extends Service {
+    private static final String TAG = "DeviceLockKeepAliveService";
+    private final IBinder mBinder = new Binder();
+
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        LogUtil.i(TAG, "onBind called for DLC keep alive service");
+        return mBinder;
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/stats/StatsLogger.java b/DeviceLockController/src/com/android/devicelockcontroller/stats/StatsLogger.java
new file mode 100644
index 0000000..45361b5
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/stats/StatsLogger.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.stats;
+
+import androidx.annotation.IntDef;
+
+import com.android.devicelockcontroller.DevicelockStatsLog;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Utility class wrapping operations related to Statistics.
+ *
+ * Please refer to {@link DevicelockStatsLog} class and
+ * stats/atoms/devicelock/devicelock_extension_atoms.proto for more information.
+ */
+public interface StatsLogger {
+    /**
+     * Logs the analytics event of attempting to get device check in status from the server,
+     * regardless if the result is successful.
+     */
+    void logGetDeviceCheckInStatus();
+
+    /**
+     * Logs the analytics event of successfully pausing the device provisioning.
+     */
+    void logPauseDeviceProvisioning();
+
+    /**
+     * Logs the analytics event of successfully reporting the device provisioning state to the
+     * server.
+     */
+    void logReportDeviceProvisionState();
+
+    /**
+     * Logs the analytics event of receiving a result from the server of the
+     * IsDeviceInApprovedCountry gRPC call.
+     */
+    void logIsDeviceInApprovedCountry();
+
+    /**
+     * Logs the analytics event of receiving a request from the Kisok app.
+     *
+     * @param uid The UID of the Kiosk app, which can be acquired from the PackageManager.
+     */
+    void logKioskAppRequest(int uid);
+
+    /**
+     * Logs the analytics event of starting the provisioning process, starting the Kiosk app, and
+     * the time elapsed in between.
+     */
+    void logProvisioningComplete(long timeSpentInProvisioningMillis);
+
+    /**
+     * Logs the analytics event of resetting the device due to a failed provisioning.
+     *
+     * @param isProvisioningMandatory True if the provision is mandatory, false otherwise.
+     */
+    void logDeviceReset(boolean isProvisioningMandatory);
+
+    /**
+     * Logs the analytics event of successfully handling a check in response received from the
+     * server.
+     */
+    void logSuccessfulCheckIn();
+
+    /**
+     * Logs the analytics event of successfully completing the provisioning.
+     */
+    void logSuccessfulProvisioning();
+
+    /**
+     * Logs the analytics event of retrying a check in request.
+     *
+     * @param reason The reason of the retry, the enum corresponds to the RetryReason in
+     *               frameworks/proto_logging/stats/atoms/devicelock/devicelock_extension_atoms.proto
+     */
+    void logCheckInRetry(@CheckInRetryReason int reason);
+
+    // TODO(bojiandu): update this definition after updating the atom to match the new design
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            CheckInRetryReason.RESPONSE_UNSPECIFIED,
+            CheckInRetryReason.CONFIG_UNAVAILABLE,
+            CheckInRetryReason.NETWORK_TIME_UNAVAILABLE,
+            CheckInRetryReason.RPC_FAILURE
+    })
+    @interface CheckInRetryReason {
+        int RESPONSE_UNSPECIFIED = 0;
+        int CONFIG_UNAVAILABLE = 1;
+        int NETWORK_TIME_UNAVAILABLE = 2;
+        int RPC_FAILURE = 3;
+    }
+
+    /**
+     * Logs the analytics event of a provision failure.
+     *
+     * @param reason The reason of the failure, the enum corresponds to the FailureReason in
+     *               frameworks/proto_logging/stats/atoms/devicelock/devicelock_extension_atoms.proto
+     */
+    void logProvisionFailure(@ProvisionFailureReasonStats int reason);
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            ProvisionFailureReasonStats.UNKNOWN,
+            ProvisionFailureReasonStats.PLAY_TASK_UNAVAILABLE,
+            ProvisionFailureReasonStats.PLAY_INSTALLATION_FAILED,
+            ProvisionFailureReasonStats.COUNTRY_INFO_UNAVAILABLE,
+            ProvisionFailureReasonStats.NOT_IN_ELIGIBLE_COUNTRY,
+            ProvisionFailureReasonStats.POLICY_ENFORCEMENT_FAILED
+    })
+    @interface ProvisionFailureReasonStats {
+        // Unknown reason
+        int UNKNOWN = 0;
+        // Failed due to play task unavailable
+        int PLAY_TASK_UNAVAILABLE = 1;
+        // Failed due to installation from play unsuccessful
+        int PLAY_INSTALLATION_FAILED = 2;
+        // Failed due to country eligibility unknown
+        int COUNTRY_INFO_UNAVAILABLE = 3;
+        // Failed due to country not eligible
+        int NOT_IN_ELIGIBLE_COUNTRY = 4;
+        // Failed due to unable to enforce policies
+        int POLICY_ENFORCEMENT_FAILED = 5;
+    }
+
+    /**
+     * Logs the analytics event of a lock device failure.
+     *
+     * @param deviceStatePostCommand The device state after the lock device command
+     */
+    void logLockDeviceFailure(@DeviceStateStats int deviceStatePostCommand);
+
+    /**
+     * Logs the analytics event of a unlock device failure.
+     *
+     * @param deviceStatePostCommand The device state after the unlock device command
+     */
+    void logUnlockDeviceFailure(@DeviceStateStats int deviceStatePostCommand);
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            DeviceStateStats.UNDEFINED,
+            DeviceStateStats.UNLOCKED,
+            DeviceStateStats.LOCKED,
+            DeviceStateStats.CLEARED,
+    })
+    @interface DeviceStateStats {
+        int UNDEFINED = 0;
+        int UNLOCKED = 1;
+        int LOCKED = 2;
+        int CLEARED = 3;
+    }
+
+    /**
+     * Logs the analytics event of successfully locking the device.
+     */
+    void logSuccessfulLockingDevice();
+
+    /**
+     * Logs the analytics event of successfully unlocking the device.
+     */
+    void logSuccessfulUnlockingDevice();
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/stats/StatsLoggerImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/stats/StatsLoggerImpl.java
new file mode 100644
index 0000000..833fe08
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/stats/StatsLoggerImpl.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.stats;
+
+import static com.android.devicelockcontroller.DevicelockStatsLog.CHECK_IN_RETRY_REPORTED__REASON__COUNFIGURATION_UNAVAILABLE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.CHECK_IN_RETRY_REPORTED__REASON__NETWORK_TIME_UNAVAILABLE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.CHECK_IN_RETRY_REPORTED__REASON__RESPONSE_UNSPECIFIED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.CHECK_IN_RETRY_REPORTED__REASON__RPC_FAILURE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__GET_DEVICE_CHECK_IN_STATUS;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__IS_DEVICE_IN_APPROVED_COUNTRY;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__PAUSE_DEVICE_PROVISIONING;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__REPORT_DEVICE_PROVISION_STATE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_RETRY_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_KIOSK_APP_REQUEST_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_LOCK_UNLOCK_DEVICE_FAILURE_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_PROVISIONING_COMPLETE_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_PROVISION_FAILURE_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__CLEARED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__LOCKED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__UNDEFINED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__UNLOCKED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__COUNTRY_INFO_UNAVAILABLE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__NOT_IN_ELIGIBLE_COUNTRY;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__PLAY_INSTALLATION_FAILED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__PLAY_TASK_UNAVAILABLE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__POLICY_ENFORCEMENT_FAILED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__UNKNOWN;
+import static com.android.devicelockcontroller.stats.StatsLogger.CheckInRetryReason.CONFIG_UNAVAILABLE;
+import static com.android.devicelockcontroller.stats.StatsLogger.CheckInRetryReason.NETWORK_TIME_UNAVAILABLE;
+import static com.android.devicelockcontroller.stats.StatsLogger.CheckInRetryReason.RESPONSE_UNSPECIFIED;
+import static com.android.devicelockcontroller.stats.StatsLogger.CheckInRetryReason.RPC_FAILURE;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.COUNTRY_INFO_UNAVAILABLE;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.NOT_IN_ELIGIBLE_COUNTRY;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.PLAY_INSTALLATION_FAILED;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.PLAY_TASK_UNAVAILABLE;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.POLICY_ENFORCEMENT_FAILED;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.UNKNOWN;
+
+import com.android.devicelockcontroller.DevicelockStatsLog;
+
+import com.android.modules.expresslog.Counter;
+
+import java.util.concurrent.TimeUnit;
+
+public final class StatsLoggerImpl implements StatsLogger{
+    // The Telemetry Express metric ID for the counter of device reset due to failure of mandatory
+    // provisioning. As defined in
+    // platform/frameworks/proto_logging/stats/express/catalog/device_lock.cfg
+    static final String TEX_ID_DEVICE_RESET_PROVISION_MANDATORY =
+            "device_lock.value_resets_unsuccessful_provisioning_mandatory";
+    // The Telemetry Express metric ID for the counter of device reset due to failure of deferred
+    // provisioning. As defined in
+    // platform/frameworks/proto_logging/stats/express/catalog/device_lock.cfg
+    static final String TEX_ID_DEVICE_RESET_PROVISION_DEFERRED =
+            "device_lock.value_resets_unsuccessful_provisioning_deferred";
+    // The Telemetry Express metric ID for the counter of a successful check in request. As
+    // defined in platform/frameworks/proto_logging/stats/express/catalog/device_lock.cfg
+    static final String TEX_ID_SUCCESSFUL_CHECK_IN_RESPONSE_COUNT =
+            "device_lock.value_successful_check_in_response_count";
+    // The Telemetry Express metric ID for the counter of a successful provisioning. As
+    // defined in platform/frameworks/proto_logging/stats/express/catalog/device_lock.cfg
+    static final String TEX_ID_SUCCESSFUL_PROVISIONING_COUNT =
+            "device_lock.value_successful_provisioning_count";
+    // The Telemetry Express metric ID for the counter of a successful locking. As
+    // defined in platform/frameworks/proto_logging/stats/express/catalog/device_lock.cfg
+    static final String TEX_ID_SUCCESSFUL_LOCKING_COUNT =
+            "device_lock.value_successful_locking_count";
+    // The Telemetry Express metric ID for the counter of a successful unlocking. As
+    // defined in platform/frameworks/proto_logging/stats/express/catalog/device_lock.cfg
+    static final String TEX_ID_SUCCESSFUL_UNLOCKING_COUNT =
+            "device_lock.value_successful_unlocking_count";
+    private static final String TAG = "StatsLogger";
+
+    @Override
+    public void logGetDeviceCheckInStatus() {
+        DevicelockStatsLog.write(DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED,
+                DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__GET_DEVICE_CHECK_IN_STATUS);
+    }
+
+    @Override
+    public void logPauseDeviceProvisioning() {
+        DevicelockStatsLog.write(DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED,
+                DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__PAUSE_DEVICE_PROVISIONING);
+    }
+
+    @Override
+    public void logReportDeviceProvisionState() {
+        DevicelockStatsLog.write(DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED,
+                DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__REPORT_DEVICE_PROVISION_STATE);
+    }
+
+    @Override
+    public void logIsDeviceInApprovedCountry() {
+        DevicelockStatsLog.write(DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED,
+                DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__IS_DEVICE_IN_APPROVED_COUNTRY);
+    }
+
+    @Override
+    public void logKioskAppRequest(int uid) {
+        DevicelockStatsLog.write(DEVICE_LOCK_KIOSK_APP_REQUEST_REPORTED, uid);
+    }
+
+    @Override
+    public void logProvisioningComplete(long timeSpentInProvisioningMillis) {
+        DevicelockStatsLog.write(DEVICE_LOCK_PROVISIONING_COMPLETE_REPORTED,
+                TimeUnit.MILLISECONDS.toSeconds(timeSpentInProvisioningMillis));
+    }
+
+    @Override
+    public void logDeviceReset(boolean isProvisioningMandatory) {
+        if (isProvisioningMandatory) {
+            Counter.logIncrement(TEX_ID_DEVICE_RESET_PROVISION_MANDATORY);
+        } else {
+            Counter.logIncrement(TEX_ID_DEVICE_RESET_PROVISION_DEFERRED);
+        }
+    }
+
+    @Override
+    public void logSuccessfulCheckIn() {
+        Counter.logIncrement(TEX_ID_SUCCESSFUL_CHECK_IN_RESPONSE_COUNT);
+    }
+
+    @Override
+    public void logSuccessfulProvisioning() {
+        Counter.logIncrement(TEX_ID_SUCCESSFUL_PROVISIONING_COUNT);
+    }
+
+    @Override
+    public void logCheckInRetry(@CheckInRetryReason int reason) {
+        int checkInRetryReason;
+        switch (reason) {
+            case CONFIG_UNAVAILABLE -> checkInRetryReason =
+                    CHECK_IN_RETRY_REPORTED__REASON__COUNFIGURATION_UNAVAILABLE;
+            case NETWORK_TIME_UNAVAILABLE -> checkInRetryReason =
+                    CHECK_IN_RETRY_REPORTED__REASON__NETWORK_TIME_UNAVAILABLE;
+            case RESPONSE_UNSPECIFIED -> checkInRetryReason =
+                    CHECK_IN_RETRY_REPORTED__REASON__RESPONSE_UNSPECIFIED;
+            case RPC_FAILURE -> checkInRetryReason = CHECK_IN_RETRY_REPORTED__REASON__RPC_FAILURE;
+            default -> checkInRetryReason = CHECK_IN_RETRY_REPORTED__REASON__RESPONSE_UNSPECIFIED;
+        }
+        DevicelockStatsLog.write(DEVICE_LOCK_CHECK_IN_RETRY_REPORTED, checkInRetryReason);
+    }
+
+    @Override
+    public void logProvisionFailure(@ProvisionFailureReasonStats int reason) {
+        int provisionFailureReason;
+        switch (reason) {
+            case POLICY_ENFORCEMENT_FAILED -> provisionFailureReason =
+                    PROVISION_FAILURE_REPORTED__REASON__POLICY_ENFORCEMENT_FAILED;
+            case PLAY_TASK_UNAVAILABLE -> provisionFailureReason =
+                    PROVISION_FAILURE_REPORTED__REASON__PLAY_TASK_UNAVAILABLE;
+            case NOT_IN_ELIGIBLE_COUNTRY -> provisionFailureReason =
+                    PROVISION_FAILURE_REPORTED__REASON__NOT_IN_ELIGIBLE_COUNTRY;
+            case COUNTRY_INFO_UNAVAILABLE -> provisionFailureReason =
+                    PROVISION_FAILURE_REPORTED__REASON__COUNTRY_INFO_UNAVAILABLE;
+            case PLAY_INSTALLATION_FAILED -> provisionFailureReason =
+                    PROVISION_FAILURE_REPORTED__REASON__PLAY_INSTALLATION_FAILED;
+            case UNKNOWN -> provisionFailureReason = PROVISION_FAILURE_REPORTED__REASON__UNKNOWN;
+            default -> provisionFailureReason = PROVISION_FAILURE_REPORTED__REASON__UNKNOWN;
+        }
+        DevicelockStatsLog.write(DEVICE_LOCK_PROVISION_FAILURE_REPORTED, provisionFailureReason);
+    }
+
+    @Override
+    public void logLockDeviceFailure(@DeviceStateStats int deviceStatePostCommand) {
+        DevicelockStatsLog.write(DEVICE_LOCK_LOCK_UNLOCK_DEVICE_FAILURE_REPORTED,
+                /* arg1 = (isLock)*/ true,
+                getStatePostCommandForLockUnlockDeviceFailure(deviceStatePostCommand));
+    }
+
+    @Override
+    public void logUnlockDeviceFailure(@DeviceStateStats int deviceStatePostCommand) {
+        DevicelockStatsLog.write(DEVICE_LOCK_LOCK_UNLOCK_DEVICE_FAILURE_REPORTED,
+                /* arg1 = (isLock)*/ false,
+                getStatePostCommandForLockUnlockDeviceFailure(deviceStatePostCommand));
+    }
+
+    private int getStatePostCommandForLockUnlockDeviceFailure(@DeviceStateStats int deviceState) {
+        switch (deviceState) {
+            case DeviceStateStats.UNDEFINED -> {
+                return LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__UNDEFINED;
+            }
+            case DeviceStateStats.UNLOCKED -> {
+                return LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__UNLOCKED;
+            }
+            case DeviceStateStats.LOCKED -> {
+                return LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__LOCKED;
+            }
+            case DeviceStateStats.CLEARED -> {
+                return LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__CLEARED;
+            }
+            default -> {
+                return LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__UNDEFINED;
+            }
+        }
+    }
+
+    @Override
+    public void logSuccessfulLockingDevice() {
+        Counter.logIncrement(TEX_ID_SUCCESSFUL_LOCKING_COUNT);
+    }
+
+    @Override
+    public void logSuccessfulUnlockingDevice() {
+        Counter.logIncrement(TEX_ID_SUCCESSFUL_UNLOCKING_COUNT);
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/stats/StatsLoggerProvider.java b/DeviceLockController/src/com/android/devicelockcontroller/stats/StatsLoggerProvider.java
new file mode 100644
index 0000000..28831c8
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/stats/StatsLoggerProvider.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.stats;
+
+/**
+ * Interface for getting {@link StatsLogger}
+ */
+public interface StatsLoggerProvider {
+    StatsLogger getStatsLogger();
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParameters.java b/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParameters.java
index 5e25a72..58c3c7a 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParameters.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParameters.java
@@ -19,14 +19,15 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.os.Build;
-import android.util.ArraySet;
 
 import androidx.annotation.Nullable;
 
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
+import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
+import com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState;
+import com.android.devicelockcontroller.util.LogUtil;
 
-import java.util.ArrayList;
-import java.util.Set;
+import java.util.Locale;
 
 /**
  * Stores global parameters.
@@ -37,13 +38,13 @@
  */
 final class GlobalParameters {
     private static final String FILENAME = "global-params";
-    private static final String KEY_KIOSK_SIGNING_CERT = "kiosk_signing_cert";
-    private static final String KEY_LOCK_TASK_ALLOWLIST = "lock_task_allowlist";
-    private static final String KEY_NEED_CHECK_IN = "need_check_in";
     private static final String KEY_REGISTERED_DEVICE_ID = "registered_device_id";
     private static final String KEY_FORCED_PROVISION = "forced_provision";
-    private static final String KEY_ENROLLMENT_TOKEN = "enrollment_token";
     private static final String KEY_LAST_RECEIVED_PROVISION_STATE = "last-received-provision-state";
+    private static final String TAG = "GlobalParameters";
+    private static final String KEY_DEVICE_STATE = "device_state";
+    private static final String KEY_FINALIZATION_STATE = "finalization_state";
+    public static final String KEY_IS_PROVISION_READY = "key-is-provision-ready";
 
 
     private GlobalParameters() {
@@ -55,81 +56,13 @@
         return deviceContext.getSharedPreferences(FILENAME, Context.MODE_PRIVATE);
     }
 
-    /**
-     * Get the kiosk app signature.
-     *
-     * @param context Context used to get the shared preferences.
-     * @return the kiosk app signature.
-     */
-    @Nullable
-    static String getKioskSignature(Context context) {
-        return getSharedPreferences(context).getString(KEY_KIOSK_SIGNING_CERT, null);
+    static boolean isProvisionReady(Context context) {
+        return getSharedPreferences(context).getBoolean(KEY_IS_PROVISION_READY, false);
     }
 
-    /**
-     * Sets the kiosk app signature.
-     *
-     * @param context   Context used to get the shared preferences.
-     * @param signature Kiosk app signature.
-     */
-    static void setKioskSignature(Context context, String signature) {
-        getSharedPreferences(context).edit().putString(KEY_KIOSK_SIGNING_CERT, signature).apply();
-    }
-
-    /**
-     * Gets the list of packages allowlisted in lock task mode.
-     *
-     * @param context Context used to get the shared preferences.
-     * @return List of packages that are allowed in lock task mode.
-     */
-    static ArrayList<String> getLockTaskAllowlist(Context context) {
-        final ArrayList<String> allowlistArray = new ArrayList<>();
-        SharedPreferences sharedPreferences = getSharedPreferences(context);
-        final Set<String> allowlist =
-                sharedPreferences.getStringSet(KEY_LOCK_TASK_ALLOWLIST, /* defValue= */ null);
-        if (allowlist != null) {
-            allowlistArray.addAll(allowlist);
-        }
-
-        return allowlistArray;
-    }
-
-    /**
-     * Sets the list of packages allowlisted in lock task mode.
-     *
-     * @param context   Context used to get the shared preferences.
-     * @param allowlist List of packages that are allowed in lock task mode.
-     */
-    static void setLockTaskAllowlist(Context context, ArrayList<String> allowlist) {
-        final Set<String> allowlistSet = new ArraySet<>(allowlist);
-
-        getSharedPreferences(context)
-                .edit()
-                .putStringSet(KEY_LOCK_TASK_ALLOWLIST, allowlistSet)
-                .apply();
-    }
-
-    /**
-     * Checks if a check-in request needs to be performed.
-     *
-     * @param context Context used to get the shared preferences.
-     * @return true if check-in request needs to be performed.
-     */
-    static boolean needCheckIn(Context context) {
-        return getSharedPreferences(context).getBoolean(KEY_NEED_CHECK_IN, /* defValue= */ true);
-    }
-
-    /**
-     * Sets the value of whether this device needs to perform check-in request.
-     *
-     * @param context     Context used to get the shared preferences.
-     * @param needCheckIn new state of whether the device needs to perform check-in request.
-     */
-    static void setNeedCheckIn(Context context, boolean needCheckIn) {
-        getSharedPreferences(context)
-                .edit()
-                .putBoolean(KEY_NEED_CHECK_IN, needCheckIn)
-                .apply();
+    static void setProvisionReady(Context context, boolean isProvisionReady) {
+        getSharedPreferences(context).edit().putBoolean(KEY_IS_PROVISION_READY,
+                isProvisionReady).apply();
     }
 
     /**
@@ -169,6 +102,37 @@
     }
 
     /**
+     * Gets the current device state.
+     */
+    @DeviceState
+    static int getDeviceState(Context context) {
+        return getSharedPreferences(context).getInt(KEY_DEVICE_STATE, DeviceState.UNDEFINED);
+    }
+
+    /**
+     * Sets the current device state.
+     */
+    static void setDeviceState(Context context, @DeviceState int state) {
+        getSharedPreferences(context).edit().putInt(KEY_DEVICE_STATE, state).apply();
+    }
+
+    /**
+     * Gets the current {@link FinalizationState}.
+     */
+    @FinalizationState
+    static int getFinalizationState(Context context) {
+        return getSharedPreferences(context).getInt(
+                KEY_FINALIZATION_STATE, FinalizationState.UNFINALIZED);
+    }
+
+    /**
+     * Sets the current {@link FinalizationState}.
+     */
+    static void setFinalizationState(Context context, @FinalizationState int state) {
+        getSharedPreferences(context).edit().putInt(KEY_FINALIZATION_STATE, state).apply();
+    }
+
+    /**
      * Set provision is forced
      *
      * @param context  Context used to get the shared preferences.
@@ -181,30 +145,6 @@
                 .apply();
     }
 
-    /**
-     * Get the enrollment token assigned by the Device Lock backend server.
-     *
-     * @param context Context used to get the shared preferences.
-     * @return A string value of the enrollment token.
-     */
-    @Nullable
-    static String getEnrollmentToken(Context context) {
-        return getSharedPreferences(context).getString(KEY_ENROLLMENT_TOKEN, null);
-    }
-
-    /**
-     * Set the enrollment token assigned by the Device Lock backend server.
-     *
-     * @param context Context used to get the shared preferences.
-     * @param token   The string value of the enrollment token.
-     */
-    static void setEnrollmentToken(Context context, String token) {
-        getSharedPreferences(context)
-                .edit()
-                .putString(KEY_ENROLLMENT_TOKEN, token)
-                .apply();
-    }
-
     @DeviceProvisionState
     static int getLastReceivedProvisionState(Context context) {
         return getSharedPreferences(context).getInt(KEY_LAST_RECEIVED_PROVISION_STATE,
@@ -225,4 +165,20 @@
         }
         getSharedPreferences(context).edit().clear().commit();
     }
+
+    static void dump(Context context) {
+        LogUtil.d(TAG, String.format(Locale.US,
+                "Dumping GlobalParameters ...\n"
+                        + "%s: %s\n"    // registered_device_id:
+                        + "%s: %s\n"    // forced_provision:
+                        + "%s: %s\n"    // last-received-provision-state:
+                        + "%s: %s\n"    // device_state:
+                        + "%s: %s\n",    // is-provision-ready:
+                KEY_REGISTERED_DEVICE_ID, getRegisteredDeviceId(context),
+                KEY_FORCED_PROVISION, isProvisionForced(context),
+                KEY_LAST_RECEIVED_PROVISION_STATE, getLastReceivedProvisionState(context),
+                KEY_DEVICE_STATE, getDeviceState(context),
+                KEY_IS_PROVISION_READY, isProvisionReady(context)
+        ));
+    }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParametersClient.java b/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParametersClient.java
index 0c987a0..ceb0115 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParametersClient.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParametersClient.java
@@ -29,12 +29,13 @@
 
 import com.android.devicelockcontroller.DeviceLockControllerApplication;
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
+import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
+import com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 
-import java.util.List;
 import java.util.concurrent.Executors;
 
 /**
@@ -105,53 +106,41 @@
     }
 
     /**
-     * Gets the list of packages allowlisted in lock task mode.
-     *
-     * @return List of packages that are allowed in lock task mode.
+     * Dump current values of SetupParameters to logcat.
      */
     @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
-    public ListenableFuture<List<String>> getLockTaskAllowlist() {
-        return call(() -> asInterface(getService()).getLockTaskAllowlist());
-    }
-
-    /**
-     * Sets the list of packages allowlisted in lock task mode.
-     *
-     * @param allowlist List of packages that are allowed in lock task mode.
-     */
-    @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
-    public ListenableFuture<Void> setLockTaskAllowlist(List<String> allowlist) {
+    public ListenableFuture<Void> dump() {
         return call(() -> {
-            asInterface(getService()).setLockTaskAllowlist(allowlist);
+            asInterface(getService()).dump();
             return null;
         });
     }
 
     /**
-     * Checks if a check-in request needs to be performed.
+     * Checks if provision is ready.
      *
-     * @return true if check-in request needs to be performed.
+     * @return true if device is ready to be provisioned.
      */
     @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
-    public ListenableFuture<Boolean> needCheckIn() {
-        return call(() -> asInterface(getService()).needCheckIn());
+    public ListenableFuture<Boolean> isProvisionReady() {
+        return call(() -> asInterface(getService()).isProvisionReady());
     }
 
     /**
-     * Sets the value of whether this device needs to perform check-in request.
+     * Sets the value of whether this device is ready for provision.
      *
-     * @param needCheckIn new state of whether the device needs to perform check-in request.
+     * @param isProvisionReady new state of whether the device is ready for provision.
      */
     @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
-    public ListenableFuture<Void> setNeedCheckIn(boolean needCheckIn) {
+    public ListenableFuture<Void> setProvisionReady(boolean isProvisionReady) {
         return call(() -> {
-            asInterface(getService()).setNeedCheckIn(needCheckIn);
+            asInterface(getService()).setProvisionReady(isProvisionReady);
             return null;
         });
     }
 
     /**
-     * Gets the unique identifier that is regisered to DeviceLock backend server.
+     * Gets the unique identifier that is registered to DeviceLock backend server.
      *
      * @return The registered device unique identifier; null if device has never checked in with
      * backed server.
@@ -199,49 +188,47 @@
     }
 
     /**
-     * Get the enrollment token assigned by the Device Lock backend server.
+     * Gets the current device state.
      *
-     * @return A string value of the enrollment token.
+     * @return current device state
      */
-    @Nullable
     @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
-    public ListenableFuture<String> getEnrollmentToken() {
-        return call(() -> asInterface(getService()).getEnrollmentToken());
+    public ListenableFuture<@DeviceState Integer> getDeviceState() {
+        return call(() -> asInterface(getService()).getDeviceState());
     }
 
     /**
-     * Set the enrollment token assigned by the Device Lock backend server.
+     * Sets the current device state.
      *
-     * @param token The string value of the enrollment token.
+     * @param state New state.
      */
     @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
-    public ListenableFuture<Void> setEnrollmentToken(String token) {
+    public ListenableFuture<Void> setDeviceState(@DeviceState int state) {
         return call(() -> {
-            asInterface(getService()).setEnrollmentToken(token);
+            asInterface(getService()).setDeviceState(state);
             return null;
         });
     }
 
     /**
-     * Get the kiosk app signature.
+     * Gets the current {@link FinalizationState}.
      *
-     * @return the kiosk app signature.
+     * @return current finalization state
      */
-    @Nullable
     @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
-    public ListenableFuture<String> getKioskSignature() {
-        return call(() -> asInterface(getService()).getKioskSignature());
+    public ListenableFuture<@FinalizationState Integer> getFinalizationState() {
+        return call(() -> asInterface(getService()).getFinalizationState());
     }
 
     /**
-     * Sets the kiosk app signature.
+     * Sets the current {@link FinalizationState}.
      *
-     * @param signature Kiosk app signature.
+     * @param state new finalization state
      */
     @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
-    public ListenableFuture<Void> setKioskSignature(String signature) {
+    public ListenableFuture<Void> setFinalizationState(@FinalizationState int state) {
         return call(() -> {
-            asInterface(getService()).setKioskSignature(signature);
+            asInterface(getService()).setFinalizationState(state);
             return null;
         });
     }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParametersService.java b/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParametersService.java
index 173fa9c..94ec96a 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParametersService.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/storage/GlobalParametersService.java
@@ -22,11 +22,10 @@
 import android.os.IBinder;
 
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
+import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
+import com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState;
 import com.android.devicelockcontroller.util.LogUtil;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * A class exposing Global Parameters as a service.
  */
@@ -43,23 +42,18 @@
                 }
 
                 @Override
-                public List<String> getLockTaskAllowlist() {
-                    return GlobalParameters.getLockTaskAllowlist(mContext);
+                public void dump() {
+                    GlobalParameters.dump(mContext);
                 }
 
                 @Override
-                public void setLockTaskAllowlist(List<String> allowlist) {
-                    GlobalParameters.setLockTaskAllowlist(mContext, new ArrayList<>(allowlist));
+                public boolean isProvisionReady() {
+                    return GlobalParameters.isProvisionReady(mContext);
                 }
 
                 @Override
-                public boolean needCheckIn() {
-                    return GlobalParameters.needCheckIn(mContext);
-                }
-
-                @Override
-                public void setNeedCheckIn(boolean needCheckIn) {
-                    GlobalParameters.setNeedCheckIn(mContext, needCheckIn);
+                public void setProvisionReady(boolean isProvisionReady) {
+                    GlobalParameters.setProvisionReady(mContext, isProvisionReady);
                 }
 
                 @Override
@@ -83,23 +77,23 @@
                 }
 
                 @Override
-                public String getEnrollmentToken() {
-                    return GlobalParameters.getEnrollmentToken(mContext);
+                public int getDeviceState() {
+                    return GlobalParameters.getDeviceState(mContext);
                 }
 
                 @Override
-                public void setEnrollmentToken(String token) {
-                    GlobalParameters.setEnrollmentToken(mContext, token);
+                public void setDeviceState(@DeviceState int state) {
+                    GlobalParameters.setDeviceState(mContext, state);
                 }
 
                 @Override
-                public String getKioskSignature() {
-                    return GlobalParameters.getKioskSignature(mContext);
+                public @FinalizationState int getFinalizationState() {
+                    return GlobalParameters.getFinalizationState(mContext);
                 }
 
                 @Override
-                public void setKioskSignature(String kioskSignature) {
-                    GlobalParameters.setKioskSignature(mContext, kioskSignature);
+                public void setFinalizationState(@FinalizationState int state) {
+                    GlobalParameters.setFinalizationState(mContext, state);
                 }
 
                 @Override
@@ -113,8 +107,6 @@
                         @DeviceProvisionState int provisionState) {
                     GlobalParameters.setLastReceivedProvisionState(mContext, provisionState);
                 }
-
-
             };
 
     @Override
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/storage/IGlobalParametersService.aidl b/DeviceLockController/src/com/android/devicelockcontroller/storage/IGlobalParametersService.aidl
index dbfe257..b8ce9b0 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/storage/IGlobalParametersService.aidl
+++ b/DeviceLockController/src/com/android/devicelockcontroller/storage/IGlobalParametersService.aidl
@@ -22,18 +22,17 @@
  */
 interface IGlobalParametersService {
     void clear();
-    List<String> getLockTaskAllowlist();
-    void setLockTaskAllowlist(in List<String> allowlist);
-    boolean needCheckIn();
-    void setNeedCheckIn(boolean needCheckIn);
+    void dump();
+    boolean isProvisionReady();
+    void setProvisionReady(boolean isProvisionReady);
     String getRegisteredDeviceId();
     void setRegisteredDeviceId(String registeredDeviceId);
     boolean isProvisionForced();
     void setProvisionForced(boolean isForced);
-    String getEnrollmentToken();
-    void setEnrollmentToken(String token);
-    String getKioskSignature();
-    void setKioskSignature(String signature);
+    int getDeviceState();
+    void setDeviceState(int state);
+    int getFinalizationState();
+    void setFinalizationState(int state);
     int getLastReceivedProvisionState();
     void setLastReceivedProvisionState(int provisionState);
 }
\ No newline at end of file
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/storage/ISetupParametersService.aidl b/DeviceLockController/src/com/android/devicelockcontroller/storage/ISetupParametersService.aidl
index 3db45df..33e5373 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/storage/ISetupParametersService.aidl
+++ b/DeviceLockController/src/com/android/devicelockcontroller/storage/ISetupParametersService.aidl
@@ -24,8 +24,8 @@
     void overridePrefs(in Bundle bundle);
     void createPrefs(in Bundle bundle);
     void clear();
+    void dump();
     String getKioskPackage();
-    String getKioskSetupActivity();
     boolean getOutgoingCallsDisabled();
     List<String> getKioskAllowlist();
     boolean isNotificationsInLockTaskModeEnabled();
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParameters.java b/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParameters.java
index c3d387a..1eda07e 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParameters.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParameters.java
@@ -22,7 +22,6 @@
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_DISABLE_OUTGOING_CALLS;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_SETUP_ACTIVITY;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_MANDATORY_PROVISION;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_PROVISIONING_TYPE;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_SUPPORT_URL;
@@ -58,7 +57,6 @@
     private static final String TAG = "SetupParameters";
     private static final String FILENAME = "setup-prefs";
     private static final String KEY_KIOSK_PACKAGE = "kiosk-package-name";
-    private static final String KEY_KIOSK_SETUP_ACTIVITY = "kiosk-setup-activity";
     private static final String KEY_KIOSK_ALLOWLIST = "kiosk-allowlist";
     private static final String KEY_KIOSK_DISABLE_OUTGOING_CALLS =
             "kiosk-disable-outgoing-calls";
@@ -92,11 +90,10 @@
         dumpParameters(context);
     }
 
-    private static void dumpParameters(Context context) {
+    static void dumpParameters(Context context) {
         LogUtil.d(TAG, String.format(Locale.US,
                 "Dumping SetupParameters ...\n"
                 + "%s: %s\n"    // kiosk-package-name:
-                + "%s: %s\n"    // kiosk-setup-activity:
                 + "%s: %s\n"    // kiosk-allowlist:
                 + "%s: %s\n"    // kiosk-disable-outgoing-calls:
                 + "%s: %s\n"    // kiosk-enable-notifications-in-lock-task-mode:
@@ -107,7 +104,6 @@
                 + "%s: %s\n"    // terms-and-conditions-url:
                 + "%s: %s\n",   // support-url:
                 KEY_KIOSK_PACKAGE, getKioskPackage(context),
-                KEY_KIOSK_SETUP_ACTIVITY, getKioskSetupActivity(context),
                 KEY_KIOSK_ALLOWLIST, getKioskAllowlist(context),
                 KEY_KIOSK_DISABLE_OUTGOING_CALLS, getOutgoingCallsDisabled(context),
                 KEY_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE,
@@ -143,7 +139,6 @@
 
         SharedPreferences.Editor editor = sharedPreferences.edit();
         editor.putString(KEY_KIOSK_PACKAGE, bundle.getString(EXTRA_KIOSK_PACKAGE));
-        editor.putString(KEY_KIOSK_SETUP_ACTIVITY, bundle.getString(EXTRA_KIOSK_SETUP_ACTIVITY));
         editor.putBoolean(KEY_KIOSK_DISABLE_OUTGOING_CALLS,
                 bundle.getBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS));
         editor.putBoolean(KEY_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE,
@@ -174,18 +169,6 @@
     }
 
     /**
-     * Get the setup activity for the kiosk app.
-     *
-     * @param context Context used to get the shared preferences.
-     * @return Setup activity.
-     */
-    @Nullable
-    static String getKioskSetupActivity(Context context) {
-        return getSharedPreferences(context)
-                .getString(KEY_KIOSK_SETUP_ACTIVITY, null /* defValue */);
-    }
-
-    /**
      * Check if the configuration disables outgoing calls.
      *
      * @param context Context used to get the shared preferences.
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParametersClient.java b/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParametersClient.java
index 59bc685..b2f2878 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParametersClient.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParametersClient.java
@@ -107,6 +107,18 @@
     }
 
     /**
+     * Dump current values of SetupParameters to logcat.
+     * Note that this API can only be called in debuggable build for debugging purpose.
+     */
+    @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
+    public ListenableFuture<Void> dump() {
+        return call(() -> {
+            asInterface(getService()).dump();
+            return null;
+        });
+    }
+
+    /**
      * Clear any existing setup parameters.
      * Note that this API can only be called in debuggable build for debugging purpose.
      */
@@ -143,16 +155,6 @@
     }
 
     /**
-     * Get the setup activity for the kiosk app.
-     *
-     * @return Setup activity.
-     */
-    @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone).
-    public ListenableFuture<String> getKioskSetupActivity() {
-        return call(() -> asInterface(getService()).getKioskSetupActivity());
-    }
-
-    /**
      * Check if the configuration disables outgoing calls.
      *
      * @return True if outgoign calls are disabled.
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParametersService.java b/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParametersService.java
index 8420252..df1bb09 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParametersService.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/storage/SetupParametersService.java
@@ -47,6 +47,11 @@
                 }
 
                 @Override
+                public void dump() {
+                    SetupParameters.dumpParameters(mContext);
+                }
+
+                @Override
                 public void clear() {
                     SetupParameters.clear(mContext);
                 }
@@ -57,11 +62,6 @@
                 }
 
                 @Override
-                public String getKioskSetupActivity() {
-                    return SetupParameters.getKioskSetupActivity(mContext);
-                }
-
-                @Override
                 public boolean getOutgoingCallsDisabled() {
                     return SetupParameters.getOutgoingCallsDisabled(mContext);
                 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/storage/UserParameters.java b/DeviceLockController/src/com/android/devicelockcontroller/storage/UserParameters.java
index 33fe0e4..3440b04 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/storage/UserParameters.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/storage/UserParameters.java
@@ -16,13 +16,20 @@
 
 package com.android.devicelockcontroller.storage;
 
+import android.annotation.CurrentTimeMillisLong;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.os.Build;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
 
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState;
+import com.android.devicelockcontroller.util.LogUtil;
+import com.android.devicelockcontroller.util.ThreadAsserts;
+
+import java.util.Locale;
+import java.util.concurrent.Executors;
 
 /**
  * Stores per-user local parameters.
@@ -30,9 +37,22 @@
  */
 public final class UserParameters {
     private static final String FILENAME = "user-params";
-    private static final String KEY_DEVICE_STATE = "device_state";
     private static final String KEY_HOME_PACKAGE_OVERRIDE = "home_override_package";
     private static final String TAG = "UserParameters";
+    private static final String KEY_PROVISION_STATE = "provision-state";
+    private static final String KEY_BOOT_TIME_MILLS = "boot-time-mills";
+    private static final String KEY_NEXT_CHECK_IN_TIME_MILLIS = "next-check-in-time-millis";
+    private static final String KEY_RESUME_PROVISION_TIME_MILLIS =
+            "resume-provision-time-millis";
+    private static final String KEY_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS =
+            "next-provision-failed-step-time-millis";
+    private static final String KEY_RESET_DEVICE_TIME_MILLIS = "reset-device-time-millis";
+    private static final String KEY_DAYS_LEFT_UNTIL_RESET = "days-left-until-reset";
+    private static final String KEY_PROVISIONING_START_TIME_MILLIS =
+            "provisioning-start-time-millis";
+    public static final String KEY_NEED_INITIAL_CHECK_IN = "need-initial-check-in";
+    public static final String KEY_NOTIFICATION_CHANNEL_ID_SUFFIX =
+            "notification-channel-id-suffix";
 
     private UserParameters() {
     }
@@ -43,37 +63,34 @@
         return deviceContext.getSharedPreferences(FILENAME, Context.MODE_PRIVATE);
     }
 
-
     /**
-     * Gets the current device state.
-     *
-     * @param context Context used to get the shared preferences.
-     * @return the current device state.
+     * Gets the current user state.
      */
-    @DeviceState
-    public static int getDeviceState(Context context) {
-        return getSharedPreferences(context).getInt(KEY_DEVICE_STATE, DeviceState.UNPROVISIONED);
+    @WorkerThread
+    @ProvisionState
+    public static int getProvisionState(Context context) {
+        ThreadAsserts.assertWorkerThread("getProvisionState");
+        return getSharedPreferences(context).getInt(KEY_PROVISION_STATE,
+                ProvisionState.UNPROVISIONED);
     }
 
     /**
-     * Sets the current device state.
-     *
-     * @param context Context used to get the shared preferences.
-     * @param state   New state.
+     * Sets the current user state.
      */
-    public static void setDeviceState(Context context, @DeviceState int state) {
-        getSharedPreferences(context).edit().putInt(KEY_DEVICE_STATE, state).apply();
+    public static void setProvisionState(Context context, @ProvisionState int state) {
+        getSharedPreferences(context).edit().putInt(KEY_PROVISION_STATE, state).apply();
     }
 
-    /**
-     * Sets the current device state and synchronously write to storage. This call will block until
-     * write is complete.
-     *
-     * @param state new {@link DeviceState}
-     * @return true if state is set successfully; otherwise, false.
-     */
-    public static boolean setDeviceStateSync(Context context, @DeviceState int state) {
-        return getSharedPreferences(context).edit().putInt(KEY_DEVICE_STATE, state).commit();
+    /** Check if initial check-in is required. */
+    @WorkerThread
+    public static boolean needInitialCheckIn(Context context) {
+        ThreadAsserts.assertWorkerThread("needInitialCheckIn");
+        return getSharedPreferences(context).getBoolean(KEY_NEED_INITIAL_CHECK_IN, true);
+    }
+
+    /** Mark initial check-in has been scheduled. */
+    public static void initialCheckInScheduled(Context context) {
+        getSharedPreferences(context).edit().putBoolean(KEY_NEED_INITIAL_CHECK_IN, false).apply();
     }
 
     /**
@@ -82,8 +99,10 @@
      * @param context Context used to get the shared preferences.
      * @return Package overriding home.
      */
+    @WorkerThread
     @Nullable
     public static String getPackageOverridingHome(Context context) {
+        ThreadAsserts.assertWorkerThread("getPackageOverridingHome");
         return getSharedPreferences(context).getString(KEY_HOME_PACKAGE_OVERRIDE, null);
     }
 
@@ -98,13 +117,164 @@
                 .putString(KEY_HOME_PACKAGE_OVERRIDE, packageName).apply();
     }
 
+    /** Get the device boot time */
+    @WorkerThread
+    @CurrentTimeMillisLong
+    public static long getBootTimeMillis(Context context) {
+        ThreadAsserts.assertWorkerThread("getBootTimeMillis");
+        return getSharedPreferences(context).getLong(KEY_BOOT_TIME_MILLS, 0L);
+    }
+
+    /** Set the time when device boot */
+    public static void setBootTimeMillis(Context context, @CurrentTimeMillisLong long bootTime) {
+        getSharedPreferences(context).edit().putLong(KEY_BOOT_TIME_MILLS, bootTime).apply();
+    }
+
+    /** Get the time when next check in should happen */
+    @WorkerThread
+    @CurrentTimeMillisLong
+    public static long getNextCheckInTimeMillis(Context context) {
+        ThreadAsserts.assertWorkerThread("getNextCheckInTimeMillis");
+        return getSharedPreferences(context).getLong(KEY_NEXT_CHECK_IN_TIME_MILLIS, 0L);
+    }
+
+    /** Set the time when next check in should happen */
+    public static void setNextCheckInTimeMillis(Context context,
+            @CurrentTimeMillisLong long nextCheckInTime) {
+        getSharedPreferences(context).edit().putLong(KEY_NEXT_CHECK_IN_TIME_MILLIS,
+                nextCheckInTime).apply();
+    }
+
+    /** Get the time when provision should resume */
+    @WorkerThread
+    @CurrentTimeMillisLong
+    public static long getResumeProvisionTimeMillis(Context context) {
+        ThreadAsserts.assertWorkerThread("getResumeProvisionTimeMillis");
+        return getSharedPreferences(context).getLong(KEY_RESUME_PROVISION_TIME_MILLIS, 0L);
+    }
+
+    /** Set the time when provision should resume */
+    public static void setResumeProvisionTimeMillis(Context context,
+            @CurrentTimeMillisLong long resumeProvisionTime) {
+        getSharedPreferences(context).edit().putLong(KEY_RESUME_PROVISION_TIME_MILLIS,
+                resumeProvisionTime).apply();
+    }
+
+    /** Get the time when next provision failed step should happen */
+    @WorkerThread
+    @CurrentTimeMillisLong
+    public static long getNextProvisionFailedStepTimeMills(Context context) {
+        ThreadAsserts.assertWorkerThread("getNextProvisionFailedStepTimeMills");
+        return getSharedPreferences(context).getLong(KEY_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS,
+                0L);
+    }
+
+    /** Set the time when next provision failed step should happen */
+    public static void setNextProvisionFailedStepTimeMills(Context context,
+            @CurrentTimeMillisLong long nextProvisionFailedStep) {
+        getSharedPreferences(context).edit().putLong(KEY_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS,
+                nextProvisionFailedStep).apply();
+    }
+
+    /** Get the time when device should factory reset */
+    @WorkerThread
+    @CurrentTimeMillisLong
+    public static long getResetDeviceTimeMillis(Context context) {
+        ThreadAsserts.assertWorkerThread("getResetDeviceTimeMillis");
+        return getSharedPreferences(context).getLong(KEY_RESET_DEVICE_TIME_MILLIS, 0L);
+    }
+
+    /** Set the time when device should factory reset */
+    public static void setResetDeviceTimeMillis(Context context,
+            @CurrentTimeMillisLong long resetDeviceTime) {
+        getSharedPreferences(context).edit().putLong(KEY_RESET_DEVICE_TIME_MILLIS,
+                resetDeviceTime).apply();
+    }
+
+    /** Get the number of days before device should factory reset */
+    @WorkerThread
+    public static int getDaysLeftUntilReset(Context context) {
+        ThreadAsserts.assertWorkerThread("getDaysLeftUntilReset");
+        return getSharedPreferences(context).getInt(KEY_DAYS_LEFT_UNTIL_RESET, Integer.MAX_VALUE);
+    }
+
+    /** Set the number of days before device should factory reset */
+    public static void setDaysLeftUntilReset(Context context, int days) {
+        getSharedPreferences(context).edit().putInt(KEY_DAYS_LEFT_UNTIL_RESET, days).apply();
+    }
+
+    public static long getProvisioningStartTimeMillis(Context context) {
+        return getSharedPreferences(context).getLong(KEY_PROVISIONING_START_TIME_MILLIS,
+                /* defValue = */-1L);
+    }
+
+    public static void setProvisioningStartTimeMillis(Context context,
+            @CurrentTimeMillisLong long provisioningStartTime) {
+        getSharedPreferences(context).edit().putLong(KEY_PROVISIONING_START_TIME_MILLIS,
+                provisioningStartTime).apply();
+    }
+
+    /** Get the suffix used for the notification channel */
+    @WorkerThread
+    public static String getNotificationChannelIdSuffix(Context context) {
+        ThreadAsserts.assertWorkerThread("getNotificationChannelIdSuffix");
+        return getSharedPreferences(context).getString(KEY_NOTIFICATION_CHANNEL_ID_SUFFIX,
+                /* defValue= */ "");
+    }
+
+    /** Set the suffix used for the notification channel */
+    @WorkerThread
+    public static void setNotificationChannelIdSuffix(Context context,
+            @Nullable String notificationChannelSuffix) {
+        ThreadAsserts.assertWorkerThread("setNotificationChannelIdSuffix");
+        getSharedPreferences(context).edit()
+                .putString(KEY_NOTIFICATION_CHANNEL_ID_SUFFIX, notificationChannelSuffix).apply();
+    }
+
     /**
      * Clear all user parameters.
      */
+    @WorkerThread
     public static void clear(Context context) {
+        ThreadAsserts.assertWorkerThread("clear");
         if (!Build.isDebuggable()) {
             throw new SecurityException("Clear is not allowed in non-debuggable build!");
         }
+        // We want to keep the boot time in order to reschedule works/alarms when system clock
+        // changes.
+        long bootTime = UserParameters.getBootTimeMillis(context);
         getSharedPreferences(context).edit().clear().commit();
+        UserParameters.setBootTimeMillis(context, bootTime);
+    }
+
+    /**
+     * Dump the current value of user parameters for the user associated with the input context.
+     */
+    public static void dump(Context context) {
+        Executors.newSingleThreadScheduledExecutor().submit(() -> {
+            LogUtil.d(TAG, String.format(Locale.US,
+                    "Dumping UserParameters for user: %s ...\n"
+                            + "%s: %s\n"    // user_state:
+                            + "%s: %s\n"    // home_override_package:
+                            + "%s: %s\n"    // boot-time-mills:
+                            + "%s: %s\n"    // next-check-in-time-millis:
+                            + "%s: %s\n"    // resume-provision-time-millis:
+                            + "%s: %s\n"    // next-provision-failed-step-time-millis:
+                            + "%s: %s\n"    // reset-device-time-millis:
+                            + "%s: %s\n"    // days-left-until-reset:
+                            + "%s: %s\n",   // notification-channel-suffix:
+                    context.getUser(),
+                    KEY_PROVISION_STATE, getProvisionState(context),
+                    KEY_HOME_PACKAGE_OVERRIDE, getPackageOverridingHome(context),
+                    KEY_BOOT_TIME_MILLS, getBootTimeMillis(context),
+                    KEY_NEXT_CHECK_IN_TIME_MILLIS, getNextCheckInTimeMillis(context),
+                    KEY_RESUME_PROVISION_TIME_MILLIS, getResumeProvisionTimeMillis(context),
+                    KEY_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS,
+                    getNextProvisionFailedStepTimeMills(context),
+                    KEY_RESET_DEVICE_TIME_MILLIS, getResetDeviceTimeMillis(context),
+                    KEY_DAYS_LEFT_UNTIL_RESET, getDaysLeftUntilReset(context),
+                    KEY_NOTIFICATION_CHANNEL_ID_SUFFIX, getNotificationChannelIdSuffix(context)
+            ));
+        });
     }
 }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/util/ThreadAsserts.java b/DeviceLockController/src/com/android/devicelockcontroller/util/ThreadAsserts.java
new file mode 100644
index 0000000..f0dfdce
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/util/ThreadAsserts.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.util;
+
+import android.os.Looper;
+
+/** A utility class that asserts worker/main threads */
+public final class ThreadAsserts {
+
+    private ThreadAsserts() {}
+
+    /**
+     * Assert that calling thread is not the main thread. If the calling thread is main thread, an
+     * {@link IllegalStateException} will be thrown.
+     *
+     * @param methodName The name of the method which will show up in the log if an exception is
+     *                   thrown.
+     */
+    public static void assertWorkerThread(String methodName) {
+        if (Looper.getMainLooper().isCurrentThread()) {
+            throw new IllegalStateException("Can not invoke " + methodName + " on the main thread");
+        }
+    }
+
+    /**
+     * Assert that calling thread is the main thread. If the calling thread is not the main thread,
+     * an {@link IllegalStateException} will be thrown.
+     *
+     * @param methodName The name of the method which will show up in the log if an exception is
+     *                   thrown.
+     */
+    public static void assertMainThread(String methodName) {
+        if (!Looper.getMainLooper().isCurrentThread()) {
+            throw new IllegalStateException(
+                    "Can not invoke " + methodName + " on a background thread");
+        }
+    }
+}
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/util/ThreadUtils.java b/DeviceLockController/src/com/android/devicelockcontroller/util/ThreadUtils.java
new file mode 100644
index 0000000..9aa7d1f
--- /dev/null
+++ b/DeviceLockController/src/com/android/devicelockcontroller/util/ThreadUtils.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.util;
+
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/** An utility class related to multi-threading */
+public final class ThreadUtils {
+    private static volatile Executor sSequentialSchedulerExecutor;
+
+    // Prevent instantiation
+    private ThreadUtils() {
+    }
+
+    /**
+     * Get the sequential executor for DeviceLockControllerScheduler.
+     */
+    public static synchronized Executor getSequentialSchedulerExecutor() {
+        if (sSequentialSchedulerExecutor == null) {
+            sSequentialSchedulerExecutor = MoreExecutors.newSequentialExecutor(
+                    Executors.newSingleThreadExecutor());
+        }
+        return sSequentialSchedulerExecutor;
+    }
+}
diff --git a/DeviceLockController/tests/android_test/Android.bp b/DeviceLockController/tests/android_test/Android.bp
new file mode 100644
index 0000000..45c0ebc
--- /dev/null
+++ b/DeviceLockController/tests/android_test/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2023 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+    name: "DeviceLockControllerAndroidTests",
+    manifest: "AndroidManifest.xml",
+    test_config: "AndroidTest.xml",
+    defaults: [
+        // For ExtendedMockito dependencies.
+        "modules-utils-testable-device-config-defaults",
+    ],
+    static_libs: [
+        "devicelockcontroller-stats",
+        "statsdprotolite",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+        "framework-statsd",
+    ],
+}
diff --git a/DeviceLockController/tests/android_test/AndroidManifest.xml b/DeviceLockController/tests/android_test/AndroidManifest.xml
new file mode 100644
index 0000000..b89f967
--- /dev/null
+++ b/DeviceLockController/tests/android_test/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.devicelockcontroller.tests">
+
+    <uses-sdk android:minSdkVersion="34" android:targetSdkVersion="34" />
+
+    <application
+        android:label="DeviceLockControllerAndroidTests"
+        android:debuggable="true">
+        <uses-library android:name="android.test.runner"/>
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.devicelockcontroller.tests"
+                     android:label="DeviceLockControllerAndroidTests"/>
+</manifest>
\ No newline at end of file
diff --git a/tests/unittests/AndroidTest.xml b/DeviceLockController/tests/android_test/AndroidTest.xml
similarity index 60%
rename from tests/unittests/AndroidTest.xml
rename to DeviceLockController/tests/android_test/AndroidTest.xml
index 393abcd..076cc70 100644
--- a/tests/unittests/AndroidTest.xml
+++ b/DeviceLockController/tests/android_test/AndroidTest.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2022 The Android Open Source Project
+  ~ Copyright (C) 2023 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.
@@ -14,21 +14,18 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<configuration description="Config for Device Lock unit test cases">
-    <option name="test-tag" value="DeviceLockUnitTests" />
-
+<configuration description="Runs unit tests for DeviceLockController APEX.">
+    <option name="test-tag" value="DeviceLockControllerAndroidTests"/>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true"/>
-        <option name="test-file-name" value="DeviceLockUnitTests.apk"/>
+        <option name="test-file-name" value="DeviceLockControllerAndroidTests.apk"/>
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
-        <option name="hidden-api-checks" value="false" />
-        <option name="package" value="com.android.server.devicelock.tests"/>
+        <option name="package" value="com.android.devicelockcontroller.tests"/>
+        <option name="hidden-api-checks" value="false"/>
     </test>
 
     <object type="module_controller"
-            class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
-        <option name="mainline-module-package-name" value="com.google.android.devicelock"/>
-    </object>
-</configuration>
+            class="com.android.tradefed.testtype.suite.module.Sdk34ModuleController"/>
+</configuration>
\ No newline at end of file
diff --git a/DeviceLockController/tests/android_test/src/com/android/devicelockcontroller/stats/StatsLoggerImplTest.java b/DeviceLockController/tests/android_test/src/com/android/devicelockcontroller/stats/StatsLoggerImplTest.java
new file mode 100644
index 0000000..8d81df8
--- /dev/null
+++ b/DeviceLockController/tests/android_test/src/com/android/devicelockcontroller/stats/StatsLoggerImplTest.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.stats;
+
+import static com.android.devicelockcontroller.DevicelockStatsLog.CHECK_IN_RETRY_REPORTED__REASON__COUNFIGURATION_UNAVAILABLE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.CHECK_IN_RETRY_REPORTED__REASON__NETWORK_TIME_UNAVAILABLE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.CHECK_IN_RETRY_REPORTED__REASON__RESPONSE_UNSPECIFIED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.CHECK_IN_RETRY_REPORTED__REASON__RPC_FAILURE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__GET_DEVICE_CHECK_IN_STATUS;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__IS_DEVICE_IN_APPROVED_COUNTRY;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__PAUSE_DEVICE_PROVISIONING;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__REPORT_DEVICE_PROVISION_STATE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_RETRY_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_KIOSK_APP_REQUEST_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_LOCK_UNLOCK_DEVICE_FAILURE_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_PROVISIONING_COMPLETE_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.DEVICE_LOCK_PROVISION_FAILURE_REPORTED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__LOCKED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__UNLOCKED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__COUNTRY_INFO_UNAVAILABLE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__NOT_IN_ELIGIBLE_COUNTRY;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__PLAY_INSTALLATION_FAILED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__PLAY_TASK_UNAVAILABLE;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__POLICY_ENFORCEMENT_FAILED;
+import static com.android.devicelockcontroller.DevicelockStatsLog.PROVISION_FAILURE_REPORTED__REASON__UNKNOWN;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.COUNTRY_INFO_UNAVAILABLE;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.NOT_IN_ELIGIBLE_COUNTRY;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.PLAY_INSTALLATION_FAILED;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.PLAY_TASK_UNAVAILABLE;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.POLICY_ENFORCEMENT_FAILED;
+import static com.android.devicelockcontroller.stats.StatsLogger.ProvisionFailureReasonStats.UNKNOWN;
+import static com.android.devicelockcontroller.stats.StatsLoggerImpl.TEX_ID_DEVICE_RESET_PROVISION_DEFERRED;
+import static com.android.devicelockcontroller.stats.StatsLoggerImpl.TEX_ID_DEVICE_RESET_PROVISION_MANDATORY;
+import static com.android.devicelockcontroller.stats.StatsLoggerImpl.TEX_ID_SUCCESSFUL_CHECK_IN_RESPONSE_COUNT;
+import static com.android.devicelockcontroller.stats.StatsLoggerImpl.TEX_ID_SUCCESSFUL_LOCKING_COUNT;
+import static com.android.devicelockcontroller.stats.StatsLoggerImpl.TEX_ID_SUCCESSFUL_PROVISIONING_COUNT;
+import static com.android.devicelockcontroller.stats.StatsLoggerImpl.TEX_ID_SUCCESSFUL_UNLOCKING_COUNT;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import com.android.modules.expresslog.Counter;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.android.devicelockcontroller.DevicelockStatsLog;
+
+import java.util.concurrent.TimeUnit;
+
+public final class StatsLoggerImplTest {
+    private static final int UID = 123;
+    private static final long PROVISIONING_TIME_MILLIS = 2000;
+    private final StatsLogger mStatsLogger = new StatsLoggerImpl();
+
+    @Rule
+    public final ExtendedMockitoRule mExtendedMockitoRule =
+            new ExtendedMockitoRule.Builder(this)
+                    .mockStatic(DevicelockStatsLog.class)
+                    .mockStatic(Counter.class)
+                    .build();
+
+    @Test
+    public void logGetDeviceCheckInStatus_shouldWriteCorrectLog() {
+        mStatsLogger.logGetDeviceCheckInStatus();
+        verify(() -> DevicelockStatsLog.write(
+                DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED,
+                DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__GET_DEVICE_CHECK_IN_STATUS));
+    }
+
+    @Test
+    public void logPauseDeviceProvisioning_shouldWriteCorrectLog() {
+        mStatsLogger.logPauseDeviceProvisioning();
+        verify(() -> DevicelockStatsLog.write(
+                DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED,
+                DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__PAUSE_DEVICE_PROVISIONING));
+    }
+
+    @Test
+    public void logReportDeviceProvisionState_shouldWriteCorrectLog() {
+        mStatsLogger.logReportDeviceProvisionState();
+        verify(() -> DevicelockStatsLog.write(
+                DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED,
+                DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__REPORT_DEVICE_PROVISION_STATE));
+    }
+
+    @Test
+    public void logKioskAppRequest_shouldWriteCorrectLog() {
+        mStatsLogger.logKioskAppRequest(UID);
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_KIOSK_APP_REQUEST_REPORTED, UID));
+    }
+
+    @Test
+    public void logProvisioningComplete_afterStartTimerForProvisioning_shouldWriteCorrectLog() {
+        mStatsLogger.logProvisioningComplete(PROVISIONING_TIME_MILLIS);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_PROVISIONING_COMPLETE_REPORTED,
+                TimeUnit.MILLISECONDS.toSeconds(PROVISIONING_TIME_MILLIS)));
+    }
+
+    @Test
+    public void logIsDeviceInApprovedCountry_shouldWriteCorrectLog() {
+        mStatsLogger.logIsDeviceInApprovedCountry();
+        verify(() -> DevicelockStatsLog.write(
+                DevicelockStatsLog.DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED,
+                DEVICE_LOCK_CHECK_IN_REQUEST_REPORTED__TYPE__IS_DEVICE_IN_APPROVED_COUNTRY));
+    }
+
+    @Test
+    public void logDeviceReset_provisionMandatory_shouldLogToTelemetryExpress() {
+        mStatsLogger.logDeviceReset(/* isProvisionMandatory */true);
+
+        verify(() -> Counter.logIncrement(TEX_ID_DEVICE_RESET_PROVISION_MANDATORY));
+    }
+
+    @Test
+    public void logDeviceReset_deferredProvision_shouldLogToTelemetryExpress() {
+        mStatsLogger.logDeviceReset(/* isProvisionMandatory */false);
+
+        verify(() -> Counter.logIncrement(TEX_ID_DEVICE_RESET_PROVISION_DEFERRED));
+    }
+
+    @Test
+    public void logSuccessfulCheckIn_shouldLogToTelemetryExpress() {
+        mStatsLogger.logSuccessfulCheckIn();
+
+        verify(() -> Counter.logIncrement(TEX_ID_SUCCESSFUL_CHECK_IN_RESPONSE_COUNT));
+    }
+
+    @Test
+    public void logSuccessfulProvisioning_shouldLogToTelemetryExpress() {
+        mStatsLogger.logSuccessfulProvisioning();
+
+        verify(() -> Counter.logIncrement(TEX_ID_SUCCESSFUL_PROVISIONING_COUNT));
+    }
+
+    @Test
+    public void logCheckInRetry_shouldWriteCorrectLogWhenReasonUnspecified() {
+        mStatsLogger.logCheckInRetry(StatsLogger.CheckInRetryReason.RESPONSE_UNSPECIFIED);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_CHECK_IN_RETRY_REPORTED,
+                CHECK_IN_RETRY_REPORTED__REASON__RESPONSE_UNSPECIFIED));
+    }
+
+    @Test
+    public void logCheckInRetry_shouldWriteCorrectLogWhenReasonConfigUnavailable() {
+        mStatsLogger.logCheckInRetry(StatsLogger.CheckInRetryReason.CONFIG_UNAVAILABLE);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_CHECK_IN_RETRY_REPORTED,
+                CHECK_IN_RETRY_REPORTED__REASON__COUNFIGURATION_UNAVAILABLE));
+    }
+
+    @Test
+    public void logCheckInRetry_shouldWriteCorrectLogWhenReasonNetworkTimeUnavailable() {
+        mStatsLogger.logCheckInRetry(StatsLogger.CheckInRetryReason.NETWORK_TIME_UNAVAILABLE);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_CHECK_IN_RETRY_REPORTED,
+                CHECK_IN_RETRY_REPORTED__REASON__NETWORK_TIME_UNAVAILABLE));
+    }
+
+    @Test
+    public void logCheckInRetry_shouldWriteCorrectLogWhenReasonRpcFailure() {
+        mStatsLogger.logCheckInRetry(StatsLogger.CheckInRetryReason.RPC_FAILURE);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_CHECK_IN_RETRY_REPORTED,
+                CHECK_IN_RETRY_REPORTED__REASON__RPC_FAILURE));
+    }
+
+    @Test
+    public void logProvisionFailure_shouldWriteCorrectLog_whenReasonPolicyEnforcementFailed() {
+        mStatsLogger.logProvisionFailure(POLICY_ENFORCEMENT_FAILED);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_PROVISION_FAILURE_REPORTED,
+                PROVISION_FAILURE_REPORTED__REASON__POLICY_ENFORCEMENT_FAILED));
+    }
+
+    @Test
+    public void logProvisionFailure_shouldWriteCorrectLog_whenReasonPlayTaskUnavailable() {
+        mStatsLogger.logProvisionFailure(PLAY_TASK_UNAVAILABLE);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_PROVISION_FAILURE_REPORTED,
+                PROVISION_FAILURE_REPORTED__REASON__PLAY_TASK_UNAVAILABLE));
+    }
+
+    @Test
+    public void logProvisionFailure_shouldWriteCorrectLog_whenReasonNotInEligibleCountry() {
+        mStatsLogger.logProvisionFailure(NOT_IN_ELIGIBLE_COUNTRY);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_PROVISION_FAILURE_REPORTED,
+                PROVISION_FAILURE_REPORTED__REASON__NOT_IN_ELIGIBLE_COUNTRY));
+    }
+
+    @Test
+    public void logProvisionFailure_shouldWriteCorrectLog_whenReasonCountryInfoNotAvailable() {
+        mStatsLogger.logProvisionFailure(COUNTRY_INFO_UNAVAILABLE);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_PROVISION_FAILURE_REPORTED,
+                PROVISION_FAILURE_REPORTED__REASON__COUNTRY_INFO_UNAVAILABLE));
+    }
+
+    @Test
+    public void logProvisionFailure_shouldWriteCorrectLog_whenReasonPlayInstallationFailed() {
+        mStatsLogger.logProvisionFailure(PLAY_INSTALLATION_FAILED);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_PROVISION_FAILURE_REPORTED,
+                PROVISION_FAILURE_REPORTED__REASON__PLAY_INSTALLATION_FAILED));
+    }
+
+    @Test
+    public void logProvisionFailure_shouldWriteCorrectLog_whenReasonUnknown() {
+        mStatsLogger.logProvisionFailure(UNKNOWN);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_PROVISION_FAILURE_REPORTED,
+                PROVISION_FAILURE_REPORTED__REASON__UNKNOWN));
+    }
+
+    @Test
+    public void logLockDeviceFailure_shouldWriteCorrectLog() {
+        mStatsLogger.logLockDeviceFailure(StatsLogger.DeviceStateStats.LOCKED);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_LOCK_UNLOCK_DEVICE_FAILURE_REPORTED,
+                /* arg1= (isLock)*/true,
+                LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__LOCKED));
+    }
+
+    @Test
+    public void logUnlockDeviceFailure_shouldWriteCorrectLog() {
+        mStatsLogger.logUnlockDeviceFailure(StatsLogger.DeviceStateStats.UNLOCKED);
+
+        verify(() -> DevicelockStatsLog.write(DEVICE_LOCK_LOCK_UNLOCK_DEVICE_FAILURE_REPORTED,
+                /* arg1= (isLock)*/false,
+                LOCK_UNLOCK_DEVICE_FAILURE_REPORTED__STATE_POST_COMMAND__UNLOCKED));
+    }
+
+    @Test
+    public void logSuccessfulLockingDevice_shouldWriteCorrectLog() {
+        mStatsLogger.logSuccessfulLockingDevice();
+
+        verify(() -> Counter.logIncrement(TEX_ID_SUCCESSFUL_LOCKING_COUNT));
+    }
+
+    @Test
+    public void logSuccessfulUnlockingDevice_shouldWriteCorrectLog() {
+        mStatsLogger.logSuccessfulUnlockingDevice();
+
+        verify(() -> Counter.logIncrement(TEX_ID_SUCCESSFUL_UNLOCKING_COUNT));
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/Android.bp b/DeviceLockController/tests/robolectric/Android.bp
index fee02de..d37be0a 100644
--- a/DeviceLockController/tests/robolectric/Android.bp
+++ b/DeviceLockController/tests/robolectric/Android.bp
@@ -26,10 +26,13 @@
     srcs: ["src/**/*.java"],
     static_libs: [
         "androidx.test.core",
-        "androidx.work_work-testing",
+        "androidx.test.rules",
         "mockito-robolectric-prebuilt",
-        "truth-prebuilt",
+        "truth",
         "guava-android-testlib",
     ],
+    libs: [
+        "androidx.work_work-testing",
+    ],
     test_suites: ["general-tests"],
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/DeviceLockControllerServiceTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/DeviceLockControllerServiceTest.java
new file mode 100644
index 0000000..409367f
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/DeviceLockControllerServiceTest.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.rule.ServiceTestRule;
+
+import com.android.devicelockcontroller.policy.DeviceStateController;
+import com.android.devicelockcontroller.policy.FinalizationController;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowPackageManager;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.util.concurrent.Futures;
+
+@RunWith(RobolectricTestRunner.class)
+public final class DeviceLockControllerServiceTest {
+
+    @Rule
+    public final ServiceTestRule mServiceRule = new ServiceTestRule();
+
+    private static final int KIOSK_APP_UID = 123;
+
+    private static final String KIOSK_APP_PACKAGE_NAME = "TEST_PACKAGE";
+
+    private StatsLogger mStatsLogger;
+    private TestDeviceLockControllerApplication mTestApp;
+
+    @Before
+    public void setUp() throws TimeoutException, ExecutionException, InterruptedException {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        StatsLoggerProvider loggerProvider =
+                (StatsLoggerProvider) mTestApp.getApplicationContext();
+        mStatsLogger = loggerProvider.getStatsLogger();
+
+        // Put Kiosk app package name and UID into SetupParameters and shadow PackageManager
+        setupSetupParameters();
+        ShadowPackageManager packageManager = Shadows.shadowOf(mTestApp.getPackageManager());
+        packageManager.setPackagesForUid(KIOSK_APP_UID, KIOSK_APP_PACKAGE_NAME);
+        final ShadowApplication shadowApplication = Shadows.shadowOf(mTestApp);
+
+        // Setup the service for DeviceLockControllerService using Robolectric
+        DeviceLockControllerService dlcService = Robolectric.setupService(
+                DeviceLockControllerService.class);
+        shadowApplication.setComponentNameAndServiceForBindService(
+                new ComponentName(mTestApp, DeviceLockControllerService.class),
+                dlcService.onBind(/* intent =*/null));
+        shadowApplication.setBindServiceCallsOnServiceConnectedDirectly(/* callDirectly =*/true);
+    }
+
+    @Test
+    public void lockDevice_shouldLogKioskRequest_andLogLockSuccess() throws RemoteException,
+            TimeoutException {
+        Intent serviceIntent = new Intent(mTestApp, DeviceLockControllerService.class);
+        IBinder binder = mServiceRule.bindService(serviceIntent);
+        when(mTestApp.getDeviceStateController().lockDevice()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        assertThat(binder).isNotNull();
+
+        IDeviceLockControllerService.Stub serviceStub = (IDeviceLockControllerService.Stub) binder;
+        serviceStub.lockDevice(new RemoteCallback((result -> {})));
+
+        verify(mStatsLogger).logKioskAppRequest(eq(KIOSK_APP_UID));
+        verify(mStatsLogger).logSuccessfulLockingDevice();
+    }
+
+    @Test
+    public void lockDevice_failure_shouldLogToStatsLogger() throws TimeoutException,
+            RemoteException {
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        Intent serviceIntent = new Intent(mTestApp, DeviceLockControllerService.class);
+        IBinder binder = mServiceRule.bindService(serviceIntent);
+        when(deviceStateController.lockDevice()).thenReturn(
+                Futures.immediateFailedFuture(new RuntimeException("Test Exception")));
+        when(deviceStateController.getDeviceState()).thenReturn(Futures.immediateFuture(
+                DeviceStateController.DeviceState.UNLOCKED));
+
+        assertThat(binder).isNotNull();
+
+        IDeviceLockControllerService.Stub serviceStub = (IDeviceLockControllerService.Stub) binder;
+        serviceStub.lockDevice(new RemoteCallback((result -> {})));
+
+        verify(mStatsLogger).logLockDeviceFailure(DeviceStateController.DeviceState.UNLOCKED);
+    }
+
+    @Test
+    public void unlockDevice_shouldLogKioskRequest_AndLogUnlockSuccess() throws RemoteException,
+            TimeoutException {
+        Intent serviceIntent = new Intent(mTestApp, DeviceLockControllerService.class);
+        IBinder binder = mServiceRule.bindService(serviceIntent);
+        when(mTestApp.getDeviceStateController().unlockDevice()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        assertThat(binder).isNotNull();
+
+        IDeviceLockControllerService.Stub serviceStub = (IDeviceLockControllerService.Stub) binder;
+        serviceStub.unlockDevice(new RemoteCallback((result -> {})));
+
+        verify(mStatsLogger).logKioskAppRequest(eq(KIOSK_APP_UID));
+        verify(mStatsLogger).logSuccessfulUnlockingDevice();
+    }
+
+    @Test
+    public void unlockDevice_failure_shouldLogToStatsLogger() throws TimeoutException,
+            RemoteException {
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        Intent serviceIntent = new Intent(mTestApp, DeviceLockControllerService.class);
+        IBinder binder = mServiceRule.bindService(serviceIntent);
+        when(deviceStateController.unlockDevice()).thenReturn(
+                Futures.immediateFailedFuture(new RuntimeException("Test Exception")));
+        when(deviceStateController.getDeviceState()).thenReturn(Futures.immediateFuture(
+                DeviceStateController.DeviceState.LOCKED));
+
+        assertThat(binder).isNotNull();
+
+        IDeviceLockControllerService.Stub serviceStub = (IDeviceLockControllerService.Stub) binder;
+        serviceStub.unlockDevice(new RemoteCallback((result -> {})));
+
+        verify(mStatsLogger).logUnlockDeviceFailure(DeviceStateController.DeviceState.LOCKED);
+    }
+
+    @Test
+    public void isDeviceLocked_shouldLogKioskRequest() throws RemoteException, TimeoutException {
+        Intent serviceIntent = new Intent(mTestApp, DeviceLockControllerService.class);
+        IBinder binder = mServiceRule.bindService(serviceIntent);
+        when(mTestApp.getDeviceStateController().isLocked()).thenReturn(
+                Futures.immediateFuture(true));
+
+        assertThat(binder).isNotNull();
+
+        IDeviceLockControllerService.Stub serviceStub = (IDeviceLockControllerService.Stub) binder;
+        serviceStub.isDeviceLocked(new RemoteCallback((result -> {})));
+
+        verify(mStatsLogger).logKioskAppRequest(eq(KIOSK_APP_UID));
+    }
+
+    @Test
+    public void getDeviceIdentifier_shouldLogKioskRequest()
+            throws RemoteException, TimeoutException {
+        Intent serviceIntent = new Intent(mTestApp, DeviceLockControllerService.class);
+        IBinder binder = mServiceRule.bindService(serviceIntent);
+
+        assertThat(binder).isNotNull();
+
+        IDeviceLockControllerService.Stub serviceStub = (IDeviceLockControllerService.Stub) binder;
+        serviceStub.getDeviceIdentifier(new RemoteCallback((result -> {})));
+
+        verify(mStatsLogger).logKioskAppRequest(eq(KIOSK_APP_UID));
+    }
+
+    @Test
+    public void clearDeviceRestrictions_shouldLogKioskRequest()
+            throws RemoteException, TimeoutException {
+        Intent serviceIntent = new Intent(mTestApp, DeviceLockControllerService.class);
+        IBinder binder = mServiceRule.bindService(serviceIntent);
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        when(deviceStateController.clearDevice()).thenReturn(Futures.immediateVoidFuture());
+        FinalizationController finalizationController = mTestApp.getFinalizationController();
+        when(finalizationController.notifyRestrictionsCleared()).
+                thenReturn(Futures.immediateVoidFuture());
+
+        assertThat(binder).isNotNull();
+
+        IDeviceLockControllerService.Stub serviceStub = (IDeviceLockControllerService.Stub) binder;
+        serviceStub.clearDeviceRestrictions(new RemoteCallback((result -> {})));
+
+        verify(mStatsLogger).logKioskAppRequest(eq(KIOSK_APP_UID));
+    }
+
+    private static void setupSetupParameters() throws InterruptedException, ExecutionException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, KIOSK_APP_PACKAGE_NAME);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/TestDeviceLockControllerApplication.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/TestDeviceLockControllerApplication.java
index cc50585..8fa5395 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/TestDeviceLockControllerApplication.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/TestDeviceLockControllerApplication.java
@@ -17,18 +17,32 @@
 package com.android.devicelockcontroller;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.app.Application;
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.work.ListenableWorker;
+import androidx.work.WorkerParameters;
 
 import com.android.devicelockcontroller.policy.DevicePolicyController;
 import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.policy.PolicyObjectsInterface;
-import com.android.devicelockcontroller.policy.SetupController;
+import com.android.devicelockcontroller.policy.FinalizationController;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
 import com.android.devicelockcontroller.storage.GlobalParametersClient;
 import com.android.devicelockcontroller.storage.GlobalParametersService;
 import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.storage.SetupParametersService;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.testing.TestingExecutors;
 
 import org.robolectric.Robolectric;
@@ -40,16 +54,24 @@
  * Application class that provides mock objects for tests.
  */
 public final class TestDeviceLockControllerApplication extends Application implements
-        PolicyObjectsInterface, TestLifecycleApplication {
+        PolicyObjectsProvider,
+        TestLifecycleApplication,
+        DeviceLockControllerSchedulerProvider,
+        FcmRegistrationTokenProvider,
+        PlayInstallPackageTaskClassProvider,
+        StatsLoggerProvider {
 
     private DevicePolicyController mPolicyController;
     private DeviceStateController mStateController;
-    private SetupController mSetupController;
+    private ProvisionStateController mProvisionStateController;
+    private FinalizationController mFinalizationController;
+    private DeviceLockControllerScheduler mDeviceLockControllerScheduler;
     private SetupParametersClient mSetupParametersClient;
     private GlobalParametersClient mGlobalParametersClient;
+    private StatsLogger mStatsLogger;
 
     @Override
-    public DeviceStateController getStateController() {
+    public DeviceStateController getDeviceStateController() {
         if (mStateController == null) {
             mStateController = mock(DeviceStateController.class);
         }
@@ -57,6 +79,18 @@
     }
 
     @Override
+    public ProvisionStateController getProvisionStateController() {
+        if (mProvisionStateController == null) {
+            mProvisionStateController = mock(ProvisionStateController.class);
+            when(mProvisionStateController.getDevicePolicyController()).thenReturn(
+                    getPolicyController());
+            when(mProvisionStateController.getDeviceStateController()).thenReturn(
+                    getDeviceStateController());
+        }
+        return mProvisionStateController;
+    }
+
+    @Override
     public DevicePolicyController getPolicyController() {
         if (mPolicyController == null) {
             mPolicyController = mock(DevicePolicyController.class);
@@ -65,18 +99,31 @@
     }
 
     @Override
-    public SetupController getSetupController() {
-        if (mSetupController == null) {
-            mSetupController = mock(SetupController.class);
+    public FinalizationController getFinalizationController() {
+        if (mFinalizationController == null) {
+            mFinalizationController = mock(FinalizationController.class);
         }
-        return mSetupController;
+        return mFinalizationController;
+    }
+
+    @Override
+    public synchronized StatsLogger getStatsLogger() {
+        if (null == mStatsLogger) {
+            mStatsLogger = mock(StatsLogger.class);
+        }
+        return mStatsLogger;
+    }
+
+    @Override
+    @NonNull
+    public ListenableFuture<String> getFcmRegistrationToken() {
+        return Futures.immediateFuture(null);
     }
 
     @Override
     public void destroyObjects() {
         mPolicyController = null;
         mStateController = null;
-        mSetupController = null;
     }
 
 
@@ -102,4 +149,35 @@
         GlobalParametersClient.reset();
         SetupParametersClient.reset();
     }
+
+    @Override
+    public DeviceLockControllerScheduler getDeviceLockControllerScheduler() {
+        if (mDeviceLockControllerScheduler == null) {
+            mDeviceLockControllerScheduler = mock(DeviceLockControllerScheduler.class);
+        }
+        return mDeviceLockControllerScheduler;
+    }
+
+    @Nullable
+    @Override
+    public Class<? extends ListenableWorker> getPlayInstallPackageTaskClass() {
+        return PlayInstallPackageWorker.class;
+    }
+
+    /**
+     * A stub class for play install worker.
+     */
+    public static final class PlayInstallPackageWorker extends ListenableWorker {
+
+        public PlayInstallPackageWorker(@NonNull Context appContext,
+                @NonNull WorkerParameters workerParameters) {
+            super(appContext, workerParameters);
+        }
+
+        @NonNull
+        @Override
+        public ListenableFuture<Result> startWork() {
+            return Futures.immediateFuture(Result.success());
+        }
+    }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/WorkManagerExceptionHandlerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/WorkManagerExceptionHandlerTest.java
new file mode 100644
index 0000000..46edea8
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/WorkManagerExceptionHandlerTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller;
+
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.KIOSK_PROVISIONED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_FAILED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_IN_PROGRESS;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_PAUSED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.policy.DevicePolicyController;
+import com.android.devicelockcontroller.policy.DeviceStateController;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+
+import com.google.common.util.concurrent.Futures;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.ExecutionException;
+
+@RunWith(RobolectricTestRunner.class)
+public final class WorkManagerExceptionHandlerTest {
+    private TestDeviceLockControllerApplication mTestApp;
+
+    @Rule
+    public final MockitoRule mocks = MockitoJUnit.rule();
+
+    @Mock
+    private Runnable mTerminationRunnableMock;
+
+    @Before
+    public void setUp() {
+        mTestApp = ApplicationProvider.getApplicationContext();
+    }
+
+    @Test
+    public void handleException_whenUnprovisioned_shouldTerminateNoWipe()
+            throws ExecutionException, InterruptedException {
+        WorkManagerExceptionHandler workManagerExceptionHandler =
+                new WorkManagerExceptionHandler(mTestApp, mTerminationRunnableMock);
+        ProvisionStateController provisionStateController = mTestApp.getProvisionStateController();
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
+
+        when(provisionStateController.getState())
+                .thenReturn(Futures.immediateFuture(UNPROVISIONED));
+        when(deviceStateController.isCleared()).thenReturn(Futures.immediateFuture(false));
+
+        workManagerExceptionHandler.handleException(mTestApp, new RuntimeException()).get();
+
+        verify(mTerminationRunnableMock).run();
+        verify(devicePolicyController, never()).wipeDevice();
+    }
+
+    @Test
+    public void handleException_whenProvisionInProgress_shouldWipeNoTerminate()
+            throws ExecutionException, InterruptedException {
+        WorkManagerExceptionHandler workManagerExceptionHandler =
+                new WorkManagerExceptionHandler(mTestApp, mTerminationRunnableMock);
+        ProvisionStateController provisionStateController = mTestApp.getProvisionStateController();
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
+
+        when(provisionStateController.getState())
+                .thenReturn(Futures.immediateFuture(PROVISION_IN_PROGRESS));
+        when(deviceStateController.isCleared()).thenReturn(Futures.immediateFuture(false));
+
+        workManagerExceptionHandler.handleException(mTestApp, new RuntimeException()).get();
+
+        verify(mTerminationRunnableMock, never()).run();
+        verify(devicePolicyController).wipeDevice();
+    }
+
+    @Test
+    public void handleException_whenProvisionPaused_shouldWipeNoTerminate()
+            throws ExecutionException, InterruptedException {
+        WorkManagerExceptionHandler workManagerExceptionHandler =
+                new WorkManagerExceptionHandler(mTestApp, mTerminationRunnableMock);
+        ProvisionStateController provisionStateController = mTestApp.getProvisionStateController();
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
+
+        when(provisionStateController.getState())
+                .thenReturn(Futures.immediateFuture(PROVISION_PAUSED));
+        when(deviceStateController.isCleared()).thenReturn(Futures.immediateFuture(false));
+
+        workManagerExceptionHandler.handleException(mTestApp, new RuntimeException()).get();
+
+        verify(mTerminationRunnableMock, never()).run();
+        verify(devicePolicyController).wipeDevice();
+    }
+
+    @Test
+    public void handleException_whenProvisionFailed_shouldWipeNoTerminate()
+            throws ExecutionException, InterruptedException {
+        WorkManagerExceptionHandler workManagerExceptionHandler =
+                new WorkManagerExceptionHandler(mTestApp, mTerminationRunnableMock);
+        ProvisionStateController provisionStateController = mTestApp.getProvisionStateController();
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
+
+        when(provisionStateController.getState())
+                .thenReturn(Futures.immediateFuture(PROVISION_FAILED));
+        when(deviceStateController.isCleared()).thenReturn(Futures.immediateFuture(false));
+
+        workManagerExceptionHandler.handleException(mTestApp, new RuntimeException()).get();
+
+        verify(mTerminationRunnableMock, never()).run();
+        verify(devicePolicyController).wipeDevice();
+    }
+
+    @Test
+    public void handleException_whenKioskProvisioned_shouldWipeNoTerminate()
+            throws ExecutionException, InterruptedException {
+        WorkManagerExceptionHandler workManagerExceptionHandler =
+                new WorkManagerExceptionHandler(mTestApp, mTerminationRunnableMock);
+        ProvisionStateController provisionStateController = mTestApp.getProvisionStateController();
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
+
+        when(provisionStateController.getState())
+                .thenReturn(Futures.immediateFuture(KIOSK_PROVISIONED));
+        when(deviceStateController.isCleared()).thenReturn(Futures.immediateFuture(false));
+
+        workManagerExceptionHandler.handleException(mTestApp, new RuntimeException()).get();
+
+        verify(mTerminationRunnableMock, never()).run();
+        verify(devicePolicyController).wipeDevice();
+    }
+
+    @Test
+    public void handleException_whenProvisionSucceededRestrictionsNotCleared_shouldWipeNoTerminate()
+            throws ExecutionException, InterruptedException {
+        WorkManagerExceptionHandler workManagerExceptionHandler =
+                new WorkManagerExceptionHandler(mTestApp, mTerminationRunnableMock);
+        ProvisionStateController provisionStateController = mTestApp.getProvisionStateController();
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
+
+        when(provisionStateController.getState())
+                .thenReturn(Futures.immediateFuture(PROVISION_SUCCEEDED));
+        when(deviceStateController.isCleared()).thenReturn(Futures.immediateFuture(false));
+
+        workManagerExceptionHandler.handleException(mTestApp, new RuntimeException()).get();
+
+        verify(mTerminationRunnableMock, never()).run();
+        verify(devicePolicyController).wipeDevice();
+    }
+
+    @Test
+    public void handleException_whenProvisionSucceededRestrictionsCleared_shouldntWipe()
+            throws ExecutionException, InterruptedException {
+        WorkManagerExceptionHandler workManagerExceptionHandler =
+                new WorkManagerExceptionHandler(mTestApp, mTerminationRunnableMock);
+        ProvisionStateController provisionStateController = mTestApp.getProvisionStateController();
+        DeviceStateController deviceStateController = mTestApp.getDeviceStateController();
+        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
+
+        when(provisionStateController.getState())
+                .thenReturn(Futures.immediateFuture(PROVISION_SUCCEEDED));
+        when(deviceStateController.isCleared()).thenReturn(Futures.immediateFuture(true));
+
+        workManagerExceptionHandler.handleException(mTestApp, new RuntimeException()).get();
+
+        verify(devicePolicyController, never()).wipeDevice();
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/DeviceLockSettingsActivityTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/DeviceLockSettingsActivityTest.java
new file mode 100644
index 0000000..fd8c2c1
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/DeviceLockSettingsActivityTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.devicelockcontroller.activities;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Intent;
+
+import androidx.fragment.app.FragmentManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class DeviceLockSettingsActivityTest {
+
+    @Test
+    public void onCreate_setDeviceInfoSettingsFragment() {
+        Intent intent = new Intent();
+        DeviceLockSettingsActivity activity = Robolectric.buildActivity(
+                DeviceLockSettingsActivity.class,
+                intent).setup().get();
+
+        FragmentManager fragmentManager = activity.getSupportFragmentManager();
+
+        assertThat(fragmentManager.getFragments().get(0)).isInstanceOf(
+                DeviceInfoSettingsFragment.class);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/EmptyTestFragmentActivity.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/EmptyTestFragmentActivity.java
new file mode 100644
index 0000000..a655e91
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/EmptyTestFragmentActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.devicelockcontroller.activities;
+
+import android.os.Bundle;
+import android.widget.FrameLayout;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.devicelockcontroller.R;
+
+public final class EmptyTestFragmentActivity extends FragmentActivity {
+    private Fragment mFragment;
+    private String mFragmentTag;
+
+    public void setFragment(Fragment fragment) {
+        mFragment = fragment;
+    }
+
+    public void setFragmentTag(String fragmentTag) {
+        mFragmentTag = fragmentTag;
+    }
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        FrameLayout layout = new FrameLayout(this);
+        layout.setId(R.id.container);
+        setContentView(layout);
+        if (mFragment != null) {
+            getSupportFragmentManager().beginTransaction()
+                    .add(R.id.container, mFragment, mFragmentTag)
+                    .commitNow();
+        }
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/HelpActivityTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/HelpActivityTest.java
index 518204c..970282f 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/HelpActivityTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/HelpActivityTest.java
@@ -26,7 +26,6 @@
 import androidx.test.core.app.ApplicationProvider;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
@@ -44,7 +43,6 @@
         mContext = ApplicationProvider.getApplicationContext();
     }
 
-    @Ignore("http://b/269463682")
     @Test
     public void helpActivity_loadUrlSuccess() {
         Intent intent = new Intent(mContext, HelpActivity.class);
@@ -53,14 +51,12 @@
         assertThat(shadowOf(activity.getWebView()).getLastLoadedUrl()).isEqualTo(TEST_URL);
     }
 
-    @Ignore("http://b/269463682")
     @Test
     public void helpActivity_finishWhenExtrasNotPresent() {
         HelpActivity activity = Robolectric.buildActivity(HelpActivity.class).setup().get();
         assertThat(activity.isFinishing()).isTrue();
     }
 
-    @Ignore("http://b/269463682")
     @Test
     public void helpActivity_finishWhenURLNotPresent() {
         Intent intent = new Intent(mContext, HelpActivity.class);
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/LandingActivityTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/LandingActivityTest.java
index d7c7d16..716c59e 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/LandingActivityTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/LandingActivityTest.java
@@ -16,14 +16,18 @@
 
 package com.android.devicelockcontroller.activities;
 
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_PROVISIONING;
+
 import static com.google.common.truth.Truth.assertThat;
 
+import android.content.Intent;
+import android.view.WindowInsets;
+
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentContainerView;
 
 import com.android.devicelockcontroller.R;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
@@ -32,14 +36,26 @@
 @RunWith(RobolectricTestRunner.class)
 public final class LandingActivityTest {
 
-    @Ignore("http://b/269463682")
     @Test
     public void landingActivity_setsProvisionInfoFragment() {
-        LandingActivity activity = Robolectric.buildActivity(LandingActivity.class).setup().get();
+        Intent intent = new Intent();
+        intent.setAction(ACTION_START_DEVICE_FINANCING_PROVISIONING);
+        LandingActivity activity = Robolectric.buildActivity(LandingActivity.class,
+                intent).setup().get();
         FragmentContainerView fragmentContainerView = activity.findViewById(
                 R.id.fragment_container);
 
         assertThat((Fragment) fragmentContainerView.getFragment()).isInstanceOf(
                 ProvisionInfoFragment.class);
     }
+
+    @Test
+    public void landingActivity_hideSystemBar() {
+        Intent intent = new Intent();
+        intent.setAction(ACTION_START_DEVICE_FINANCING_PROVISIONING);
+        LandingActivity activity = Robolectric.buildActivity(LandingActivity.class,
+                intent).setup().get();
+        assertThat(activity.getWindow().getDecorView().getRootWindowInsets().isVisible(
+                WindowInsets.Type.systemBars())).isFalse();
+    }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProgressFragmentTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProgressFragmentTest.java
new file mode 100644
index 0000000..4fa3695
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProgressFragmentTest.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.COUNTRY_INFO_UNAVAILABLE;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.DEADLINE_PASSED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.NOT_IN_ELIGIBLE_COUNTRY;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.PLAY_INSTALLATION_FAILED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.PLAY_TASK_UNAVAILABLE;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.POLICY_ENFORCEMENT_FAILED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.UNKNOWN_REASON;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_FAILURE;
+import static com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker.KEY_PROVISION_FAILURE_REASON;
+import static com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.text.Html;
+import android.text.SpannableString;
+import android.text.style.URLSpan;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Chronometer;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.work.Configuration;
+import androidx.work.Data;
+import androidx.work.ListenableWorker;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+import androidx.work.WorkerFactory;
+import androidx.work.WorkerParameters;
+import androidx.work.testing.WorkManagerTestInitHelper;
+
+import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.policy.ProvisionHelper;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker;
+
+import com.google.common.truth.Truth;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.ParameterizedRobolectricTestRunner;
+import org.robolectric.Robolectric;
+import org.robolectric.Shadows;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.shadows.ShadowActivity;
+import org.robolectric.shadows.ShadowDrawable;
+import org.robolectric.shadows.ShadowLooper;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+
+@RunWith(ParameterizedRobolectricTestRunner.class)
+public final class ProgressFragmentTest {
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    private static final String TEST_PROVIDER = "Test Provider";
+    private static final String PROGRESS_FRAGMENT_TAG = "ProgressFragment";
+    private static final String TEST_URL = "test.url";
+    @ParameterizedRobolectricTestRunner.Parameter
+    public ProvisioningProgress mProvisioningProgress;
+    @Mock
+    private ProvisionHelper mMockProvisionHelper;
+
+    /** Get the input parameters of the test. */
+    @ParameterizedRobolectricTestRunner.Parameters(name = "ProvisioningProgress is {0}")
+    public static List<Object[]> parameters() {
+        return Arrays.asList(new Object[][]{
+                {ProvisioningProgress.GETTING_DEVICE_READY},
+                {ProvisioningProgress.INSTALLING_KIOSK_APP},
+                {ProvisioningProgress.OPENING_KIOSK_APP},
+                {ProvisioningProgress.getMandatoryProvisioningFailedProgress(
+                        POLICY_ENFORCEMENT_FAILED)},
+                {ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                        PLAY_TASK_UNAVAILABLE)},
+                {ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                        PLAY_INSTALLATION_FAILED)},
+                {ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                        COUNTRY_INFO_UNAVAILABLE)},
+                {ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                        NOT_IN_ELIGIBLE_COUNTRY)},
+                {ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                        POLICY_ENFORCEMENT_FAILED)},
+                {ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                        DEADLINE_PASSED)}
+        });
+    }
+
+    @Test
+    public void onCreateView_viewsAndListenersShouldBeCorrectlySet()
+            throws ExecutionException, InterruptedException {
+        TestDeviceLockControllerApplication applicationContext =
+                ApplicationProvider.getApplicationContext();
+
+        WorkManagerTestInitHelper.initializeTestWorkManager(applicationContext,
+                new Configuration.Builder().setWorkerFactory(getWorkerFactory()).build());
+
+        ProvisionStateController provisionStateController =
+                applicationContext.getProvisionStateController();
+        when(provisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionStateController.ProvisionState.PROVISION_IN_PROGRESS));
+
+        ActivityController<EmptyTestFragmentActivity> activityController =
+                Robolectric.buildActivity(
+                        EmptyTestFragmentActivity.class);
+        EmptyTestFragmentActivity activity = activityController.get();
+        activity.setFragment(new ProgressFragment(mMockProvisionHelper));
+        activity.setFragmentTag(PROGRESS_FRAGMENT_TAG);
+
+        activityController.setup();
+
+        ProvisioningProgressViewModel provisioningProgressViewModel =
+                new ViewModelProvider(activity).get(ProvisioningProgressViewModel.class);
+        provisioningProgressViewModel.mProviderNameLiveData.setValue(TEST_PROVIDER);
+        provisioningProgressViewModel.mSupportUrlLiveData.setValue(TEST_URL);
+        provisioningProgressViewModel.setProvisioningProgress(mProvisioningProgress);
+
+        ShadowLooper.runUiThreadTasks();
+
+        // Check Header Icon
+        if (mProvisioningProgress.mIconId != 0) {
+            ShadowDrawable drawable = Shadows.shadowOf(((ImageView) activity.findViewById(
+                    R.id.header_icon)).getDrawable());
+            assertThat(drawable.getCreatedFromResId()).isEqualTo(
+                    mProvisioningProgress.mIconId);
+        }
+
+        // Check header text
+        if (mProvisioningProgress.mHeaderId != 0) {
+            CharSequence actual = ((TextView) activity.findViewById(R.id.header_text)).getText();
+            Truth.assertThat(actual).isEqualTo(activity.getString(mProvisioningProgress.mHeaderId,
+                    provisioningProgressViewModel.mProviderNameLiveData.getValue()));
+        }
+
+        // Check sub-header text
+        if (mProvisioningProgress.mSubheaderId != 0) {
+            TextView subHeaderView = activity.findViewById(
+                    R.id.subheader_text);
+            CharSequence actualSubHeaderText = subHeaderView.getText();
+            SpannableString actualUrlSubHeader = new SpannableString(
+                    Html.fromHtml(String.valueOf(actualSubHeaderText),
+                            Html.FROM_HTML_MODE_COMPACT));
+            URLSpan[] spans = actualUrlSubHeader.getSpans(/* queryStart= */ 0,
+                    actualUrlSubHeader.length(), URLSpan.class);
+
+            assertThat(spans.length).isLessThan(2);
+            if (spans.length == 1) {
+                spans[0].onClick(subHeaderView);
+                ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+                Intent next = shadowActivity.getNextStartedActivity();
+                assertThat(next.getClass()).isEqualTo(HelpActivity.class);
+                assertThat(next.getStringExtra(HelpActivity.EXTRA_URL_PARAM)).isEqualTo(TEST_URL);
+            }
+        }
+
+        // Check progress bar visibility
+        assertThat(activity.findViewById(R.id.progress_bar).getVisibility()).isEqualTo(
+                mProvisioningProgress.mProgressBarVisible ? View.VISIBLE : View.GONE);
+
+        // Check bottom views
+        View bottomView = activity.findViewById(R.id.bottom);
+        if (mProvisioningProgress.mBottomViewVisible) {
+            assertThat(bottomView.getVisibility()).isEqualTo(View.VISIBLE);
+
+            ((Button) activity.findViewById(R.id.button_retry)).callOnClick();
+            verify(mMockProvisionHelper).scheduleKioskAppInstallation(any(), any(), eq(false));
+
+            ((Button) activity.findViewById(R.id.button_exit)).performClick();
+            Shadows.shadowOf(Looper.getMainLooper()).idle();
+            verify(provisionStateController).postSetNextStateForEventRequest(eq(PROVISION_FAILURE));
+            WorkManager workManager = WorkManager.getInstance(applicationContext);
+            List<WorkInfo> workInfos = workManager.getWorkInfosForUniqueWork(
+                    REPORT_PROVISION_STATE_WORK_NAME).get();
+            assertThat(workInfos.size()).isEqualTo(1);
+        } else {
+            assertThat(bottomView.getVisibility()).isEqualTo(View.GONE);
+        }
+
+        // Check count down timer
+        Chronometer countDownTimer = activity.findViewById(R.id.countdown_text);
+        if (mProvisioningProgress.mCountDownTimerVisible) {
+            assertThat(countDownTimer.getVisibility()).isEqualTo(
+                    View.VISIBLE);
+            assertThat(countDownTimer.getBase()).isEqualTo(
+                    SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(
+                            MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE));
+        } else {
+            assertThat(countDownTimer.getVisibility()).isEqualTo(View.GONE);
+        }
+    }
+
+    @NonNull
+    private WorkerFactory getWorkerFactory() {
+        return new WorkerFactory() {
+            @Nullable
+            @Override
+            public ListenableWorker createWorker(@NonNull Context appContext,
+                    @NonNull String workerClassName,
+                    @NonNull WorkerParameters workerParameters) {
+                if (workerClassName.equals(
+                        ReportDeviceProvisionStateWorker.class.getName())) {
+                    return new ListenableWorker(appContext, workerParameters) {
+                        @NonNull
+                        @Override
+                        public ListenableFuture<Result> startWork() {
+                            Data input = getInputData();
+                            assertThat(input.getInt(KEY_PROVISION_FAILURE_REASON,
+                                    UNKNOWN_REASON)).isEqualTo(
+                                    mProvisioningProgress.mFailureReason);
+                            return Futures.immediateFuture(Result.success());
+                        }
+                    };
+                } else {
+                    return null;
+                }
+            }
+        };
+    }
+
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoFragmentTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoFragmentTest.java
index 14164e1..2c1cc70 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoFragmentTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoFragmentTest.java
@@ -16,29 +16,72 @@
 
 package com.android.devicelockcontroller.activities;
 
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_PROVISIONING;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.robolectric.Shadows.shadowOf;
 
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Looper;
+import android.widget.Button;
 import android.widget.ImageView;
 
 import com.android.devicelockcontroller.R;
 
-import org.junit.Ignore;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.shadows.ShadowDrawable;
 
 @RunWith(RobolectricTestRunner.class)
 public final class ProvisionInfoFragmentTest {
 
-    @Ignore("http://b/269463682")
+    private ActivityController<EmptyTestFragmentActivity> mActivityController;
+    private EmptyTestFragmentActivity mActivity;
+
+    @Before
+    public void setUp() {
+        Intent intent = new Intent();
+        intent.setAction(ACTION_START_DEVICE_FINANCING_PROVISIONING);
+        mActivityController = Robolectric.buildActivity(EmptyTestFragmentActivity.class, intent);
+        mActivity = mActivityController.get();
+        mActivity.setFragment(new ProvisionInfoFragment());
+        mActivityController.setup();
+    }
+
     @Test
-    public void onCreateView_viewIsInflated() {
-        LandingActivity activity = Robolectric.buildActivity(LandingActivity.class).setup().get();
-        ImageView imageView = activity.findViewById(R.id.header_icon);
-        assertThat(shadowOf(imageView.getDrawable()).getCreatedFromResId()).isEqualTo(
-                R.drawable.ic_info_24px);
+    public void onViewCreated_headerIconDrawableIsCorrect() {
+        shadowOf(Looper.getMainLooper()).idle();
+
+        // Check header icon
+        ShadowDrawable drawable = Shadows.shadowOf(((ImageView) mActivity.findViewById(
+                R.id.header_icon)).getDrawable());
+        assertThat(drawable.getCreatedFromResId()).isEqualTo(
+                ProvisionInfoViewModel.HEADER_DRAWABLE_ID);
+    }
+
+    @Test
+    public void clickNextButton_startTheProvisioningActivity() {
+        Intent intent = new Intent();
+        intent.setAction(ACTION_START_DEVICE_FINANCING_PROVISIONING);
+        ActivityController<EmptyTestFragmentActivity> activityController =
+                Robolectric.buildActivity(
+                        EmptyTestFragmentActivity.class, intent);
+        EmptyTestFragmentActivity activity = activityController.get();
+        activity.setFragment(new ProvisionInfoFragment());
+        activityController.setup();
+
+        // Check next button clickable
+        Button next = activity.findViewById(R.id.button_next);
+        assertThat(next.callOnClick()).isTrue();
+        Intent nextIntent = Shadows.shadowOf(activity).getNextStartedActivity();
+        assertThat(nextIntent.getComponent()).isEqualTo(
+                new ComponentName(activity, ProvisioningActivity.class));
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapterTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapterTest.java
new file mode 100644
index 0000000..b7d7272
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoListAdapterTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.TruthJUnit.assume;
+
+import android.app.Activity;
+import android.graphics.drawable.Drawable;
+import android.text.Html;
+import android.text.SpannableString;
+import android.text.SpannedString;
+import android.text.style.ClickableSpan;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.activities.ProvisionInfo.ProvisionInfoType;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public final class ProvisionInfoListAdapterTest {
+    private static final List<ProvisionInfo> TEST_PROVISION_INFOS = List.of(
+            DeviceFinancingProvisionInfoViewModel.PROVISION_INFOS);
+    private static final String TEST_PROVIDER = "Test Provider";
+    private static final String TEST_URL = "testUrl";
+    private ProvisionInfoListAdapter mAdapter;
+    private TestDeviceLockControllerApplication mTestApp;
+    private final Activity mTestActivity = Robolectric.buildActivity(Activity.class).setup().get();
+    private TextView mTextView;
+    private ProvisionInfoListAdapter.ProvisionInfoViewHolder mProvisionInfoViewHolder;
+
+    @Before
+    public void setUp() {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        mAdapter = new ProvisionInfoListAdapter();
+        mTextView = new TextView(mTestActivity);
+        mTextView.setId(R.id.text_view_item_provision_info);
+        mProvisionInfoViewHolder = new ProvisionInfoListAdapter.ProvisionInfoViewHolder(mTextView);
+        mAdapter.submitList(TEST_PROVISION_INFOS);
+    }
+
+    @Test
+    public void onCreateViewHolder_viewHolderContainsExpectedView() {
+        ProvisionInfoListAdapter.ProvisionInfoViewHolder viewHolder = mAdapter.onCreateViewHolder(
+                new ViewGroup(mTestApp) {
+                    @Override
+                    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+                    }
+                }, /* viewType= */ 0);
+        assertThat(viewHolder.itemView.getSourceLayoutResId()).isEqualTo(
+                R.layout.item_provision_info);
+    }
+
+    @Test
+    public void onBindViewHolder_regularView_noProviderName_setEmptyText() {
+        int position = 0;
+        ProvisionInfo regularInfo = TEST_PROVISION_INFOS.get(position);
+        String emptyProviderName = "";
+        regularInfo.setProviderName(emptyProviderName);
+
+        assume().that(regularInfo.getType()).isEqualTo(ProvisionInfoType.REGULAR);
+
+        mAdapter.onBindViewHolder(mProvisionInfoViewHolder, position);
+
+        assertThat(mTextView.getText().toString()).isEqualTo(emptyProviderName);
+        assertDrawableId(regularInfo.getDrawableId());
+    }
+
+    @Test
+    public void onBindViewHolder_regularView_providerNameAvailable_setText() {
+        int position = 0;
+        ProvisionInfo regularInfo = TEST_PROVISION_INFOS.get(position);
+        regularInfo.setProviderName(TEST_PROVIDER);
+
+        assume().that(regularInfo.getType()).isEqualTo(ProvisionInfoType.REGULAR);
+
+        mAdapter.onBindViewHolder(mProvisionInfoViewHolder, position);
+
+        String text = String.format(mTestActivity.getString(regularInfo.getTextId()),
+                TEST_PROVIDER);
+        assertThat(mTextView.getText().toString()).isEqualTo(text);
+        assertDrawableId(regularInfo.getDrawableId());
+    }
+
+    @Test
+    public void onBindViewHolder_urlProvisionInfo_urlNotAvailable_setTextWithEmptyUrl() {
+        int position = 1;
+        ProvisionInfo urlProvisionInfo = TEST_PROVISION_INFOS.get(position);
+        urlProvisionInfo.setProviderName(TEST_PROVIDER);
+        String testEmptyUrl = "";
+        urlProvisionInfo.setUrl(testEmptyUrl);
+
+        assume().that(urlProvisionInfo.getType()).isNotEqualTo(ProvisionInfoType.REGULAR);
+
+        mAdapter.onBindViewHolder(mProvisionInfoViewHolder, position);
+
+        CharSequence actualText = mTextView.getText();
+        assertThat(actualText.toString()).isEqualTo(
+                getExpectedUrlString(testEmptyUrl, urlProvisionInfo.getTextId()));
+        assertUrlIsExpected(actualText, testEmptyUrl);
+
+        assertDrawableId(urlProvisionInfo.getDrawableId());
+    }
+
+    @Test
+    public void onBindViewHolder_urlProvisionInfo_urlAvailable_setTextWithUrl() {
+        int position = 1;
+        ProvisionInfo urlProvisionInfo = TEST_PROVISION_INFOS.get(position);
+        urlProvisionInfo.setProviderName(TEST_PROVIDER);
+        urlProvisionInfo.setUrl(TEST_URL);
+
+        assume().that(urlProvisionInfo.getType()).isNotEqualTo(ProvisionInfoType.REGULAR);
+
+        mAdapter.onBindViewHolder(mProvisionInfoViewHolder, position);
+
+        CharSequence actualText = mTextView.getText();
+        assertThat(actualText.toString()).isEqualTo(
+                getExpectedUrlString(TEST_URL, urlProvisionInfo.getTextId()));
+        assertUrlIsExpected(actualText, TEST_URL);
+        assertDrawableId(urlProvisionInfo.getDrawableId());
+    }
+
+    private String getExpectedUrlString(String expectedUrl, int expectedTextId) {
+        String formattedString = String.format(
+                mTestActivity.getString(expectedTextId), TEST_PROVIDER, expectedUrl);
+        return new SpannableString(
+                Html.fromHtml(formattedString, Html.FROM_HTML_MODE_COMPACT)).toString();
+    }
+
+    private void assertUrlIsExpected(CharSequence actualText, String expectedUrl) {
+        SpannedString actualSpannedString = SpannedString.valueOf(actualText);
+        ClickableSpan[] spans = actualSpannedString.getSpans(0, actualSpannedString.length(),
+                ClickableSpan.class);
+        assertThat(spans.length).isAtLeast(1);
+        spans[0].onClick(mTextView);
+        assertThat(Shadows.shadowOf(mTestActivity).getNextStartedActivity().getStringExtra(
+                HelpActivity.EXTRA_URL_PARAM)).isEqualTo(expectedUrl);
+    }
+
+    private void assertDrawableId(int expectedDrawableId) {
+        Drawable[] compoundDrawablesRelative = mTextView.getCompoundDrawablesRelative();
+        assertThat(compoundDrawablesRelative.length).isAtLeast(1);
+        assertThat(Shadows.shadowOf(compoundDrawablesRelative[0]).getCreatedFromResId()).isEqualTo(
+                expectedDrawableId);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoTest.java
index dfd1eb4..1443ad1 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisionInfoTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.android.devicelockcontroller.activities.ProvisionInfo.ProvisionInfoType;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -25,19 +27,34 @@
 @RunWith(JUnit4.class)
 public final class ProvisionInfoTest {
 
-    @Test
-    public void equals_withDifferentFieldValues_returnsFalse() {
-        ProvisionInfo p1 = new ProvisionInfo(/* drawableId= */0, /* textId= */1);
-        ProvisionInfo p2 = new ProvisionInfo(/* drawableId= */100, /* textId= */101);
+    private static final int DRAWABLE_ID_1 = 0;
+    private static final int DRAWABLE_ID_2 = 1;
+    private static final int TEXT_ID_1 = 10;
+    private static final int TEXT_ID_2 = 11;
+    private static final int TYPE_1 = ProvisionInfoType.REGULAR;
+    private static final int TYPE_2 = ProvisionInfoType.TERMS_AND_CONDITIONS;
 
-        assertThat(p1.equals(p2)).isFalse();
+    @Test
+    public void equals_withOneDifferentFieldValue_returnsFalse() {
+        ProvisionInfo p1 = new ProvisionInfo(DRAWABLE_ID_1, TEXT_ID_1, TYPE_1);
+        ProvisionInfo p10 = new ProvisionInfo(DRAWABLE_ID_2, TEXT_ID_1, TYPE_1);
+        ProvisionInfo p12 = new ProvisionInfo(DRAWABLE_ID_1, TEXT_ID_2, TYPE_1);
+        ProvisionInfo p13 = new ProvisionInfo(DRAWABLE_ID_1, TEXT_ID_1, TYPE_2);
+
+        assertThat(p1).isNotEqualTo(p10);
+        assertThat(p1.hashCode()).isNotEqualTo(p10.hashCode());
+        assertThat(p1).isNotEqualTo(p12);
+        assertThat(p1.hashCode()).isNotEqualTo(p12.hashCode());
+        assertThat(p1).isNotEqualTo(p13);
+        assertThat(p1.hashCode()).isNotEqualTo(p13.hashCode());
     }
 
     @Test
     public void equals_withSameFieldValues_returnsTrue() {
-        ProvisionInfo p1 = new ProvisionInfo(/* drawableId= */0, /* textId= */1);
-        ProvisionInfo p2 = new ProvisionInfo(/* drawableId= */0, /* textId= */1);
+        ProvisionInfo p1 = new ProvisionInfo(DRAWABLE_ID_1, TEXT_ID_1, TYPE_1);
+        ProvisionInfo p2 = new ProvisionInfo(DRAWABLE_ID_1, TEXT_ID_1, TYPE_1);
 
-        assertThat(p1.equals(p2)).isTrue();
+        assertThat(p1).isEqualTo(p2);
+        assertThat(p1.hashCode()).isEqualTo(p2.hashCode());
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisioningActivityTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisioningActivityTest.java
new file mode 100644
index 0000000..742388e
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/ProvisioningActivityTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
+
+import static com.android.devicelockcontroller.activities.ProvisioningActivity.EXTRA_SHOW_CRITICAL_PROVISION_FAILED_UI_ON_START;
+import static com.android.devicelockcontroller.activities.ProvisioningActivity.EXTRA_SHOW_PROVISION_FAILED_UI_ON_START;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.Intent;
+import android.os.Looper;
+
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.android.devicelockcontroller.R;
+import com.android.devicelockcontroller.common.DeviceLockConstants;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowLooper;
+
+@RunWith(RobolectricTestRunner.class)
+public final class ProvisioningActivityTest {
+
+    @Test
+    public void noExtraSet_showDevicePoliciesFragment() {
+        ProvisioningActivity activity = Robolectric.buildActivity(
+                ProvisioningActivity.class).create().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        Fragment fragment = activity.getSupportFragmentManager().findFragmentById(
+                R.id.fragment_container);
+        assertThat(fragment).isInstanceOf(DevicePoliciesFragment.class);
+    }
+
+    @Test
+    public void
+            withCriticalFailedUIExtra_setMandatoryFailedProvisionProgressAndShowProgressFragment() {
+        ProvisioningActivity activity = Robolectric.buildActivity(ProvisioningActivity.class,
+                new Intent().putExtra(EXTRA_SHOW_CRITICAL_PROVISION_FAILED_UI_ON_START,
+                        true)).setup().get();
+
+        ShadowLooper.runUiThreadTasks();
+
+        ProvisioningProgress actual = new ViewModelProvider(activity).get(
+                ProvisioningProgressViewModel.class).getProvisioningProgressLiveData().getValue();
+        assertThat(actual).isEqualTo(ProvisioningProgress.getMandatoryProvisioningFailedProgress(
+                DeviceLockConstants.ProvisionFailureReason.POLICY_ENFORCEMENT_FAILED));
+
+        Fragment fragment = activity.getSupportFragmentManager().findFragmentById(
+                R.id.fragment_container);
+        assertThat(fragment).isInstanceOf(ProgressFragment.class);
+    }
+
+    @Test
+    public void withNonCriticalUIExtra_setNonMandatoryFailedProgressAndShowProgressFragment() {
+        ProvisioningActivity activity = Robolectric.buildActivity(ProvisioningActivity.class,
+                new Intent().putExtra(EXTRA_SHOW_PROVISION_FAILED_UI_ON_START,
+                        true)).setup().get();
+
+        ShadowLooper.runUiThreadTasks();
+
+        ProvisioningProgress actual = new ViewModelProvider(activity).get(
+                ProvisioningProgressViewModel.class).getProvisioningProgressLiveData().getValue();
+        assertThat(actual).isEqualTo(ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                DeviceLockConstants.ProvisionFailureReason.UNKNOWN_REASON));
+        Fragment fragment = activity.getSupportFragmentManager().findFragmentById(
+                R.id.fragment_container);
+        assertThat(fragment).isInstanceOf(ProgressFragment.class);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/UrlTextPreferenceTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/UrlTextPreferenceTest.java
new file mode 100644
index 0000000..bc0e4b9
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/activities/UrlTextPreferenceTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.activities;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+import android.content.Context;
+import android.text.SpannedString;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.widget.TextView;
+
+import androidx.preference.PreferenceViewHolder;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.R;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+
+@RunWith(RobolectricTestRunner.class)
+public class UrlTextPreferenceTest {
+
+    @Test
+    public void onBindViewHolder_checkClickableLinkIsCorrect() {
+        Context applicationContext = ApplicationProvider.getApplicationContext();
+        UrlTextPreference preference = new UrlTextPreference(applicationContext, /* attrs= */ null);
+        String expectedUrl = "www.test.com";
+        String testUrlText = String.format(
+                applicationContext.getString(R.string.settings_contact_provider),
+                "test provider", expectedUrl);
+        Activity emptyActivity = Robolectric.buildActivity(Activity.class).setup().get();
+        TextView title = new TextView(emptyActivity);
+        preference.setTitle(testUrlText);
+        preference.setViewId(android.R.id.title);
+        PreferenceViewHolder viewHolder = PreferenceViewHolder.createInstanceForTests(title);
+
+        preference.onBindViewHolder(viewHolder);
+
+        assertThat(title.getMovementMethod()).isInstanceOf(LinkMovementMethod.class);
+
+        SpannedString actualSpannedString = SpannedString.valueOf(title.getText());
+        ClickableSpan[] spans = actualSpannedString.getSpans(0, actualSpannedString.length(),
+                ClickableSpan.class);
+        assertThat(spans.length).isAtLeast(1);
+        spans[0].onClick(title);
+        assertThat(Shadows.shadowOf(emptyActivity).getNextStartedActivity().getStringExtra(
+                HelpActivity.EXTRA_URL_PARAM)).isEqualTo(expectedUrl);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/common/DeviceLockConstantsTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/common/DeviceLockConstantsTest.java
deleted file mode 100644
index cc1c6f5..0000000
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/common/DeviceLockConstantsTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.common;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
-/** Unit tests for {@link DeviceLockConstants} */
-@RunWith(RobolectricTestRunner.class)
-public class DeviceLockConstantsTest {
-
-    @Test
-    public void testGetLandingActivity_returnsLandingActivity() {
-        Context context = ApplicationProvider.getApplicationContext();
-        String expectedProvisioningActivity = context.getPackageName() + "/"
-                + "com.android.devicelockcontroller.activities.LandingActivity";
-
-        String provisioningActivity = DeviceLockConstants.getLandingActivity(context);
-
-        assertThat(provisioningActivity).isEqualTo(expectedProvisioningActivity);
-    }
-}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/AppOpsPolicyHandlerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/AppOpsPolicyHandlerTest.java
index 4da88a4..8d6bc4d 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/AppOpsPolicyHandlerTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/AppOpsPolicyHandlerTest.java
@@ -16,91 +16,40 @@
 
 package com.android.devicelockcontroller.policy;
 
-import static com.google.common.truth.Truth.assertThat;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
-import android.app.AppOpsManager;
-import android.content.Context;
+import android.os.Bundle;
 import android.os.OutcomeReceiver;
 
-import androidx.test.core.app.ApplicationProvider;
-
 import com.android.devicelockcontroller.SystemDeviceLockManager;
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
-import com.android.devicelockcontroller.storage.SetupParametersClientInterface;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
 
-import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.testing.TestingExecutors;
 
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.mockito.stubbing.Answer;
-import org.robolectric.ParameterizedRobolectricTestRunner;
-import org.robolectric.ParameterizedRobolectricTestRunner.Parameter;
-import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
+import org.robolectric.RobolectricTestRunner;
 
-import java.util.Arrays;
-import java.util.List;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 
-@RunWith(ParameterizedRobolectricTestRunner.class)
-public class AppOpsPolicyHandlerTest {
-    private Context mContext;
-
-    @Parameter
-    @DeviceState
-    public int mState;
-
-    @Parameter(1)
-    public boolean mExemptFromStartActivityFromBackgroundRestriction;
-
-    @Parameter(2)
-    public boolean mBackgroundRestrictionShouldBeApplied;
-
-    @Parameter(3)
-    public boolean mExemptFromHibernationRestriction;
-
-    @Parameter(4)
-    public boolean mHibernationRestrictionShouldBeApplied;
-
-    @Parameters(name = "State: {0} is exempt from starting activity from background "
-            + "restriction: {1} background restriction should be applied: {2} "
-            + "is exempt from hibernation: {3} hibernation restriction should be applied: {4}")
-    public static List<Object[]> parameters() {
-        return Arrays.asList(new Object[][]{
-                // State | exempt from background restrictions | background restriction applied |
-                // exempt from hibernation | hibernation restriction applied
-
-                // State that should not change exemptions
-                {DeviceState.PSEUDO_LOCKED,     true, false, true, false},
-                {DeviceState.PSEUDO_UNLOCKED,   true, false, true, false},
-                // Exempt from background activity start restrictions but should not
-                // change hibernation restrictions
-                {DeviceState.SETUP_IN_PROGRESS, true, true, true, false},
-                {DeviceState.SETUP_SUCCEEDED,   true, true, true, false},
-                {DeviceState.SETUP_FAILED,      true, true, true, false},
-                {DeviceState.KIOSK_SETUP,       true, true, true, false},
-                // Exempt from background activity start and hibernation
-                {DeviceState.UNLOCKED,          true, true, true, true},
-                {DeviceState.LOCKED,            true, true, true, true},
-                // Non exempt from background activity start restrictions and hibernation
-                {DeviceState.UNPROVISIONED,     false, true, false, true},
-                {DeviceState.CLEARED,           false, true, false, true}
-        });
-    }
+@RunWith(RobolectricTestRunner.class)
+public final class AppOpsPolicyHandlerTest {
+    public static final String TEST_PACKAGE = "test-package";
 
     @Rule
     public final MockitoRule mocks = MockitoJUnit.rule();
@@ -108,56 +57,103 @@
     @Mock
     private SystemDeviceLockManager mSystemDeviceLockManagerMock;
 
-    @Mock
-    private SetupParametersClientInterface mSetupParametersClient;
+    private AppOpsPolicyHandler mHandler;
 
     @Before
-    public void setUp() {
-        mContext = ApplicationProvider.getApplicationContext();
-    }
-
-    @Test
-    public void setPolicyForState_setsExpectedRestrictions() {
-        PolicyHandler handler = new AppOpsPolicyHandler(mContext, mSystemDeviceLockManagerMock,
-                mContext.getSystemService(AppOpsManager.class), mSetupParametersClient);
-
+    public void setUp() throws ExecutionException, InterruptedException {
+        mHandler = new AppOpsPolicyHandler(mSystemDeviceLockManagerMock,
+                TestingExecutors.sameThreadScheduledExecutor());
+        Bundle bundle = new Bundle();
+        bundle.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        SetupParametersClient.getInstance().createPrefs(bundle).get();
         doAnswer((Answer<Boolean>) invocation -> {
             OutcomeReceiver<Void, Exception> callback = invocation.getArgument(2 /* callback */);
             callback.onResult(null /* result */);
 
             return null;
-        }).when(mSystemDeviceLockManagerMock)
-                .setExemptFromActivityBackgroundStartRestriction(anyBoolean(),
-                        any(Executor.class),
-                        ArgumentMatchers.<OutcomeReceiver<Void, Exception>>any());
+        }).when(mSystemDeviceLockManagerMock).setDlcExemptFromActivityBgStartRestrictionState(
+                anyBoolean(), any(Executor.class), any());
+        doAnswer((Answer<Boolean>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(2 /* callback */);
+            callback.onResult(null /* result */);
 
-        when(mSetupParametersClient.getKioskPackage()).thenReturn(Futures.immediateFuture(""));
+            return null;
+        }).when(mSystemDeviceLockManagerMock).setDlcAllowedToSendUndismissibleNotifications(
+                anyBoolean(), any(Executor.class), any());
 
         doAnswer((Answer<Boolean>) invocation -> {
             OutcomeReceiver<Void, Exception> callback = invocation.getArgument(3 /* callback */);
             callback.onResult(null /* result */);
 
             return null;
-        }).when(mSystemDeviceLockManagerMock)
-                .setExemptFromHibernation(anyString(), anyBoolean(),
-                        any(Executor.class),
-                        ArgumentMatchers.<OutcomeReceiver<Void, Exception>>any());
+        }).when(mSystemDeviceLockManagerMock).setKioskAppExemptFromRestrictionsState(anyString(),
+                anyBoolean(), any(Executor.class), any());
+    }
 
-        assertThat(Futures.getUnchecked(handler.setPolicyForState(mState)))
-                .isEqualTo(AppOpsPolicyHandler.SUCCESS);
+    @Test
+    public void onProvisioned_shouldExemptBackgroundStartAndKioskApp()
+            throws ExecutionException, InterruptedException {
+        mHandler.onProvisioned().get();
 
-        final int backgroundRestrictionCount = mBackgroundRestrictionShouldBeApplied ? 1 : 0;
-        verify(mSystemDeviceLockManagerMock, times(backgroundRestrictionCount))
-                .setExemptFromActivityBackgroundStartRestriction(
-                        eq(mExemptFromStartActivityFromBackgroundRestriction),
-                        any(Executor.class),
-                        ArgumentMatchers.<OutcomeReceiver<Void, Exception>>any());
+        verify(mSystemDeviceLockManagerMock).setDlcExemptFromActivityBgStartRestrictionState(
+                eq(true), any(Executor.class), any());
+        verify(mSystemDeviceLockManagerMock).setKioskAppExemptFromRestrictionsState(
+                eq(TEST_PACKAGE), eq(true), any(Executor.class), any());
+    }
 
-        final int hibernationCount = mHibernationRestrictionShouldBeApplied ? 1 : 0;
-        verify(mSystemDeviceLockManagerMock, times(hibernationCount))
-                .setExemptFromHibernation(anyString(),
-                        eq(mExemptFromHibernationRestriction),
-                        any(Executor.class),
-                        ArgumentMatchers.<OutcomeReceiver<Void, Exception>>any());
+    @Test
+    public void onProvisionInProgress_shouldExemptBackgroundStartAndAllwUndismissibleNotifs()
+            throws ExecutionException, InterruptedException {
+        mHandler.onProvisionInProgress().get();
+
+        verify(mSystemDeviceLockManagerMock).setDlcExemptFromActivityBgStartRestrictionState(
+                eq(true), any(Executor.class), any());
+        verify(mSystemDeviceLockManagerMock).setDlcAllowedToSendUndismissibleNotifications(
+                eq(true), any(Executor.class), any());
+        verify(mSystemDeviceLockManagerMock, never()).setKioskAppExemptFromRestrictionsState(
+                anyString(), anyBoolean(), any(Executor.class), any());
+    }
+
+    @Test
+    public void onProvisionFailed_shouldBanBackgroundStart()
+            throws ExecutionException, InterruptedException {
+        mHandler.onProvisionFailed().get();
+
+        verify(mSystemDeviceLockManagerMock).setDlcExemptFromActivityBgStartRestrictionState(
+                eq(false), any(Executor.class), any());
+    }
+
+    @Test
+    public void onCleared_shouldResetDlcAndKioskAppExemptions()
+            throws ExecutionException, InterruptedException {
+        mHandler.onCleared().get();
+
+        verify(mSystemDeviceLockManagerMock).setDlcExemptFromActivityBgStartRestrictionState(
+                eq(false), any(Executor.class), any());
+        verify(mSystemDeviceLockManagerMock).setDlcAllowedToSendUndismissibleNotifications(
+                eq(false), any(Executor.class), any());
+        verify(mSystemDeviceLockManagerMock).setKioskAppExemptFromRestrictionsState(
+                eq(TEST_PACKAGE), eq(false), any(Executor.class), any());
+    }
+
+    @Test
+    public void onLocked_shouldExemptBackgroundStartAndKioskApp()
+            throws ExecutionException, InterruptedException {
+        mHandler.onLocked().get();
+        verify(mSystemDeviceLockManagerMock).setDlcExemptFromActivityBgStartRestrictionState(
+                eq(true), any(Executor.class), any());
+        verify(mSystemDeviceLockManagerMock).setKioskAppExemptFromRestrictionsState(
+                eq(TEST_PACKAGE), eq(true), any(Executor.class), any());
+    }
+
+    @Test
+    public void onUnlocked_shouldExemptKioskAppNotBackgroundStart()
+            throws ExecutionException, InterruptedException {
+        mHandler.onUnlocked().get();
+        verify(mSystemDeviceLockManagerMock,
+                never()).setDlcExemptFromActivityBgStartRestrictionState(anyBoolean(),
+                any(Executor.class), any());
+        verify(mSystemDeviceLockManagerMock).setKioskAppExemptFromRestrictionsState(
+                eq(TEST_PACKAGE), eq(true), any(Executor.class), any());
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ControllerKeepAlivePolicyHandlerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ControllerKeepAlivePolicyHandlerTest.java
new file mode 100644
index 0000000..0a330a2
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ControllerKeepAlivePolicyHandlerTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+import android.os.OutcomeReceiver;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class ControllerKeepAlivePolicyHandlerTest {
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private SystemDeviceLockManager mSystemDeviceLockManager;
+    private ControllerKeepAlivePolicyHandler mHandler;
+
+    @Before
+    public void setUp() {
+        mHandler = new ControllerKeepAlivePolicyHandler(mSystemDeviceLockManager,
+                Executors.newSingleThreadExecutor());
+    }
+
+    @Test
+    public void onProvisioned_withSuccess_shouldDisableControllerKeepalive()
+        throws ExecutionException, InterruptedException {
+        setExpectationsOnDisableControllerKeepalive(/* isSuccess =*/ true);
+        assertThat(mHandler.onProvisioned().get()).isTrue();
+        verify(mSystemDeviceLockManager).disableControllerKeepalive(any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).enableControllerKeepalive(any(Executor.class),
+                any());
+    }
+
+    @Test
+    public void onProvisioned_withFailure_shouldDisableControllerKeepalive()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnDisableControllerKeepalive(/* isSuccess =*/ false);
+        assertThat(mHandler.onProvisioned().get()).isTrue();
+        verify(mSystemDeviceLockManager).disableControllerKeepalive(any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).enableControllerKeepalive(any(Executor.class),
+                any());
+    }
+
+    @Test
+    public void onProvisionPaused_withSuccess_shouldDisableControllerKeepalive()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnDisableControllerKeepalive(/* isSuccess =*/ true);
+        assertThat(mHandler.onProvisionPaused().get()).isTrue();
+        verify(mSystemDeviceLockManager).disableControllerKeepalive(any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).enableControllerKeepalive(any(Executor.class),
+                any());
+    }
+
+    @Test
+    public void onProvisionPaused_withFailure_shouldDisableControllerKeepalive()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnDisableControllerKeepalive(/* isSuccess =*/ false);
+        assertThat(mHandler.onProvisionPaused().get()).isTrue();
+        verify(mSystemDeviceLockManager).disableControllerKeepalive(any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).enableControllerKeepalive(any(Executor.class),
+                any());
+    }
+
+    @Test
+    public void onProvisionInProgress_withSuccess_shouldEnableControllerKeepalive()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnEnableControllerKeepalive(/* isSuccess =*/ true);
+        assertThat(mHandler.onProvisionInProgress().get()).isTrue();
+        verify(mSystemDeviceLockManager).enableControllerKeepalive(any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).disableControllerKeepalive(any(Executor.class),
+                any());
+    }
+
+    @Test
+    public void onProvisionInProgress_withFailure_shouldEnableControllerKeepalive()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnEnableControllerKeepalive(/* isSuccess =*/ false);
+        assertThat(mHandler.onProvisionInProgress().get()).isTrue();
+        verify(mSystemDeviceLockManager).enableControllerKeepalive(any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).disableControllerKeepalive(any(Executor.class),
+                any());
+    }
+
+    @Test
+    public void onProvisionFailed_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionFailed().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onCleared_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onCleared().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onLocked_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onLocked().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onUnlocked_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onUnlocked().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    private void setExpectationsOnEnableControllerKeepalive(boolean isSuccess) {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 1);
+            if (isSuccess) {
+                callback.onResult(/* result =*/ null);
+            } else {
+                callback.onError(new Exception());
+            }
+            return null;
+        }).when(mSystemDeviceLockManager).enableControllerKeepalive(any(Executor.class), any());
+    }
+
+    private void setExpectationsOnDisableControllerKeepalive(boolean isSuccess) {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 1);
+            if (isSuccess) {
+                callback.onResult(/* result =*/ null);
+            } else {
+                callback.onError(new Exception());
+            }
+            return null;
+        }).when(mSystemDeviceLockManager).disableControllerKeepalive(any(Executor.class), any());
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/DevicePolicyControllerImplTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/DevicePolicyControllerImplTest.java
new file mode 100644
index 0000000..a6e8137
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/DevicePolicyControllerImplTest.java
@@ -0,0 +1,1288 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.activities.ProvisioningActivity.EXTRA_SHOW_CRITICAL_PROVISION_FAILED_UI_ON_START;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_FINANCING_PROVISIONING;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ACTION_START_DEVICE_SUBSIDY_PROVISIONING;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_PROVISIONING_TYPE;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType.TYPE_FINANCED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType.TYPE_SUBSIDY;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType.TYPE_UNDEFINED;
+import static com.android.devicelockcontroller.policy.DevicePolicyControllerImpl.ACTION_DEVICE_LOCK_KIOSK_SETUP;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNDEFINED;
+import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED;
+import static com.android.devicelockcontroller.policy.StartLockTaskModeWorker.START_LOCK_TASK_MODE_WORK_NAME;
+import static com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.OutcomeReceiver;
+import android.os.UserManager;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+import androidx.work.testing.WorkManagerTestInitHelper;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.activities.LandingActivity;
+import com.android.devicelockcontroller.activities.ProvisioningActivity;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowPackageManager;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class DevicePolicyControllerImplTest {
+    private static final String TEST_KIOSK_PACKAGE = "test.package1";
+    private static final String TEST_KIOSK_ACTIVITY = "TestActivity";
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private ProvisionStateController mMockProvisionStateController;
+    @Mock
+    private SystemDeviceLockManager mMockSystemDeviceLockManager;
+    @Mock
+    private DevicePolicyManager mMockDpm;
+    @Mock
+    private UserManager mMockUserManager;
+    @Captor
+    private ArgumentCaptor<Integer> mAllowedFlags;
+
+    private DevicePolicyController mDevicePolicyController;
+    private TestDeviceLockControllerApplication mTestApp;
+
+    @Before
+    public void setUp() {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        WorkManagerTestInitHelper.initializeTestWorkManager(mTestApp);
+        ExecutorService bgExecutor = Executors.newSingleThreadExecutor();
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+
+        UserRestrictionsPolicyHandler userRestrictionsPolicyHandler =
+                new UserRestrictionsPolicyHandler(mMockDpm,
+                        mMockUserManager, /* isDebug =*/ false, bgExecutor);
+        AppOpsPolicyHandler appOpsPolicyHandler = new AppOpsPolicyHandler(
+                mMockSystemDeviceLockManager, bgExecutor);
+        LockTaskModePolicyHandler lockTaskModePolicyHandler = new LockTaskModePolicyHandler(
+                mTestApp, mMockDpm, bgExecutor);
+        PackagePolicyHandler packagePolicyHandler = new PackagePolicyHandler(mTestApp, mMockDpm,
+                bgExecutor);
+        RolePolicyHandler rolePolicyHandler = new RolePolicyHandler(mMockSystemDeviceLockManager,
+                bgExecutor);
+        KioskKeepAlivePolicyHandler kioskKeepAlivePolicyHandler = new KioskKeepAlivePolicyHandler(
+                mMockSystemDeviceLockManager,
+                bgExecutor);
+        ControllerKeepAlivePolicyHandler controllerKeepAlivePolicyHandler =
+                new ControllerKeepAlivePolicyHandler(
+                        mMockSystemDeviceLockManager,
+                        bgExecutor);
+        NotificationsPolicyHandler notificationsPolicyHandler =
+                new NotificationsPolicyHandler(mMockSystemDeviceLockManager, bgExecutor);
+        mDevicePolicyController =
+                new DevicePolicyControllerImpl(mTestApp,
+                        mMockDpm,
+                        mMockUserManager,
+                        userRestrictionsPolicyHandler,
+                        appOpsPolicyHandler,
+                        lockTaskModePolicyHandler,
+                        packagePolicyHandler,
+                        rolePolicyHandler,
+                        kioskKeepAlivePolicyHandler,
+                        controllerKeepAlivePolicyHandler,
+                        notificationsPolicyHandler,
+                        mMockProvisionStateController,
+                        bgExecutor);
+    }
+
+    @Test
+    public void wipeDevice_shouldMakeExpectedCalls() {
+        assertThat(mDevicePolicyController.wipeDevice()).isTrue();
+        verify(mMockDpm).wipeDevice(mAllowedFlags.capture());
+        assertThat(mAllowedFlags.getValue()).isEqualTo(DevicePolicyManager.WIPE_SILENTLY
+                | DevicePolicyManager.WIPE_RESET_PROTECTION_DATA);
+    }
+
+    @Test
+    public void wipeDevice_withSecurityException_handleException() {
+        doThrow(new SecurityException()).when(mMockDpm).wipeDevice(
+                eq(DevicePolicyManager.WIPE_SILENTLY
+                        | DevicePolicyManager.WIPE_RESET_PROTECTION_DATA));
+        assertThat(mDevicePolicyController.wipeDevice()).isFalse();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withUnprovisionedState_doesNotStartLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.UNPROVISIONED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withProvisionInProgressState_startsLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableControllerKeepAlive();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withKioskProvisionedState_startsLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnAddFinancedDeviceKioskRole();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.KIOSK_PROVISIONED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withProvisionPausedState_doesNotStartLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setExpectationsOnDisableControllerKeepAlive();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_PAUSED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withProvisionPausedAndDeviceLocked_doesNotStartLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setExpectationsOnDisableControllerKeepAlive();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_PAUSED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(LOCKED).get();
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withProvisionFailedState_doesNotStartLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_FAILED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withProvisionSucceededState_doesNotStartLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setExpectationsOnDisableControllerKeepAlive();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withLockedDeviceState_startsLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(LOCKED).get();
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withUnlockedDeviceState_doesNotStartLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(UNLOCKED).get();
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_withClearedDeviceState_doesNotStartLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnDisableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnRemoveFinancedDeviceKioskRole();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        setupFinalizationControllerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(CLEARED).get();
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void enforceCurrentPolicies_clearedButProvisionInProgress_doesNotStartLockTaskMode()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnDisableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnRemoveFinancedDeviceKioskRole();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        setupFinalizationControllerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(CLEARED).get();
+
+        mDevicePolicyController.enforceCurrentPolicies().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void getLaunchIntent_withUnProvisionState_forCriticalFailure_shouldHaveExpectedIntent()
+            throws Exception {
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPoliciesForCriticalFailure().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleMandatoryResetDeviceAlarm();
+        assertReportSetupFailedWorkStarted();
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        verify(mMockProvisionStateController).getState();
+        assertCriticalFailureIntent(intent);
+    }
+
+    @Test
+    public void
+            getLaunchIntent_withProvisionPausedState_forCriticalFailure_shouldHaveExpectedIntent()
+            throws Exception {
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        setExpectationsOnDisableControllerKeepAlive();
+
+        mDevicePolicyController.enforceCurrentPoliciesForCriticalFailure().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleMandatoryResetDeviceAlarm();
+        assertReportSetupFailedWorkStarted();
+
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_PAUSED));
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertCriticalFailureIntent(intent);
+    }
+
+    @Test
+    public void
+            getLaunchIntent_withProvisionSucceededSt_forCriticalFailure_shouldHaveExpectedIntent()
+            throws Exception {
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPoliciesForCriticalFailure().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleMandatoryResetDeviceAlarm();
+        assertReportSetupFailedWorkStarted();
+
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertCriticalFailureIntent(intent);
+    }
+
+    @Test
+    public void
+            getLaunchIntent_withKioskProvisionedState_forCriticalFailure_shouldHaveExpectedIntent()
+            throws Exception {
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPoliciesForCriticalFailure().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleMandatoryResetDeviceAlarm();
+        assertReportSetupFailedWorkStarted();
+
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.KIOSK_PROVISIONED));
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertCriticalFailureIntent(intent);
+    }
+
+    @Test
+    public void
+            getLaunchIntent_withProvisionFailedState_forCriticalFailure_shouldHaveExpectedIntent()
+            throws Exception {
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.enforceCurrentPoliciesForCriticalFailure().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleMandatoryResetDeviceAlarm();
+        assertReportSetupFailedWorkStarted();
+
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_FAILED));
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertCriticalFailureIntent(intent);
+    }
+
+    @Test
+    public void
+            getLaunchIntent_withProvisionInProgressSt_forCriticalFailure_shouldHaveExpectedIntent()
+            throws Exception {
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        setExpectationsOnEnableControllerKeepAlive();
+
+        mDevicePolicyController.enforceCurrentPoliciesForCriticalFailure().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleMandatoryResetDeviceAlarm();
+        assertReportSetupFailedWorkStarted();
+
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertCriticalFailureIntent(intent);
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withUnprovisionedState_shouldMakeExpectedCalls()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.UNPROVISIONED));
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+        assertThat(intent).isNull();
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionPausedState_shouldMakeExpectedCalls()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnDisableControllerKeepAlive();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_PAUSED));
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+        assertThat(intent).isNull();
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionFailedState_shouldMakeExpectedCalls()
+            throws ExecutionException, InterruptedException {
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_FAILED));
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+        assertThat(intent).isNull();
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionSucceededState_shouldMakeExpectedCalls()
+            throws ExecutionException, InterruptedException {
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnDisableControllerKeepAlive();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+        assertThat(intent).isNull();
+    }
+
+    @Test
+    public void
+            getLaunchIntentForCurrentState_withProvisionSucceededState_withoutKioskAppInstalled()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnDisableControllerKeepAlive();
+        GlobalParametersClient.getInstance().setDeviceState(LOCKED).get();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDevicePolicyController.getLaunchIntentForCurrentState().get());
+
+        assertThat(thrown).hasCauseThat().isInstanceOf(IllegalStateException.class);
+        assertThat(thrown).hasMessageThat().contains("Failed to get launch intent for kiosk app!");
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionSucceededStateAndKioskAppInstalled()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        GlobalParametersClient.getInstance().setDeviceState(LOCKED).get();
+        installKioskAppWithLockScreenIntentFilter();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(intent).isNotNull();
+        assertThat(intent.getComponent().getClassName()).isEqualTo(TEST_KIOSK_ACTIVITY);
+        assertThat(intent.getCategories()).containsExactly(Intent.CATEGORY_HOME);
+        assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
+    }
+
+    @Test
+    public void
+            getLaunchIntentForCurrentState_withProvisionSucceededStateAndKioskAppWithoutHomeCateg()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        GlobalParametersClient.getInstance().setDeviceState(LOCKED).get();
+        installKioskAppWithoutCategoryHomeIntentFilter();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(intent).isNotNull();
+        assertThat(intent.getComponent().getClassName()).isEqualTo(TEST_KIOSK_ACTIVITY);
+        assertThat(intent.getCategories()).containsExactly(Intent.CATEGORY_LAUNCHER);
+        assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionSucceededStateAndDeviceStateUnlocked()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        GlobalParametersClient.getInstance().setDeviceState(UNLOCKED).get();
+        installKioskAppWithoutCategoryHomeIntentFilter();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(intent).isNull();
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withDeviceStateCleared_returnsNull()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnDisableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnRemoveFinancedDeviceKioskRole();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        setupFinalizationControllerExpectations();
+        GlobalParametersClient.getInstance().setDeviceState(CLEARED).get();
+        installKioskAppWithoutCategoryHomeIntentFilter();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(intent).isNull();
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_provisionInProgressButCleared_returnsNull()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnDisableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnRemoveFinancedDeviceKioskRole();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        setupFinalizationControllerExpectations();
+        GlobalParametersClient.getInstance().setDeviceState(CLEARED).get();
+        installKioskAppWithoutCategoryHomeIntentFilter();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(intent).isNull();
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionSucceededStateAndDeviceStateUndefined()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        GlobalParametersClient.getInstance().setDeviceState(UNDEFINED).get();
+        installKioskAppWithoutCategoryHomeIntentFilter();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(intent).isNull();
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withKioskProvisionedState_shouldReturnIntent()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnAddFinancedDeviceKioskRole();
+        installKioskAppWithSetupIntentFilter();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.KIOSK_PROVISIONED));
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(intent).isNotNull();
+        assertThat(intent.getComponent().getClassName()).isEqualTo(TEST_KIOSK_ACTIVITY);
+        assertThat(intent.getAction()).isEqualTo(ACTION_DEVICE_LOCK_KIOSK_SETUP);
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withKioskProvisionedState_withoutKioskAppInstalled()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnAddFinancedDeviceKioskRole();
+
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.KIOSK_PROVISIONED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDevicePolicyController.getLaunchIntentForCurrentState().get());
+
+        assertThat(thrown).hasCauseThat().isInstanceOf(IllegalStateException.class);
+        assertThat(thrown).hasMessageThat().contains(
+                "Failed to get setup activity intent for kiosk app!");
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withKioskProvisionedState_withoutKioskAppPackage() {
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnAddFinancedDeviceKioskRole();
+        installKioskAppWithSetupIntentFilter();
+
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.KIOSK_PROVISIONED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDevicePolicyController.getLaunchIntentForCurrentState().get());
+
+        assertThat(thrown).hasCauseThat().isInstanceOf(IllegalStateException.class);
+        assertThat(thrown).hasMessageThat().contains(
+                "Failed to enforce policies for provision state");
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionInProgressState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableControllerKeepAlive();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDevicePolicyController.getLaunchIntentForCurrentState().get());
+
+        assertThat(thrown).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
+        assertThat(thrown).hasMessageThat().contains("Provisioning type is unknown!");
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionTypeUndefined_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_KIOSK_PACKAGE);
+        preferences.putInt(EXTRA_PROVISIONING_TYPE, TYPE_UNDEFINED);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableControllerKeepAlive();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDevicePolicyController.getLaunchIntentForCurrentState().get());
+
+        assertThat(thrown).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
+        assertThat(thrown).hasMessageThat().contains("Provisioning type is unknown!");
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionTypeFinanced_shouldReturnIntent()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_KIOSK_PACKAGE);
+        preferences.putInt(EXTRA_PROVISIONING_TYPE, TYPE_FINANCED);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableControllerKeepAlive();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(intent).isNotNull();
+        assertThat(intent.getComponent().getClassName()).isEqualTo(LandingActivity.class.getName());
+        assertThat(intent.getAction()).isEqualTo(ACTION_START_DEVICE_FINANCING_PROVISIONING);
+    }
+
+    @Test
+    public void getLaunchIntentForCurrentState_withProvisionTypeSubsidy_shouldReturnIntent()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_KIOSK_PACKAGE);
+        preferences.putInt(EXTRA_PROVISIONING_TYPE, TYPE_SUBSIDY);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableControllerKeepAlive();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+
+        Intent intent = mDevicePolicyController.getLaunchIntentForCurrentState().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(intent).isNotNull();
+        assertThat(intent.getComponent().getClassName()).isEqualTo(LandingActivity.class.getName());
+        assertThat(intent.getAction()).isEqualTo(ACTION_START_DEVICE_SUBSIDY_PROVISIONING);
+    }
+
+    @Test
+    public void onUserUnlocked_withUnprovisionedState_shouldCallExpectedMethods() throws Exception {
+        when(mMockProvisionStateController.onUserUnlocked()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.UNPROVISIONED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onUserUnlocked_withProvisionInProgressState_shouldCallExpectedMethods()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableControllerKeepAlive();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        when(mMockProvisionStateController.onUserUnlocked()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+    }
+
+    @Test
+    public void onUserUnlocked_withKioskProvisionedState_shouldMakeExpectedCalls()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnAddFinancedDeviceKioskRole();
+        when(mMockProvisionStateController.onUserUnlocked()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.KIOSK_PROVISIONED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+    }
+
+    @Test
+    public void onUserUnlocked_withProvisionPausedState_shouldMakeExpectedCalls()
+            throws Exception {
+        setupSetupParameters();
+        setExpectationsOnDisableControllerKeepAlive();
+        when(mMockProvisionStateController.onUserUnlocked()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_PAUSED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onUserUnlocked_withProvisionFailedState_shouldMakeExpectedCalls()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.onUserUnlocked()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_FAILED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onUserUnlocked_withUndefinedDeviceState_shouldMakeExpectedCalls() throws Exception {
+        setupSetupParameters();
+        when(mMockProvisionStateController.onUserUnlocked()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(UNDEFINED).get();
+
+        mDevicePolicyController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onUserUnlocked_withLockedDeviceState_shouldMakeExpectedCalls() throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.onUserUnlocked()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(LOCKED).get();
+
+        mDevicePolicyController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+    }
+
+    @Test
+    public void onUserUnlocked_withUnlockedDeviceState_shouldMakeExpectedCalls() throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.onUserUnlocked()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(UNLOCKED).get();
+
+        mDevicePolicyController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onUserUnlocked_withClearedDeviceState_shouldMakeExpectedCalls() throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnDisableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnRemoveFinancedDeviceKioskRole();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        setupFinalizationControllerExpectations();
+        when(mMockProvisionStateController.onUserUnlocked()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(CLEARED).get();
+
+        mDevicePolicyController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onAppCrashed_withUnprovisionedState_shouldMakeExpectedCalls()
+            throws Exception {
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.UNPROVISIONED));
+
+        mDevicePolicyController.onAppCrashed(true /* isKiosk */).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onAppCrashed_withProvisionInProgressState_shouldCallExpectedMethods()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableControllerKeepAlive();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_IN_PROGRESS));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.onAppCrashed(true /* isKiosk */).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+    }
+
+    @Test
+    public void onAppCrashed_withKioskProvisionedState_shouldMakeExpectedCalls()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnEnableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnAddFinancedDeviceKioskRole();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.KIOSK_PROVISIONED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.onAppCrashed(true /* isKiosk */).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+    }
+
+    @Test
+    public void onAppCrashed_withProvisionPausedState_shouldMakeExpectedCalls()
+            throws Exception {
+        setupSetupParameters();
+        setExpectationsOnDisableControllerKeepAlive();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_PAUSED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.onAppCrashed(true /* isKiosk */).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onAppCrashed_withProvisionFailedState_shouldMakeExpectedCalls()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_FAILED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+
+        mDevicePolicyController.onAppCrashed(true /* isKiosk */).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onAppCrashed_withUndefinedDeviceState_shouldMakeExpectedCalls()
+            throws Exception {
+        setupSetupParameters();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(UNDEFINED).get();
+
+        mDevicePolicyController.onAppCrashed(true /* isKiosk */).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onAppCrashed_withLockedDeviceState_shouldMakeExpectedCalls() throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(LOCKED).get();
+
+        mDevicePolicyController.onAppCrashed(true /* isKiosk */).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeStarted();
+    }
+
+    @Test
+    public void onAppCrashed_withUnlockedDeviceState_shouldMakeExpectedCalls()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(UNLOCKED).get();
+
+        mDevicePolicyController.onAppCrashed(true /* isKiosk */).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    @Test
+    public void onAppCrashed_withClearedDeviceState_shouldMakeExpectedCalls()
+            throws Exception {
+        setupSetupParameters();
+        setupAppOpsPolicyHandlerExpectations();
+        setExpectationsOnDisableKioskKeepAlive();
+        setExpectationsOnDisableControllerKeepAlive();
+        setExpectationsOnRemoveFinancedDeviceKioskRole();
+        setExpectationsOnSetPostNotificationsSystemFixed();
+        setupFinalizationControllerExpectations();
+        when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
+                ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockUserManager.isUserUnlocked()).thenReturn(true);
+        GlobalParametersClient.getInstance().setDeviceState(CLEARED).get();
+
+        mDevicePolicyController.onAppCrashed(true /* isKiosk */).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskModeNotStarted();
+    }
+
+    private void assertLockTaskModeStarted() throws Exception {
+        ListenableFuture<List<WorkInfo>> workInfosFuture = WorkManager.getInstance(mTestApp)
+                .getWorkInfosForUniqueWork(START_LOCK_TASK_MODE_WORK_NAME);
+        List<WorkInfo> workInfos = Futures.getChecked(workInfosFuture, Exception.class);
+        assertThat(workInfos).isNotEmpty();
+    }
+
+    private void assertLockTaskModeNotStarted() throws Exception {
+        ListenableFuture<List<WorkInfo>> workInfosFuture = WorkManager.getInstance(mTestApp)
+                .getWorkInfosForUniqueWork(START_LOCK_TASK_MODE_WORK_NAME);
+        List<WorkInfo> workInfos = Futures.getChecked(workInfosFuture, Exception.class);
+        assertThat(workInfos).isEmpty();
+    }
+
+    private void assertReportSetupFailedWorkStarted() throws Exception {
+        ListenableFuture<List<WorkInfo>> workInfosFuture = WorkManager.getInstance(mTestApp)
+                .getWorkInfosForUniqueWork(REPORT_PROVISION_STATE_WORK_NAME);
+        List<WorkInfo> workInfos = Futures.getChecked(workInfosFuture, Exception.class);
+        assertThat(workInfos).isNotEmpty();
+    }
+
+    private static void assertCriticalFailureIntent(Intent intent) {
+        assertThat(intent).isNotNull();
+        assertThat(intent.getComponent().getClassName()).isEqualTo(
+                ProvisioningActivity.class.getName());
+        assertThat(intent.getExtras().getBoolean(
+                EXTRA_SHOW_CRITICAL_PROVISION_FAILED_UI_ON_START)).isTrue();
+    }
+
+    private void installKioskAppWithoutCategoryHomeIntentFilter() {
+        ShadowPackageManager shadowPackageManager = Shadows.shadowOf(mTestApp.getPackageManager());
+        PackageInfo kioskPackageInfo = new PackageInfo();
+        kioskPackageInfo.packageName = TEST_KIOSK_PACKAGE;
+        shadowPackageManager.installPackage(kioskPackageInfo);
+
+        IntentFilter kioskAppIntentFilter = new IntentFilter(Intent.ACTION_MAIN);
+        kioskAppIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);
+        kioskAppIntentFilter.addCategory(Intent.CATEGORY_LAUNCHER);
+        ComponentName kioskAppComponent =
+                new ComponentName(TEST_KIOSK_PACKAGE, TEST_KIOSK_ACTIVITY);
+
+        shadowPackageManager.addActivityIfNotPresent(kioskAppComponent);
+        shadowPackageManager.addIntentFilterForActivity(kioskAppComponent, kioskAppIntentFilter);
+    }
+
+    private void installKioskAppWithLockScreenIntentFilter() {
+        ShadowPackageManager shadowPackageManager = Shadows.shadowOf(mTestApp.getPackageManager());
+        PackageInfo kioskPackageInfo = new PackageInfo();
+        kioskPackageInfo.packageName = TEST_KIOSK_PACKAGE;
+        shadowPackageManager.installPackage(kioskPackageInfo);
+
+        IntentFilter kioskAppIntentFilter = new IntentFilter(Intent.ACTION_MAIN);
+        kioskAppIntentFilter.addCategory(Intent.CATEGORY_HOME);
+        kioskAppIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);
+        ComponentName kioskAppComponent =
+                new ComponentName(TEST_KIOSK_PACKAGE, TEST_KIOSK_ACTIVITY);
+
+        shadowPackageManager.addActivityIfNotPresent(kioskAppComponent);
+        shadowPackageManager.addIntentFilterForActivity(kioskAppComponent, kioskAppIntentFilter);
+    }
+
+    private void installKioskAppWithSetupIntentFilter() {
+        ShadowPackageManager shadowPackageManager = Shadows.shadowOf(mTestApp.getPackageManager());
+        PackageInfo kioskPackageInfo = new PackageInfo();
+        kioskPackageInfo.packageName = TEST_KIOSK_PACKAGE;
+        shadowPackageManager.installPackage(kioskPackageInfo);
+
+        IntentFilter kioskAppIntentFilter =
+                new IntentFilter(ACTION_DEVICE_LOCK_KIOSK_SETUP);
+        kioskAppIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);
+        ComponentName kioskAppComponent =
+                new ComponentName(TEST_KIOSK_PACKAGE, TEST_KIOSK_ACTIVITY);
+
+        shadowPackageManager.addActivityIfNotPresent(kioskAppComponent);
+        shadowPackageManager.addIntentFilterForActivity(kioskAppComponent, kioskAppIntentFilter);
+    }
+
+    private static void setupSetupParameters() throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_KIOSK_PACKAGE);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+    }
+
+    private void setExpectationsOnAddFinancedDeviceKioskRole() {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 2);
+            callback.onResult(/* result =*/ null);
+            return null;
+        }).when(mMockSystemDeviceLockManager).addFinancedDeviceKioskRole(anyString(),
+                any(Executor.class), any());
+    }
+
+    private void setExpectationsOnRemoveFinancedDeviceKioskRole() {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 2);
+            callback.onResult(/* result =*/ null);
+            return null;
+        }).when(mMockSystemDeviceLockManager).removeFinancedDeviceKioskRole(anyString(),
+                any(Executor.class), any());
+    }
+
+    private void setExpectationsOnEnableKioskKeepAlive() {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 2);
+            callback.onResult(/* result =*/ null);
+            return null;
+        }).when(mMockSystemDeviceLockManager).enableKioskKeepalive(anyString(),
+                any(Executor.class), any());
+    }
+
+    private void setExpectationsOnDisableKioskKeepAlive() {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 1);
+            callback.onResult(/* result =*/ null);
+            return null;
+        }).when(mMockSystemDeviceLockManager).disableKioskKeepalive(any(Executor.class), any());
+    }
+
+    private void setExpectationsOnEnableControllerKeepAlive() {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 1);
+            callback.onResult(/* result =*/ null);
+            return null;
+        }).when(mMockSystemDeviceLockManager).enableControllerKeepalive(any(Executor.class),
+                any());
+    }
+
+    private void setExpectationsOnDisableControllerKeepAlive() {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 1);
+            callback.onResult(/* result =*/ null);
+            return null;
+        }).when(mMockSystemDeviceLockManager).disableControllerKeepalive(any(Executor.class),
+                any());
+    }
+
+    private void setupAppOpsPolicyHandlerExpectations() {
+        doAnswer((Answer<Boolean>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(2 /* callback */);
+            callback.onResult(null /* result */);
+
+            return null;
+        }).when(mMockSystemDeviceLockManager)
+                .setDlcExemptFromActivityBgStartRestrictionState(anyBoolean(),
+                        any(Executor.class),
+                        any());
+        doAnswer((Answer<Boolean>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(2 /* callback */);
+            callback.onResult(null /* result */);
+
+            return null;
+        }).when(mMockSystemDeviceLockManager)
+                .setDlcAllowedToSendUndismissibleNotifications(anyBoolean(),
+                        any(Executor.class),
+                        any());
+
+        doAnswer((Answer<Boolean>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(3 /* callback */);
+            callback.onResult(null /* result */);
+
+            return null;
+        }).when(mMockSystemDeviceLockManager)
+                .setKioskAppExemptFromRestrictionsState(anyString(), anyBoolean(),
+                        any(Executor.class), any());
+    }
+
+    private void setupFinalizationControllerExpectations() {
+        doAnswer((Answer<Boolean>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(2 /* callback */);
+            callback.onResult(null /* result */);
+
+            return null;
+        }).when(mMockSystemDeviceLockManager)
+                .setDeviceFinalized(anyBoolean(),
+                        any(Executor.class),
+                        any());
+    }
+
+    private void setExpectationsOnSetPostNotificationsSystemFixed() {
+        doAnswer((Answer<Boolean>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(2 /* callback */);
+            callback.onResult(null /* result */);
+
+            return null;
+        }).when(mMockSystemDeviceLockManager)
+                .setPostNotificationsSystemFixed(anyBoolean(),
+                        any(Executor.class),
+                        any());
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/DeviceStateControllerImplTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/DeviceStateControllerImplTest.java
new file mode 100644
index 0000000..458b843
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/DeviceStateControllerImplTest.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+
+import com.google.common.util.concurrent.Futures;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class DeviceStateControllerImplTest {
+    private static final String USER_HAS_NOT_BEEN_PROVISIONED = "User has not been provisioned!";
+    private static final String DEVICE_HAS_BEEN_CLEARED = "Device has been cleared!";
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private DevicePolicyController mMockDevicePolicyController;
+
+    @Mock
+    private ProvisionStateController mMockProvisionStateController;
+
+    private DeviceStateController mDeviceStateController;
+
+    @Before
+    public void setUp() {
+        mDeviceStateController = new DeviceStateControllerImpl(mMockDevicePolicyController,
+                mMockProvisionStateController, Executors.newSingleThreadExecutor());
+    }
+
+    @Test
+    public void lockDevice_withUnprovisionedState_shouldPseudoLockDevice()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.UNPROVISIONED));
+        mDeviceStateController.lockDevice().get();
+
+        assertThat(mDeviceStateController.isLocked().get()).isTrue();
+
+        // Should not have changed the real device state
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void lockDevice_withProvisionInProgressState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_IN_PROGRESS));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.lockDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void lockDevice_withProvisionPausedState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_PAUSED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.lockDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void lockDevice_withProvisionFailedState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_FAILED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.lockDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void lockDevice_withKioskProvisionedState_shouldLockDevice()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.KIOSK_PROVISIONED));
+        when(mMockDevicePolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.setNextStateForEvent(
+                eq(ProvisionEvent.PROVISION_SUCCESS))).thenReturn(
+                Futures.immediateVoidFuture());
+        mDeviceStateController.lockDevice().get();
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.LOCKED);
+    }
+
+    @Test
+    public void lockDevice_withClearDeviceState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_SUCCEEDED));
+        GlobalParametersClient globalParametersClient = GlobalParametersClient.getInstance();
+        globalParametersClient.setDeviceState(DeviceState.CLEARED).get();
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.lockDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(DEVICE_HAS_BEEN_CLEARED);
+        assertThat(mDeviceStateController.isLocked().get()).isFalse();
+    }
+
+    @Test
+    public void lockDevice_withProvisionSucceededState_shouldLockDevice()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockDevicePolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        mDeviceStateController.lockDevice().get();
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.LOCKED);
+        assertThat(mDeviceStateController.isLocked().get()).isTrue();
+    }
+
+    @Test
+    public void unlockDevice_withKioskProvisionedState_shouldUnlockDevice()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.KIOSK_PROVISIONED));
+        when(mMockDevicePolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.setNextStateForEvent(
+                eq(ProvisionEvent.PROVISION_SUCCESS))).thenReturn(
+                Futures.immediateVoidFuture());
+        mDeviceStateController.unlockDevice().get();
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNLOCKED);
+    }
+
+    @Test
+    public void unlockDevice_withUnprovisionedState_shouldPseudoUnlock()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.UNPROVISIONED));
+        mDeviceStateController.unlockDevice().get();
+
+        assertThat(mDeviceStateController.isLocked().get()).isFalse();
+
+        // Should not have changed the real device state
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void unlockDevice_withProvisionInProgressState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_IN_PROGRESS));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.unlockDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void unlockDevice_withProvisionPausedState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_PAUSED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.unlockDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void unlockDevice_withProvisionFailedState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_FAILED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.unlockDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void unlockDevice_withClearDeviceState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_SUCCEEDED));
+        GlobalParametersClient globalParametersClient = GlobalParametersClient.getInstance();
+        globalParametersClient.setDeviceState(DeviceState.CLEARED).get();
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.unlockDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(DEVICE_HAS_BEEN_CLEARED);
+    }
+
+    @Test
+    public void unlockDevice_withProvisionSucceeded_shouldUnlockDevice()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockDevicePolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        mDeviceStateController.unlockDevice().get();
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNLOCKED);
+        assertThat(mDeviceStateController.isLocked().get()).isFalse();
+    }
+
+    @Test
+    public void clearDevice_withUnprovisionedState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.UNPROVISIONED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.clearDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void clearDevice_withProvisionInProgressState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_IN_PROGRESS));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.clearDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void clearDevice_withProvisionPausedState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_PAUSED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.clearDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void clearDevice_withProvisionFailedState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_FAILED));
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.clearDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(USER_HAS_NOT_BEEN_PROVISIONED);
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.UNDEFINED);
+    }
+
+    @Test
+    public void clearDevice_withKioskProvisionedState_shouldClearDevice()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.KIOSK_PROVISIONED));
+        when(mMockDevicePolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockProvisionStateController.setNextStateForEvent(
+                eq(ProvisionEvent.PROVISION_SUCCESS))).thenReturn(
+                Futures.immediateVoidFuture());
+        mDeviceStateController.clearDevice().get();
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.CLEARED);
+    }
+
+    @Test
+    public void clearDevice_withClearDeviceState_shouldThrowException()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_SUCCEEDED));
+        GlobalParametersClient globalParametersClient = GlobalParametersClient.getInstance();
+        globalParametersClient.setDeviceState(DeviceState.CLEARED).get();
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mDeviceStateController.clearDevice().get());
+        assertThat(thrown).hasCauseThat().isInstanceOf(RuntimeException.class);
+        assertThat(thrown).hasMessageThat().contains(DEVICE_HAS_BEEN_CLEARED);
+    }
+
+    @Test
+    public void clearDevice_withProvisionSucceeded_shouldUnlockDevice()
+            throws ExecutionException, InterruptedException {
+        when(mMockProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(ProvisionState.PROVISION_SUCCEEDED));
+        when(mMockDevicePolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        mDeviceStateController.clearDevice().get();
+
+        assertThat(GlobalParametersClient.getInstance().getDeviceState().get()).isEqualTo(
+                DeviceState.CLEARED);
+    }
+
+    @Test
+    public void getDeviceState_shouldReturnResultFromGlobalParametersClient()
+            throws ExecutionException, InterruptedException {
+        GlobalParametersClient globalParametersClient = GlobalParametersClient.getInstance();
+        globalParametersClient.setDeviceState(DeviceState.UNLOCKED).get();
+
+        int deviceState = mDeviceStateController.getDeviceState().get();
+
+        assertThat(deviceState).isEqualTo(DeviceState.UNLOCKED);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/DeviceStateControllerStateTransitionTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/DeviceStateControllerStateTransitionTest.java
deleted file mode 100644
index 9de18fb..0000000
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/DeviceStateControllerStateTransitionTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
-
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.CLEAR;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.LOCK_DEVICE;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.PROVISIONING_SUCCESS;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.SETUP_COMPLETE;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.SETUP_FAILURE;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.SETUP_SUCCESS;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.UNLOCK_DEVICE;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.KIOSK_SETUP;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_LOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.PSEUDO_UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_FAILED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_IN_PROGRESS;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.SETUP_SUCCEEDED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNPROVISIONED;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
-import com.android.devicelockcontroller.storage.UserParameters;
-
-import com.google.common.truth.Truth;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.ParameterizedRobolectricTestRunner;
-
-import java.util.Arrays;
-import java.util.List;
-
-@RunWith(ParameterizedRobolectricTestRunner.class)
-public class DeviceStateControllerStateTransitionTest {
-    private DeviceStateControllerImpl mDeviceStateController;
-
-    @ParameterizedRobolectricTestRunner.Parameter
-    @DeviceStateController.DeviceState
-    public int mState;
-
-    @ParameterizedRobolectricTestRunner.Parameter(1)
-    @DeviceStateController.DeviceEvent
-    public int mEvent;
-
-    @ParameterizedRobolectricTestRunner.Parameter(2)
-    @DeviceStateController.DeviceState
-    public int mNextState;
-
-    @ParameterizedRobolectricTestRunner.Parameters(name =
-            "Transition from {0} to {2} when {1} event happens")
-    public static List<Object[]> parameters() {
-        return Arrays.asList(new Object[][]{
-                {UNPROVISIONED, PROVISIONING_SUCCESS, SETUP_IN_PROGRESS},
-                {SETUP_FAILED, PROVISIONING_SUCCESS, SETUP_IN_PROGRESS},
-                {UNPROVISIONED, LOCK_DEVICE, PSEUDO_LOCKED},
-                {SETUP_IN_PROGRESS, SETUP_SUCCESS, SETUP_SUCCEEDED},
-                {SETUP_IN_PROGRESS, SETUP_FAILURE, SETUP_FAILED},
-                {SETUP_SUCCEEDED, SETUP_COMPLETE, KIOSK_SETUP},
-                {KIOSK_SETUP, UNLOCK_DEVICE, UNLOCKED},
-                {KIOSK_SETUP, CLEAR, CLEARED},
-                {UNLOCKED, LOCK_DEVICE, LOCKED},
-                {UNLOCKED, UNLOCK_DEVICE, UNLOCKED},
-                {UNLOCKED, CLEAR, CLEARED},
-                {LOCKED, UNLOCK_DEVICE, UNLOCKED},
-                {LOCKED, LOCK_DEVICE, LOCKED},
-                {LOCKED, CLEAR, CLEARED},
-                {PSEUDO_LOCKED, UNLOCK_DEVICE, PSEUDO_UNLOCKED},
-                {PSEUDO_LOCKED, LOCK_DEVICE, PSEUDO_LOCKED},
-                {PSEUDO_LOCKED, PROVISIONING_SUCCESS, SETUP_IN_PROGRESS},
-                {PSEUDO_UNLOCKED, LOCK_DEVICE, PSEUDO_LOCKED},
-                {PSEUDO_UNLOCKED, UNLOCK_DEVICE, PSEUDO_UNLOCKED},
-                {PSEUDO_UNLOCKED, PROVISIONING_SUCCESS, SETUP_IN_PROGRESS}
-        });
-    }
-
-
-    @Before
-    public void setup() {
-        TestDeviceLockControllerApplication testApplication =
-                ApplicationProvider.getApplicationContext();
-        UserParameters.setDeviceState(testApplication, mState);
-        mDeviceStateController = new DeviceStateControllerImpl(testApplication);
-    }
-
-    @Test
-    public void testGetNextState() throws StateTransitionException {
-        Truth.assertThat(mDeviceStateController.getNextState(mEvent)).isEqualTo(mNextState);
-    }
-}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/FinalizationControllerImplTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/FinalizationControllerImplTest.java
new file mode 100644
index 0000000..9f0a070
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/FinalizationControllerImplTest.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.FINALIZED;
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.FINALIZED_UNREPORTED;
+import static com.android.devicelockcontroller.provision.worker.ReportDeviceLockProgramCompleteWorker.REPORT_DEVICE_LOCK_PROGRAM_COMPLETE_WORK_NAME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.OutcomeReceiver;
+
+import androidx.annotation.NonNull;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.work.ListenableWorker;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+import androidx.work.WorkerParameters;
+import androidx.work.testing.WorkManagerTestInitHelper;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+import com.android.devicelockcontroller.provision.grpc.DeviceFinalizeClient.ReportDeviceProgramCompleteResponse;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+
+import com.google.common.util.concurrent.ExecutionSequencer;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(RobolectricTestRunner.class)
+public final class FinalizationControllerImplTest {
+
+    private static final int TIMEOUT_MS = 1000;
+
+    private final SystemDeviceLockManager mSystemDeviceLockManager =
+            new TestSystemDeviceLockManager();
+    private Context mContext;
+    private FinalizationControllerImpl mFinalizationController;
+    private FinalizationStateDispatchQueue mDispatchQueue;
+    private final ExecutionSequencer mExecutionSequencer = ExecutionSequencer.create();
+    private final Executor mBgExecutor = Executors.newCachedThreadPool();
+    private GlobalParametersClient mGlobalParametersClient;
+
+    @Before
+    public void setUp() {
+        mContext = ApplicationProvider.getApplicationContext();
+        WorkManagerTestInitHelper.initializeTestWorkManager(mContext);
+
+        mGlobalParametersClient = GlobalParametersClient.getInstance();
+        mDispatchQueue = new FinalizationStateDispatchQueue(mExecutionSequencer);
+    }
+
+    @Test
+    public void notifyRestrictionsCleared_startsReportingWork() throws Exception {
+        mFinalizationController = makeFinalizationController();
+
+        // WHEN restrictions are cleared
+        ListenableFuture<Void> clearedFuture =
+                mFinalizationController.notifyRestrictionsCleared();
+        Futures.getChecked(clearedFuture, Exception.class, TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
+        // THEN work manager has work scheduled to report the device is finalized and the disk
+        // value is set to unreported
+        ListenableFuture<List<WorkInfo>> workInfosFuture = WorkManager.getInstance(mContext)
+                .getWorkInfosForUniqueWork(REPORT_DEVICE_LOCK_PROGRAM_COMPLETE_WORK_NAME);
+        List<WorkInfo> workInfos = Futures.getChecked(workInfosFuture, Exception.class);
+        assertThat(workInfos).isNotEmpty();
+        assertThat(mGlobalParametersClient.getFinalizationState().get())
+                .isEqualTo(FINALIZED_UNREPORTED);
+    }
+
+    @Test
+    public void reportingFinishedSuccessfully_fullyFinalizes() throws Exception {
+        mFinalizationController = makeFinalizationController();
+
+        // GIVEN the restrictions have been requested to clear
+        ListenableFuture<Void> clearedFuture =
+                mFinalizationController.notifyRestrictionsCleared();
+        Futures.getChecked(clearedFuture, Exception.class, TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
+        // WHEN the work is reported successfully
+        ReportDeviceProgramCompleteResponse successResponse =
+                new ReportDeviceProgramCompleteResponse();
+        ListenableFuture<Void> reportedFuture =
+                mFinalizationController.notifyFinalizationReportResult(successResponse);
+        Futures.getChecked(reportedFuture, Exception.class, TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
+        // THEN the disk value is set to finalized
+        assertThat(mGlobalParametersClient.getFinalizationState().get()).isEqualTo(FINALIZED);
+    }
+
+    @Test
+    public void unreportedStateInitializedFromDisk_reportsWork() throws Exception {
+        // GIVEN the state on disk is unreported
+        Futures.getChecked(
+                mGlobalParametersClient.setFinalizationState(FINALIZED_UNREPORTED),
+                Exception.class);
+
+        // WHEN the controller is initialized
+        mFinalizationController = makeFinalizationController();
+        Futures.getChecked(mFinalizationController.enforceInitialState(), Exception.class,
+                TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
+        // THEN the state from disk is used and is applied immediately, reporting the work.
+        ListenableFuture<List<WorkInfo>> workInfosFuture = WorkManager.getInstance(mContext)
+                .getWorkInfosForUniqueWork(REPORT_DEVICE_LOCK_PROGRAM_COMPLETE_WORK_NAME);
+        List<WorkInfo> workInfos = Futures.getChecked(workInfosFuture, Exception.class);
+        assertThat(workInfos).isNotEmpty();
+    }
+
+    private FinalizationControllerImpl makeFinalizationController() {
+        return new FinalizationControllerImpl(
+                mContext, mDispatchQueue, mBgExecutor, TestWorker.class, mSystemDeviceLockManager);
+    }
+
+    private static final class TestSystemDeviceLockManager implements SystemDeviceLockManager {
+
+        @Override
+        public void addFinancedDeviceKioskRole(@NonNull String packageName, Executor executor,
+                @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+
+        @Override
+        public void removeFinancedDeviceKioskRole(@NonNull String packageName, Executor executor,
+                @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+
+        @Override
+        public void setDlcExemptFromActivityBgStartRestrictionState(boolean exempt,
+                Executor executor, @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+
+        @Override
+        public void setDlcAllowedToSendUndismissibleNotifications(boolean allowed,
+                Executor executor, @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+
+        @Override
+        public void setKioskAppExemptFromRestrictionsState(String packageName, boolean exempt,
+                Executor executor, @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+
+        @Override
+        public void enableKioskKeepalive(String packageName, Executor executor,
+                @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+
+        @Override
+        public void disableKioskKeepalive(Executor executor,
+                @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+
+        @Override
+        public void enableControllerKeepalive(Executor executor,
+                @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+
+        @Override
+        public void disableControllerKeepalive(Executor executor,
+                @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+
+        @Override
+        public void setDeviceFinalized(boolean finalized, Executor executor,
+                @NonNull OutcomeReceiver<Void, Exception> callback) {
+            executor.execute(() -> callback.onResult(null));
+        }
+
+        @Override
+        public void setPostNotificationsSystemFixed(boolean systemFixed, Executor executor,
+                @NonNull OutcomeReceiver<Void, Exception> callback) {
+
+        }
+    }
+
+    /**
+     * Fake test worker that just finishes work immediately
+     */
+    private static final class TestWorker extends ListenableWorker {
+
+        TestWorker(@NonNull Context appContext, @NonNull WorkerParameters workerParams) {
+            super(appContext, workerParams);
+        }
+
+        @NonNull
+        @Override
+        public ListenableFuture<Result> startWork() {
+            return Futures.immediateFuture(Result.success());
+        }
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/InstallExistingPackageTaskTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/InstallExistingPackageTaskTest.java
deleted file mode 100644
index 63a5c7b..0000000
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/InstallExistingPackageTaskTest.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
-
-import static android.content.pm.PackageInstaller.EXTRA_STATUS;
-import static android.content.pm.PackageInstaller.STATUS_FAILURE;
-import static android.content.pm.PackageInstaller.STATUS_SUCCESS;
-import static android.util.Log.VERBOSE;
-
-import static androidx.work.WorkInfo.State.FAILED;
-import static androidx.work.WorkInfo.State.SUCCEEDED;
-
-import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
-import static com.android.devicelockcontroller.policy.AbstractTask.ERROR_CODE_GET_PENDING_INTENT_FAILED;
-import static com.android.devicelockcontroller.policy.AbstractTask.ERROR_CODE_INSTALLATION_FAILED;
-import static com.android.devicelockcontroller.policy.AbstractTask.ERROR_CODE_NO_PACKAGE_NAME;
-import static com.android.devicelockcontroller.policy.AbstractTask.TASK_RESULT_ERROR_CODE_KEY;
-import static com.android.devicelockcontroller.policy.InstallExistingPackageTask.ACTION_INSTALL_EXISTING_APP_COMPLETE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Application;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.os.Looper;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.work.Configuration;
-import androidx.work.Data;
-import androidx.work.ListenableWorker;
-import androidx.work.OneTimeWorkRequest;
-import androidx.work.WorkInfo;
-import androidx.work.WorkManager;
-import androidx.work.WorkerFactory;
-import androidx.work.WorkerParameters;
-import androidx.work.testing.WorkManagerTestInitHelper;
-
-import com.android.devicelockcontroller.policy.InstallExistingPackageTask.InstallExistingPackageCompleteBroadcastReceiver;
-import com.android.devicelockcontroller.policy.InstallExistingPackageTask.PackageInstallPendingIntentProvider;
-import com.android.devicelockcontroller.policy.InstallExistingPackageTask.PackageInstallPendingIntentProviderImpl;
-import com.android.devicelockcontroller.policy.InstallExistingPackageTask.PackageInstallerWrapper;
-
-import com.google.common.util.concurrent.MoreExecutors;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.Shadows;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.shadows.ShadowContextWrapper;
-
-import java.util.concurrent.ExecutionException;
-
-@RunWith(RobolectricTestRunner.class)
-public final class InstallExistingPackageTaskTest {
-    @Rule
-    public final MockitoRule mMocks = MockitoJUnit.rule();
-    @Mock
-    private PackageInstallerWrapper mMockPackageInstaller;
-    @Mock
-    private PackageInstallPendingIntentProvider mMockPackageInstallPendingIntentProvider;
-
-    private Context mContext;
-    private WorkManager mWorkManager;
-    private final InstallExistingPackageCompleteBroadcastReceiver mFakeBroadcastReceiver =
-            new InstallExistingPackageCompleteBroadcastReceiver(mContext);
-    private ShadowApplication mShadowApplication;
-
-    @Before
-    public void setup() throws Exception {
-        mContext = ApplicationProvider.getApplicationContext();
-        mShadowApplication = Shadows.shadowOf((Application) mContext);
-
-        when(mMockPackageInstallPendingIntentProvider.get()).thenReturn(
-                new PackageInstallPendingIntentProviderImpl(mContext).get());
-
-        final Configuration config =
-                new Configuration.Builder()
-                        .setMinimumLoggingLevel(VERBOSE)
-                        .setWorkerFactory(
-                                new WorkerFactory() {
-                                    @Override
-                                    public ListenableWorker createWorker(
-                                            Context context, String workerClassName,
-                                            WorkerParameters workerParameters) {
-                                        return new InstallExistingPackageTask(
-                                                context,
-                                                workerParameters,
-                                                MoreExecutors.newDirectExecutorService(),
-                                                mFakeBroadcastReceiver,
-                                                mMockPackageInstaller,
-                                                mMockPackageInstallPendingIntentProvider);
-                                    }
-                                })
-                        .build();
-        WorkManagerTestInitHelper.initializeTestWorkManager(mContext, config);
-        mWorkManager = WorkManager.getInstance(mContext);
-    }
-
-    @Test
-    public void testInstallExistingPackageCompleteBroadcastReceiver_StatusSuccess()
-            throws ExecutionException, InterruptedException {
-        // WHEN register the receiver and send an installation success broadcast
-        registerReceiverWithStatus(STATUS_SUCCESS);
-
-        // THEN the receiver should be unregistered
-        assertThat(mShadowApplication.getRegisteredReceivers()).isEmpty();
-        assertThat(mFakeBroadcastReceiver.getFuture().isDone()).isTrue();
-        assertThat(mFakeBroadcastReceiver.getFuture().get()).isTrue();
-    }
-
-
-    /*
-     * The broadcast should never return anything other than STATUS_SUCCESS in response
-     * to installExistingPackage().
-     * Here we test what would happen if we receive something unexpected.
-     */
-    @Test
-    public void testInstallExistingPackageCompleteBroadcastReceiver_StatusFailure()
-            throws ExecutionException, InterruptedException {
-        // WHEN register the receiver and send an installation failure broadcast
-        registerReceiverWithStatus(STATUS_FAILURE);
-
-        // THEN the receiver should be unregistered
-        assertThat(mShadowApplication.getRegisteredReceivers()).isEmpty();
-        assertThat(mFakeBroadcastReceiver.getFuture().isDone()).isTrue();
-        assertThat(mFakeBroadcastReceiver.getFuture().get()).isFalse();
-    }
-
-    @Test
-    public void testInstallExistingPackage_PackageNameIsNull() {
-        // GIVEN the package name is null
-        final WorkInfo workInfo = buildTaskAndRun(mWorkManager, /* packageName */ null);
-
-        // THEN task failed
-        assertThat(workInfo.getState()).isEqualTo(FAILED);
-        assertThat(workInfo.getOutputData().getInt(TASK_RESULT_ERROR_CODE_KEY,
-                /* defaultValue */ -1)).isEqualTo(ERROR_CODE_NO_PACKAGE_NAME);
-    }
-
-    @Test
-    public void testInstallExistingPackage_PackageNameIsEmpty() {
-        // GIVEN the file location is empty
-        final WorkInfo workInfo = buildTaskAndRun(mWorkManager, /* packageName */ "");
-
-        // THEN task failed
-        assertThat(workInfo.getState()).isEqualTo(FAILED);
-        assertThat(workInfo.getOutputData().getInt(TASK_RESULT_ERROR_CODE_KEY,
-                /* defaultValue */ -1)).isEqualTo(ERROR_CODE_NO_PACKAGE_NAME);
-    }
-
-
-    @Test
-    public void testInstall_Succeed() {
-        // GIVEN
-        mShadowApplication.clearRegisteredReceivers();
-        // GIVEN the installation completes with success
-        mFakeBroadcastReceiver.mFuture.set(true);
-
-        // WHEN
-        final WorkInfo workInfo = buildTaskAndRun(mWorkManager);
-
-        // THEN
-        verifyPackageInstalled();
-        assertThat(workInfo.getState()).isEqualTo(SUCCEEDED);
-    }
-
-    @Test
-    public void testInstall_BroadcastReceiverReturnedFalse_Failed() {
-        // GIVEN
-        mShadowApplication.clearRegisteredReceivers();
-        // GIVEN the installation completes with failure
-        mFakeBroadcastReceiver.mFuture.set(false);
-
-        // WHEN
-        final WorkInfo workInfo = buildTaskAndRun(mWorkManager);
-
-        // THEN
-        verifyPackageInstalled();
-        assertThat(workInfo.getState()).isEqualTo(FAILED);
-        assertThat(workInfo.getOutputData().getInt(TASK_RESULT_ERROR_CODE_KEY,
-                /* defaultValue */ -1)).isEqualTo(ERROR_CODE_INSTALLATION_FAILED);
-    }
-
-    @Test
-    public void testInstall_withNullPendingIntent_fails() {
-        when(mMockPackageInstallPendingIntentProvider.get()).thenReturn(null);
-
-        // WHEN run install package task
-        final WorkInfo workInfo = buildTaskAndRun(mWorkManager);
-
-        // THEN
-        assertThat(workInfo.getState()).isEqualTo(FAILED);
-        assertThat(workInfo.getOutputData().getInt(TASK_RESULT_ERROR_CODE_KEY,
-                /* defaultValue */ -1)).isEqualTo(ERROR_CODE_GET_PENDING_INTENT_FAILED);
-    }
-
-    private void verifyPackageInstalled() {
-        // THEN a BroadcastReceiver should be registered
-        assertThat(mShadowApplication.getRegisteredReceivers()).hasSize(1);
-        assertThat(mShadowApplication.getRegisteredReceivers().get(0).getBroadcastReceiver())
-                .isEqualTo(mFakeBroadcastReceiver);
-        verify(mMockPackageInstaller).installExistingPackage(anyString(), anyInt(),
-                any(IntentSender.class));
-    }
-
-    private WorkInfo buildTaskAndRun(WorkManager workManager, String packageName) {
-        // GIVEN
-        final Data data = new Data.Builder().putString(EXTRA_KIOSK_PACKAGE, packageName).build();
-
-
-        // WHEN
-        final OneTimeWorkRequest request =
-                new OneTimeWorkRequest.Builder(InstallExistingPackageTask.class).setInputData(data)
-                        .build();
-        workManager.enqueue(request);
-
-        try {
-            return workManager.getWorkInfoById(request.getId()).get();
-        } catch (ExecutionException | InterruptedException e) {
-            throw new AssertionError("Exception", e);
-        }
-    }
-
-    private WorkInfo buildTaskAndRun(WorkManager workManager) {
-        final String kioskPackageName = "com.example.kiosk";
-        return buildTaskAndRun(workManager, kioskPackageName);
-    }
-
-    private void registerReceiverWithStatus(int status) {
-        // GIVEN clear BroadcastReceivers and Broadcast intents
-        mShadowApplication.clearRegisteredReceivers();
-        final ShadowContextWrapper shadowContextWrapper =
-                Shadows.shadowOf((ContextWrapper) mContext);
-        shadowContextWrapper.clearBroadcastIntents();
-
-        // WHEN
-        mContext.registerReceiver(mFakeBroadcastReceiver,
-                new IntentFilter(ACTION_INSTALL_EXISTING_APP_COMPLETE));
-
-        // THEN
-        assertThat(mShadowApplication.getRegisteredReceivers()).hasSize(1);
-        assertThat(mShadowApplication.getRegisteredReceivers().get(0).getBroadcastReceiver())
-                .isEqualTo(mFakeBroadcastReceiver);
-
-        // WHEN send intent with status
-        final Intent intent = new Intent(ACTION_INSTALL_EXISTING_APP_COMPLETE);
-        intent.putExtra(EXTRA_STATUS, status);
-        mContext.sendBroadcast(intent);
-
-        Shadows.shadowOf(Looper.getMainLooper()).idle();
-        // THEN make sure broadcast intent has correct contents
-        assertThat(shadowContextWrapper.getBroadcastIntents()).hasSize(1);
-        final Intent receivedIntent = shadowContextWrapper.getBroadcastIntents().get(0);
-        assertThat(receivedIntent.getAction()).isEqualTo(ACTION_INSTALL_EXISTING_APP_COMPLETE);
-        assertThat(receivedIntent.getExtras().getInt(EXTRA_STATUS)).isEqualTo(status);
-    }
-}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/KioskKeepAlivePolicyHandlerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/KioskKeepAlivePolicyHandlerTest.java
new file mode 100644
index 0000000..65858c4
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/KioskKeepAlivePolicyHandlerTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+import android.os.Bundle;
+import android.os.OutcomeReceiver;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class KioskKeepAlivePolicyHandlerTest {
+    private static final String TEST_KIOSK_PACKAGE = "test.package1";
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private SystemDeviceLockManager mSystemDeviceLockManager;
+    private KioskKeepAlivePolicyHandler mHandler;
+
+    @Before
+    public void setUp() throws ExecutionException, InterruptedException {
+        mHandler = new KioskKeepAlivePolicyHandler(mSystemDeviceLockManager,
+                Executors.newSingleThreadExecutor());
+        setupSetupParameters();
+    }
+
+    @Test
+    public void onProvisioned_enablesKioskKeepalive()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnEnableKioskKeepalive(/* isSuccess =*/ true);
+        assertThat(mHandler.onProvisioned().get()).isTrue();
+        verify(mSystemDeviceLockManager).enableKioskKeepalive(eq(TEST_KIOSK_PACKAGE),
+                any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).disableKioskKeepalive(any(Executor.class), any());
+    }
+
+    @Test
+    public void onProvisioned_onFailure_stillReturnsTrue()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnEnableKioskKeepalive(/* isSuccess =*/ false);
+        assertThat(mHandler.onProvisioned().get()).isTrue();
+        verify(mSystemDeviceLockManager).enableKioskKeepalive(eq(TEST_KIOSK_PACKAGE),
+                any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).disableKioskKeepalive(any(Executor.class), any());
+    }
+
+    @Test
+    public void onCleared_disablesKioskKeepalive()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnDisableKioskKeepalive(/* isSuccess =*/ true);
+        assertThat(mHandler.onCleared().get()).isTrue();
+        verify(mSystemDeviceLockManager).disableKioskKeepalive(any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).enableKioskKeepalive(eq(TEST_KIOSK_PACKAGE),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onCleared_onFailure_stillReturnsTrue()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnDisableKioskKeepalive(/* isSuccess =*/ false);
+        assertThat(mHandler.onCleared().get()).isTrue();
+        verify(mSystemDeviceLockManager).disableKioskKeepalive(any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).enableKioskKeepalive(eq(TEST_KIOSK_PACKAGE),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onProvisionInProgress_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionInProgress().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onProvisionPaused_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionPaused().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onProvisionFailed_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionFailed().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onLocked_shouldDoNothing() throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onLocked().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onUnlocked_shouldDoNothing() throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onUnlocked().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    private void setExpectationsOnEnableKioskKeepalive(boolean isSuccess) {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 2);
+            if (isSuccess) {
+                callback.onResult(/* result =*/ null);
+            } else {
+                callback.onError(new Exception());
+            }
+            return null;
+        }).when(mSystemDeviceLockManager).enableKioskKeepalive(anyString(),
+                any(Executor.class), any());
+    }
+
+
+    private void setExpectationsOnDisableKioskKeepalive(boolean isSuccess) {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 1);
+            if (isSuccess) {
+                callback.onResult(/* result =*/ null);
+            } else {
+                callback.onError(new Exception());
+            }
+            return null;
+        }).when(mSystemDeviceLockManager).disableKioskKeepalive(any(Executor.class), any());
+    }
+
+    private static void setupSetupParameters() throws InterruptedException, ExecutionException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_KIOSK_PACKAGE);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/LockTaskModePolicyHandlerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/LockTaskModePolicyHandlerTest.java
new file mode 100644
index 0000000..3fcd511
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/LockTaskModePolicyHandlerTest.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST;
+import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_ALLOWLIST;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Looper;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.provider.Telephony;
+import android.telecom.TelecomManager;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.core.content.pm.ApplicationInfoBuilder;
+import androidx.test.core.content.pm.PackageInfoBuilder;
+import androidx.work.testing.WorkManagerTestInitHelper;
+
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+import com.android.devicelockcontroller.storage.UserParameters;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowPackageManager;
+import org.robolectric.shadows.ShadowTelecomManager;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class LockTaskModePolicyHandlerTest {
+    private static final String TEST_PACKAGE = "test.package1";
+    private static final String DIALER_PACKAGE = "test.dialer";
+    private static final String SETTINGS_PACKAGE = "test.settings";
+    private static final String PERMISSION_PACKAGE = "test.permissions";
+    private static final String DEVICELOCK_CONTROLLER_PACKAGE = "com.android.devicelockcontroller";
+    private static final String PACKAGE_OVERRIDING_HOME = "com.home.package";
+    private static final String[] EXPECTED_ALLOWLIST_PACKAGES =
+            new String[]{TEST_PACKAGE, SETTINGS_PACKAGE, DIALER_PACKAGE,
+                    DEVICELOCK_CONTROLLER_PACKAGE};
+    private static final String TEST_ACTIVITY = "TestActivity";
+    private static final String CELL_BROADCAST_RECEIVER_PACKAGE =
+            "test.cell.broadcast.receiver";
+    private static final String IME_PACKAGE = "test.ime";
+    private static final String IME_COMPONENT = IME_PACKAGE + "/.inputmethod";
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Mock
+    private DevicePolicyManager mMockDpm;
+    @Captor
+    private ArgumentCaptor<Integer> mAllowedFeatures;
+    @Captor
+    private ArgumentCaptor<String[]> mAllowedPackages;
+
+    private ShadowTelecomManager mTelecomManager;
+    private LockTaskModePolicyHandler mHandler;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = ApplicationProvider.getApplicationContext();
+        WorkManagerTestInitHelper.initializeTestWorkManager(mContext);
+        mTelecomManager = Shadow.extract(mContext.getSystemService(TelecomManager.class));
+        mHandler = new LockTaskModePolicyHandler(mContext, mMockDpm,
+                Executors.newSingleThreadExecutor());
+    }
+
+    @Test
+    public void onProvisionInProgress_shouldHaveExpectedLockTaskFeaturesAndPackages()
+            throws ExecutionException, InterruptedException {
+        final String[] expectedAllowlistPackages = {DEVICELOCK_CONTROLLER_PACKAGE};
+        mHandler.onProvisionInProgress().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskMode(LockTaskModePolicyHandler.DEFAULT_LOCK_TASK_FEATURES_FOR_DLC,
+                expectedAllowlistPackages);
+    }
+
+    @Test
+    public void onProvisionInProgress_shouldHaveDefaultDialerInExpectedLockTaskPackages()
+            throws ExecutionException, InterruptedException {
+        final String[] expectedAllowlistPackages = {DIALER_PACKAGE, DEVICELOCK_CONTROLLER_PACKAGE};
+        mTelecomManager.setDefaultDialer(DIALER_PACKAGE);
+        mHandler.onProvisionInProgress().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskMode(LockTaskModePolicyHandler.DEFAULT_LOCK_TASK_FEATURES_FOR_DLC,
+                expectedAllowlistPackages);
+    }
+
+    @Test
+    public void onProvisioned_shouldHaveNonDuplicateLockTaskFeaturesAndPackages()
+            throws ExecutionException, InterruptedException {
+        setupKioskAllowListWithDuplicates();
+        mHandler.onProvisioned().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskMode(LockTaskModePolicyHandler.DEFAULT_LOCK_TASK_FEATURES_FOR_KIOSK,
+                EXPECTED_ALLOWLIST_PACKAGES);
+    }
+
+    @Test
+    public void onProvisionPaused_shouldDisableLockTaskMode()
+            throws ExecutionException, InterruptedException {
+        mHandler.onProvisionPaused().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertDisableLockTaskMode();
+    }
+
+    @Test
+    public void onProvisionFailed_shouldDisableLockTaskMode()
+            throws ExecutionException, InterruptedException {
+        mHandler.onProvisionFailed().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertDisableLockTaskMode();
+    }
+
+    @Test
+    public void onLocked_shouldHaveNonDuplicateLockTaskFeaturesAndPackages()
+            throws ExecutionException, InterruptedException {
+        setupKioskAllowListWithDuplicates();
+        mTelecomManager.setDefaultDialer(DIALER_PACKAGE);
+        mHandler.onLocked().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskMode(LockTaskModePolicyHandler.DEFAULT_LOCK_TASK_FEATURES_FOR_KIOSK,
+                EXPECTED_ALLOWLIST_PACKAGES);
+    }
+
+    @Test
+    public void onLocked_withDefaultSystemPackages_shouldHaveExpectedLockTaskFeaturesAndPackages()
+            throws ExecutionException, InterruptedException {
+        final String[] expectedAllowlistPackages =
+                new String[]{TEST_PACKAGE, SETTINGS_PACKAGE, DIALER_PACKAGE, IME_PACKAGE,
+                        PERMISSION_PACKAGE, CELL_BROADCAST_RECEIVER_PACKAGE,
+                        DEVICELOCK_CONTROLLER_PACKAGE};
+        Bundle bundle = new Bundle();
+        bundle.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        SetupParametersClient.getInstance().createPrefs(bundle).get();
+        setupDefaultSystemPackages();
+        mHandler.onLocked().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertLockTaskMode(LockTaskModePolicyHandler.DEFAULT_LOCK_TASK_FEATURES_FOR_KIOSK,
+                expectedAllowlistPackages);
+    }
+
+    @Test
+    public void onUnlocked_shouldDisableLockTaskMode()
+            throws ExecutionException, InterruptedException {
+        mHandler.onUnlocked().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertDisableLockTaskMode();
+    }
+
+    @Test
+    public void onCleared_shouldDisableLockTaskMode()
+            throws ExecutionException, InterruptedException {
+        mHandler.onCleared().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertDisableLockTaskMode();
+        verify(mMockDpm, times(0)).clearPackagePersistentPreferredActivities(eq(null),
+                eq(PACKAGE_OVERRIDING_HOME));
+    }
+
+    @Test
+    public void onUnlocked_withHomePackageOverride_shouldDisableLockTaskMode()
+            throws ExecutionException, InterruptedException {
+        UserParameters.setPackageOverridingHome(mContext, PACKAGE_OVERRIDING_HOME);
+        mHandler.onProvisionFailed().get();
+        shadowOf(Looper.getMainLooper()).idle();
+        assertDisableLockTaskMode();
+
+        verify(mMockDpm).clearPackagePersistentPreferredActivities(eq(null),
+                eq(PACKAGE_OVERRIDING_HOME));
+        Executors.newSingleThreadExecutor().submit(() -> {
+            assertThat(UserParameters.getPackageOverridingHome(mContext)).isNull();
+        }).get();
+    }
+
+    private void setupDefaultSystemPackages() {
+        ShadowPackageManager shadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
+
+        IntentFilter dialerIntent = new IntentFilter(Intent.ACTION_DIAL);
+        dialerIntent.addCategory(Intent.CATEGORY_DEFAULT);
+        ComponentName dialerComponent = new ComponentName(DIALER_PACKAGE, TEST_ACTIVITY);
+
+        PackageInfo dialerPackage =
+                PackageInfoBuilder.newBuilder()
+                        .setPackageName(DIALER_PACKAGE)
+                        .setApplicationInfo(
+                                ApplicationInfoBuilder.newBuilder()
+                                        .setName(DIALER_PACKAGE)
+                                        .setPackageName(DIALER_PACKAGE)
+                                        .build())
+                        .build();
+        dialerPackage.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        shadowPackageManager.installPackage(dialerPackage);
+        shadowPackageManager.addActivityIfNotPresent(dialerComponent);
+        shadowPackageManager.addIntentFilterForActivity(dialerComponent, dialerIntent);
+
+        IntentFilter settingsIntent = new IntentFilter(Settings.ACTION_SETTINGS);
+        settingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
+        ComponentName settingsComponent = new ComponentName(SETTINGS_PACKAGE, TEST_ACTIVITY);
+
+        PackageInfo settingsPackage =
+                PackageInfoBuilder.newBuilder()
+                        .setPackageName(SETTINGS_PACKAGE)
+                        .setApplicationInfo(
+                                ApplicationInfoBuilder.newBuilder()
+                                        .setName(SETTINGS_PACKAGE)
+                                        .setPackageName(SETTINGS_PACKAGE)
+                                        .build())
+                        .build();
+        settingsPackage.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        shadowPackageManager.installPackage(settingsPackage);
+        shadowPackageManager.addActivityIfNotPresent(settingsComponent);
+        shadowPackageManager.addIntentFilterForActivity(settingsComponent, settingsIntent);
+
+        IntentFilter requestPermissionIntent = new IntentFilter(
+                PackageManager.ACTION_REQUEST_PERMISSIONS);
+        requestPermissionIntent.addCategory(Intent.CATEGORY_DEFAULT);
+        ComponentName requestPermissionComponent = new ComponentName(PERMISSION_PACKAGE,
+                TEST_ACTIVITY);
+
+        PackageInfo requestPermissionPackage =
+                PackageInfoBuilder.newBuilder()
+                        .setPackageName(PERMISSION_PACKAGE)
+                        .setApplicationInfo(
+                                ApplicationInfoBuilder.newBuilder()
+                                        .setName(PERMISSION_PACKAGE)
+                                        .setPackageName(PERMISSION_PACKAGE)
+                                        .build())
+                        .build();
+        requestPermissionPackage.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        shadowPackageManager.installPackage(requestPermissionPackage);
+        shadowPackageManager.addActivityIfNotPresent(requestPermissionComponent);
+        shadowPackageManager.addIntentFilterForActivity(requestPermissionComponent,
+                requestPermissionIntent);
+
+        PackageInfo cellBroadcastReceiverPackage =
+                PackageInfoBuilder.newBuilder()
+                        .setPackageName(CELL_BROADCAST_RECEIVER_PACKAGE)
+                        .setApplicationInfo(
+                                ApplicationInfoBuilder.newBuilder()
+                                        .setName(CELL_BROADCAST_RECEIVER_PACKAGE)
+                                        .setPackageName(CELL_BROADCAST_RECEIVER_PACKAGE)
+                                        .build())
+                        .build();
+        cellBroadcastReceiverPackage.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        cellBroadcastReceiverPackage.requestedPermissions =
+                new String[]{RECEIVE_EMERGENCY_BROADCAST};
+        cellBroadcastReceiverPackage.requestedPermissionsFlags =
+                new int[]{REQUESTED_PERMISSION_GRANTED};
+        shadowPackageManager.installPackage(cellBroadcastReceiverPackage);
+
+        IntentFilter cellBroadcastIntentFilter =
+                new IntentFilter(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION);
+        ComponentName cellBroadcastComponent =
+                new ComponentName(CELL_BROADCAST_RECEIVER_PACKAGE, TEST_ACTIVITY);
+
+        shadowPackageManager.addActivityIfNotPresent(cellBroadcastComponent);
+        shadowPackageManager.addIntentFilterForActivity(
+                cellBroadcastComponent, cellBroadcastIntentFilter);
+        Secure.putString(mContext.getContentResolver(), Secure.DEFAULT_INPUT_METHOD, IME_COMPONENT);
+    }
+
+    private static void setupKioskAllowListWithDuplicates()
+            throws ExecutionException, InterruptedException {
+        final String[] allowlistPackagesWithDuplicates =
+                {TEST_PACKAGE, TEST_PACKAGE, DIALER_PACKAGE, SETTINGS_PACKAGE, DIALER_PACKAGE};
+        Bundle bundle = new Bundle();
+        bundle.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        bundle.putStringArrayList(EXTRA_KIOSK_ALLOWLIST,
+                new ArrayList<>(List.of(allowlistPackagesWithDuplicates)));
+        SetupParametersClient.getInstance().createPrefs(bundle).get();
+    }
+
+    private void assertLockTaskMode(int defaultLockTaskFeatures,
+            String[] expectedAllowlistPackages) {
+        verify(mMockDpm, times(2)).setLockTaskFeatures(eq(null), mAllowedFeatures.capture());
+        verify(mMockDpm, times(3)).setLockTaskPackages(eq(null), mAllowedPackages.capture());
+        assertThat(mAllowedFeatures.getAllValues()).containsExactlyElementsIn(
+                new Integer[]{DevicePolicyManager.LOCK_TASK_FEATURE_NONE,
+                        defaultLockTaskFeatures});
+        assertThat(mAllowedPackages.getValue()).isEqualTo(expectedAllowlistPackages);
+    }
+
+    private void assertDisableLockTaskMode() {
+        verify(mMockDpm).setLockTaskFeatures(eq(null), mAllowedFeatures.capture());
+        verify(mMockDpm, times(2)).setLockTaskPackages(eq(null), mAllowedPackages.capture());
+        assertThat(mAllowedFeatures.getValue()).isEqualTo(
+                DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
+        List<String[]> allowedPackages = mAllowedPackages.getAllValues();
+        assertThat(allowedPackages.get(0)).isEqualTo(new String[]{""});
+        assertThat(allowedPackages.get(1)).isEqualTo(new String[0]);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/NotificationsPolicyHandlerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/NotificationsPolicyHandlerTest.java
new file mode 100644
index 0000000..f1a248e
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/NotificationsPolicyHandlerTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.devicelockcontroller.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+import android.os.OutcomeReceiver;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class NotificationsPolicyHandlerTest {
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private SystemDeviceLockManager mSystemDeviceLockManager;
+    private NotificationsPolicyHandler mHandler;
+
+    @Before
+    public void setUp() {
+        mHandler = new NotificationsPolicyHandler(mSystemDeviceLockManager,
+                Executors.newSingleThreadExecutor());
+    }
+
+    @Test
+    public void onProvisioned_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisioned().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onProvisionPaused_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionPaused().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onProvisionInProgress_withSuccess_shouldTryToSetSystemFixedFlag()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnSetPostNotificationsSystemFixedFuture(/* isSuccess =*/ true);
+        assertThat(mHandler.onProvisionInProgress().get()).isTrue();
+        verify(mSystemDeviceLockManager).setPostNotificationsSystemFixed(eq(true),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onProvisionInProgress_withFailure_shouldTryToSetSystemFixedFlag()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnSetPostNotificationsSystemFixedFuture(/* isSuccess =*/ false);
+        assertThat(mHandler.onProvisionInProgress().get()).isTrue();
+        verify(mSystemDeviceLockManager).setPostNotificationsSystemFixed(eq(true),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onProvisionFailed_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionFailed().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onCleared_withSuccess_shouldTryToClearSystemFixedFlag()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnSetPostNotificationsSystemFixedFuture(/* isSuccess =*/ false);
+        assertThat(mHandler.onCleared().get()).isTrue();
+        verify(mSystemDeviceLockManager).setPostNotificationsSystemFixed(eq(false),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onCleared_withFailure_shouldTryToClearSystemFixedFlag()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnSetPostNotificationsSystemFixedFuture(/* isSuccess =*/ false);
+        assertThat(mHandler.onCleared().get()).isTrue();
+        verify(mSystemDeviceLockManager).setPostNotificationsSystemFixed(eq(false),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onLocked_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onLocked().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onUnlocked_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onUnlocked().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    private void setExpectationsOnSetPostNotificationsSystemFixedFuture(boolean isSuccess) {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 2);
+            if (isSuccess) {
+                callback.onResult(/* result =*/ null);
+            } else {
+                callback.onError(new Exception());
+            }
+            return null;
+        }).when(mSystemDeviceLockManager).setPostNotificationsSystemFixed(anyBoolean(),
+                any(Executor.class), any());
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/PackagePolicyHandlerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/PackagePolicyHandlerTest.java
new file mode 100644
index 0000000..71faa7b
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/PackagePolicyHandlerTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class PackagePolicyHandlerTest {
+    private static final String TEST_KIOSK_PACKAGE = "test.package1";
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Mock
+    private DevicePolicyManager mMockDpm;
+    @Captor
+    private ArgumentCaptor<String> mKioskPackageNameCaptor;
+    @Captor
+    private ArgumentCaptor<Boolean> mUninstallBlockedCaptor;
+    @Captor
+    private ArgumentCaptor<List<String>> mUserControlDisabledPackages;
+
+    private Context mContext;
+
+    private PackagePolicyHandler mHandler;
+
+    @Before
+    public void setUp() {
+        mContext = ApplicationProvider.getApplicationContext();
+        mHandler = new PackagePolicyHandler(mContext, mMockDpm,
+                Executors.newSingleThreadExecutor());
+    }
+
+    @Test
+    public void onProvisioned_withKioskPackageSet_shouldHaveExpectedMethodCalls()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+
+        assertThat(mHandler.onProvisioned().get()).isTrue();
+
+        verify(mMockDpm).setUninstallBlocked(eq(null), mKioskPackageNameCaptor.capture(),
+                mUninstallBlockedCaptor.capture());
+        assertThat(mKioskPackageNameCaptor.getValue()).isEqualTo(TEST_KIOSK_PACKAGE);
+        assertThat(mUninstallBlockedCaptor.getValue()).isTrue();
+
+        verify(mMockDpm).setUserControlDisabledPackages(eq(null),
+                mUserControlDisabledPackages.capture());
+        List<String> userControlDisabledPackages = mUserControlDisabledPackages.getValue();
+        assertThat(userControlDisabledPackages).containsAnyIn(
+                new String[]{mContext.getPackageName(), TEST_KIOSK_PACKAGE});
+    }
+
+    @Test
+    public void onProvisioned_withoutKioskPackageSet_shouldHaveExpectedMethodCalls()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisioned().get()).isTrue();
+
+        verify(mMockDpm, never()).setUninstallBlocked(eq(null), mKioskPackageNameCaptor.capture(),
+                mUninstallBlockedCaptor.capture());
+
+        verify(mMockDpm).setUserControlDisabledPackages(eq(null),
+                mUserControlDisabledPackages.capture());
+        List<String> userControlDisabledPackages = mUserControlDisabledPackages.getValue();
+        assertThat(userControlDisabledPackages).containsAnyIn(
+                new String[]{mContext.getPackageName()});
+    }
+
+    @Test
+    public void onProvisioned_withSecurityException_shouldHaveExpectedMethodCalls()
+            throws ExecutionException, InterruptedException {
+        doAnswer((Answer<Object>) invocation -> {
+            throw new SecurityException();
+        }).when(mMockDpm).setUserControlDisabledPackages(any(), any());
+
+        assertThat(mHandler.onProvisioned().get()).isFalse();
+
+        verify(mMockDpm, never()).setUninstallBlocked(eq(null), mKioskPackageNameCaptor.capture(),
+                mUninstallBlockedCaptor.capture());
+    }
+
+    @Test
+    public void onCleared_withKioskPackageSet_shouldHaveExpectedMethodCalls()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+
+        assertThat(mHandler.onCleared().get()).isTrue();
+
+        verify(mMockDpm).setUninstallBlocked(eq(null), mKioskPackageNameCaptor.capture(),
+                mUninstallBlockedCaptor.capture());
+        assertThat(mKioskPackageNameCaptor.getValue()).isEqualTo(TEST_KIOSK_PACKAGE);
+        assertThat(mUninstallBlockedCaptor.getValue()).isFalse();
+
+        verify(mMockDpm).setUserControlDisabledPackages(eq(null),
+                mUserControlDisabledPackages.capture());
+        List<String> userControlDisabledPackages = mUserControlDisabledPackages.getValue();
+        assertThat(userControlDisabledPackages).containsAnyIn(
+                new String[]{mContext.getPackageName()});
+    }
+
+    @Test
+    public void onProvisionInProgress_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionInProgress().get()).isTrue();
+        verifyNoInteractions(mMockDpm);
+    }
+
+    @Test
+    public void onProvisionPaused_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionPaused().get()).isTrue();
+        verifyNoInteractions(mMockDpm);
+    }
+
+    @Test
+    public void onProvisionFailed_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionFailed().get()).isTrue();
+        verifyNoInteractions(mMockDpm);
+    }
+
+    @Test
+    public void onLocked_shouldDoNothing() throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onLocked().get()).isTrue();
+        verifyNoInteractions(mMockDpm);
+    }
+
+    @Test
+    public void onUnlocked_shouldDoNothing() throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onUnlocked().get()).isTrue();
+        verifyNoInteractions(mMockDpm);
+    }
+
+    private static void setupSetupParameters() throws InterruptedException, ExecutionException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_KIOSK_PACKAGE);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionHelperImplTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionHelperImplTest.java
new file mode 100644
index 0000000..8d119f2
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionHelperImplTest.java
@@ -0,0 +1,690 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.NOT_IN_ELIGIBLE_COUNTRY;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.PLAY_INSTALLATION_FAILED;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason.UNKNOWN_REASON;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_KIOSK;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_PAUSE;
+import static com.android.devicelockcontroller.provision.worker.IsDeviceInApprovedCountryWorker.KEY_IS_IN_APPROVED_COUNTRY;
+import static com.android.devicelockcontroller.provision.worker.PauseProvisioningWorker.REPORT_PROVISION_PAUSED_BY_USER_WORK;
+import static com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker.KEY_IS_PROVISION_SUCCESSFUL;
+import static com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker.KEY_PROVISION_FAILURE_REASON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Looper;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+
+import androidx.annotation.NonNull;
+import androidx.core.util.Consumer;
+import androidx.core.util.Preconditions;
+import androidx.lifecycle.Lifecycle.State;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.work.Configuration;
+import androidx.work.Data;
+import androidx.work.ListenableWorker;
+import androidx.work.ListenableWorker.Result;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+import androidx.work.WorkerFactory;
+import androidx.work.WorkerParameters;
+import androidx.work.testing.TestDriver;
+import androidx.work.testing.WorkManagerTestInitHelper;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication.PlayInstallPackageWorker;
+import com.android.devicelockcontroller.activities.ProvisioningProgress;
+import com.android.devicelockcontroller.activities.ProvisioningProgressController;
+import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason;
+import com.android.devicelockcontroller.provision.worker.IsDeviceInApprovedCountryWorker;
+import com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker;
+import com.android.devicelockcontroller.shadows.ShadowBuild;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.testing.TestingExecutors;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowPackageManager;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBuild.class})
+public final class ProvisionHelperImplTest {
+
+    private static final String TEST_KIOSK_PACKAGE = "test.package.name";
+    private static final String PLAY_INSTALL_WORKER_UNIQUE_NAME =
+            PlayInstallPackageWorker.class.getSimpleName();
+    private static final String PLAY_INSTALL_WORKER_CLASS_NAME =
+            PlayInstallPackageWorker.class.getName();
+    private static final String COUNTRY_WORKER_CLASS_NAME =
+            IsDeviceInApprovedCountryWorker.class.getName();
+    private static final String COUNTRY_WORKER_UNIQUE_NAME =
+            IsDeviceInApprovedCountryWorker.class.getSimpleName();
+
+    @Rule
+    public final MockitoRule mMocks = MockitoJUnit.rule();
+
+    private ProvisionStateController mMockStateController;
+    @Mock
+    private LifecycleOwner mMockLifecycleOwner;
+    @Mock
+    private ProvisioningProgressController mProgressController;
+    @Captor
+    private ArgumentCaptor<ProvisioningProgress> mProvisioningProgressArgumentCaptor;
+
+    private TestDeviceLockControllerApplication mTestApp;
+    private ProvisionHelperImpl mProvisionHelper;
+
+    private TestDriver mTestDriver;
+    private TestWorkerFactory mTestWorkerFactory;
+
+    @Before
+    public void setUp() {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        mMockStateController = mTestApp.getProvisionStateController();
+        Executor executor = TestingExecutors.sameThreadScheduledExecutor();
+        ProvisionHelperImpl.getSharedPreferences(mTestApp).edit().clear().commit();
+        mProvisionHelper = new ProvisionHelperImpl(mTestApp, mMockStateController, executor);
+        mTestWorkerFactory = new TestWorkerFactory();
+        WorkManagerTestInitHelper.initializeTestWorkManager(mTestApp,
+                new Configuration.Builder().setExecutor(executor).setWorkerFactory(
+                        mTestWorkerFactory).build());
+        mTestDriver = WorkManagerTestInitHelper.getTestDriver(mTestApp);
+        setupLifecycle();
+    }
+
+    @Test
+    public void checkGeoEligibility_countryUnknown_thenProceedToFailure() throws Exception {
+        // GIVEN Country is unknown
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.failure());
+
+        // WHEN Installation is executed
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+
+        // THEN Installation fails
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                        ProvisionFailureReason.COUNTRY_INFO_UNAVAILABLE)));
+    }
+
+    @Test
+    public void checkGeoEligibility_inUnapprovedCountry_thenProceedToFailure() throws Exception {
+        // GIVEN Country is unapproved
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, false).build()));
+
+        // WHEN Installation is initiated
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+
+        // THEN Installation fails
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                        ProvisionFailureReason.NOT_IN_ELIGIBLE_COUNTRY)));
+    }
+
+    @Test
+    public void checkGeoEligibility_inApprovedCountry_thenProceedToInstalling() throws Exception {
+        // GIVEN Country is approved
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+
+
+        // WHEN Installation is initiated
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(IsDeviceInApprovedCountryWorker.class.getSimpleName());
+
+        // THEN install kiosk app
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.INSTALLING_KIOSK_APP));
+    }
+
+    @Test
+    public void installKiosk_onDebuggableBuild_thenUseInstalledApp() throws Exception {
+        // GIVEN build is debuggable build and kiosk app is installed
+        ShadowBuild.setIsDebuggable(true);
+        setupSetupParameters();
+        installKioskApp();
+        setupLifecycle();
+
+        // GIVEN Country is approved and play installation would fail.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+
+
+        // WHEN installation is executed
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+
+        // THEN go through correct ProvisioningProgress and advance to next state.
+        verify(mMockStateController).postSetNextStateForEventRequest(eq(PROVISION_KIOSK));
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.INSTALLING_KIOSK_APP,
+                ProvisioningProgress.OPENING_KIOSK_APP));
+
+        // THEN play installation work is not enqueued.
+        assertWorkNotEnqueued(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN provision complete is reported
+        mTestWorkerFactory.setWorkerInputDataAssert(
+                ReportDeviceProvisionStateWorker.class.getName(), data -> {
+                    assertThat(data.getBoolean(KEY_IS_PROVISION_SUCCESSFUL, false)).isTrue();
+                });
+        executeWork(ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME);
+    }
+
+    @Test
+    public void installKiosk_whenFlagIsDisabledOnDebuggableBuild_thenInstallFromPlay()
+            throws Exception {
+        // GIVEN build is debuggable build and kiosk app is installed and flag is disabled
+        ShadowBuild.setIsDebuggable(true);
+        setupSetupParameters();
+        installKioskApp();
+        setupLifecycle();
+        ProvisionHelperImpl.setPreinstalledKioskAllowed(mTestApp, false);
+
+        // GIVEN Country is approved and play installation would success.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+        mTestWorkerFactory.setWorkResult(PLAY_INSTALL_WORKER_CLASS_NAME, Result.success());
+
+
+        // WHEN installation is executed
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+        executeWork(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN go through correct ProvisioningProgress and advance to next state.
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.INSTALLING_KIOSK_APP,
+                ProvisioningProgress.OPENING_KIOSK_APP));
+        verify(mMockStateController).postSetNextStateForEventRequest(eq(PROVISION_KIOSK));
+
+        // THEN provision complete is reported
+        assertWorkEnqueued(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+        mTestWorkerFactory.setWorkerInputDataAssert(
+                ReportDeviceProvisionStateWorker.class.getName(), data -> {
+                    assertThat(data.getBoolean(KEY_IS_PROVISION_SUCCESSFUL, false)).isTrue();
+                });
+        executeWork(ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME);
+    }
+
+    @Test
+    public void installKiosk_whenFlagIsEnabledOnNonDebuggableBuild_thenInstallFromPlay()
+            throws Exception {
+        // GIVEN build is non-debuggable build and kiosk app is installed and flag is enabled
+        ShadowBuild.setIsDebuggable(false);
+        setupSetupParameters();
+        installKioskApp();
+        setupLifecycle();
+        ProvisionHelperImpl.setPreinstalledKioskAllowed(mTestApp, true);
+
+        // GIVEN Country is approved and play installation would success.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+        mTestWorkerFactory.setWorkResult(PLAY_INSTALL_WORKER_CLASS_NAME, Result.success());
+
+
+        // WHEN installation is executed
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+        executeWork(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN go through correct ProvisioningProgress and advance to next state.
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.INSTALLING_KIOSK_APP,
+                ProvisioningProgress.OPENING_KIOSK_APP));
+        verify(mMockStateController).postSetNextStateForEventRequest(eq(PROVISION_KIOSK));
+
+        // THEN provision complete is reported
+        assertWorkEnqueued(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+        mTestWorkerFactory.setWorkerInputDataAssert(
+                ReportDeviceProvisionStateWorker.class.getName(), data -> {
+                    assertThat(data.getBoolean(KEY_IS_PROVISION_SUCCESSFUL, false)).isTrue();
+                });
+        executeWork(ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME);
+    }
+
+    @Test
+    public void installKiosk_whenFlagIsDisabledOnNonDebuggableBuild_thenInstallFromPlay()
+            throws Exception {
+        // GIVEN build is non-debuggable build and kiosk app is installed and flag is disabled
+        ShadowBuild.setIsDebuggable(false);
+        setupSetupParameters();
+        installKioskApp();
+        setupLifecycle();
+        ProvisionHelperImpl.setPreinstalledKioskAllowed(mTestApp, false);
+
+        // GIVEN Country is approved and play installation would success.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+        mTestWorkerFactory.setWorkResult(PLAY_INSTALL_WORKER_CLASS_NAME, Result.success());
+
+
+        // WHEN installation is executed
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+        executeWork(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN go through correct ProvisioningProgress and advance to next state.
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.INSTALLING_KIOSK_APP,
+                ProvisioningProgress.OPENING_KIOSK_APP));
+        verify(mMockStateController).postSetNextStateForEventRequest(eq(PROVISION_KIOSK));
+
+        // THEN provision complete is reported
+        assertWorkEnqueued(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+        mTestWorkerFactory.setWorkerInputDataAssert(
+                ReportDeviceProvisionStateWorker.class.getName(), data -> {
+                    assertThat(data.getBoolean(KEY_IS_PROVISION_SUCCESSFUL, false)).isTrue();
+                });
+        executeWork(ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME);
+    }
+
+    @Test
+    public void installKiosk_whenAppIsNotPreinstalled_thenInstallFromPlay() throws Exception {
+        // GIVEN build is debuggable build and kiosk app is not installed
+        ShadowBuild.setIsDebuggable(true);
+        setupSetupParameters();
+        setupLifecycle();
+        checkKioskAppNotInstalled();
+
+        // GIVEN Country is approved and play installation would success.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+        mTestWorkerFactory.setWorkResult(PLAY_INSTALL_WORKER_CLASS_NAME, Result.success());
+
+
+        // WHEN installation is executed
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+        executeWork(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN go through correct ProvisioningProgress and advance to next state.
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.INSTALLING_KIOSK_APP,
+                ProvisioningProgress.OPENING_KIOSK_APP));
+        verify(mMockStateController).postSetNextStateForEventRequest(eq(PROVISION_KIOSK));
+
+        // THEN provision complete is reported
+        assertWorkEnqueued(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+        mTestWorkerFactory.setWorkerInputDataAssert(
+                ReportDeviceProvisionStateWorker.class.getName(), data -> {
+                    assertThat(data.getBoolean(KEY_IS_PROVISION_SUCCESSFUL, false)).isTrue();
+                });
+        executeWork(ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME);
+    }
+
+    @Test
+    public void installKiosk_whenInstallationFailsAndIsMandatory_thenReportFailure()
+            throws Exception {
+        // GIVEN Country is approved and play installation would fail.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+        mTestWorkerFactory.setWorkResult(PLAY_INSTALL_WORKER_CLASS_NAME, Result.failure());
+
+        // WHEN installation is executed for mandatory provisioning
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ true);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+        executeWork(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN go through correct ProvisioningProgress and schedule reset alarm.
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.INSTALLING_KIOSK_APP,
+                ProvisioningProgress.getMandatoryProvisioningFailedProgress(
+                        PLAY_INSTALLATION_FAILED)));
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleMandatoryResetDeviceAlarm();
+
+        // THEN provision failure is reported
+        mTestWorkerFactory.setWorkerInputDataAssert(
+                ReportDeviceProvisionStateWorker.class.getName(), data -> {
+                    assertThat(data.getBoolean(KEY_IS_PROVISION_SUCCESSFUL, true)).isFalse();
+                    assertThat(data.getInt(KEY_PROVISION_FAILURE_REASON,
+                            UNKNOWN_REASON)).isEqualTo(NOT_IN_ELIGIBLE_COUNTRY);
+                });
+        executeWork(ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME);
+    }
+
+    @Test
+    public void installKiosk_whenInstallationFailsAndIsMandatory_thenSetResetTimer()
+            throws Exception {
+        // GIVEN Country is approved and play installation would fail.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+        mTestWorkerFactory.setWorkResult(PLAY_INSTALL_WORKER_CLASS_NAME, Result.failure());
+
+
+        // WHEN installation is executed for mandatory provisioning
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ true);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+        executeWork(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN schedule reset alarm.
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleMandatoryResetDeviceAlarm();
+    }
+
+    @Test
+    public void installKiosk_whenInstallationFailsAndIsMandatory_thenSetProgress()
+            throws Exception {
+        // GIVEN Country is approved and play installation would fail.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+        mTestWorkerFactory.setWorkResult(PLAY_INSTALL_WORKER_CLASS_NAME, Result.failure());
+
+
+        // WHEN installation is executed for mandatory provisioning
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ true);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+        executeWork(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN go through correct ProvisioningProgress.
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.INSTALLING_KIOSK_APP,
+                ProvisioningProgress.getMandatoryProvisioningFailedProgress(
+                        PLAY_INSTALLATION_FAILED)));
+    }
+
+    @Test
+    public void installKiosk_whenInstallationFailsAndIsNonMandatory_thenSetProgress()
+            throws Exception {
+        // GIVEN Country is approved and play installation would fail.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+        mTestWorkerFactory.setWorkResult(PLAY_INSTALL_WORKER_CLASS_NAME, Result.failure());
+
+
+        // WHEN installation is executed for non-mandatory provisioning
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+        executeWork(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN go through correct ProvisioningProgress.
+        verifyProgressesSet(Arrays.asList(ProvisioningProgress.GETTING_DEVICE_READY,
+                ProvisioningProgress.INSTALLING_KIOSK_APP,
+                ProvisioningProgress.getNonMandatoryProvisioningFailedProgress(
+                        PLAY_INSTALLATION_FAILED)));
+    }
+
+    @Test
+    public void installKiosk_whenInstallationFailsAndIsNonMandatory_thenDoNotReportFailure()
+            throws Exception {
+        // GIVEN Country is approved and play installation would fail.
+        mTestWorkerFactory.setWorkResult(COUNTRY_WORKER_CLASS_NAME,
+                Result.success(
+                        new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build()));
+        mTestWorkerFactory.setWorkResult(PLAY_INSTALL_WORKER_CLASS_NAME, Result.failure());
+
+
+        // WHEN installation is executed for mandatory provisioning
+        mProvisionHelper.scheduleKioskAppInstallation(mMockLifecycleOwner,
+                mProgressController, /* isProvisionMandatory= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        executeWork(COUNTRY_WORKER_UNIQUE_NAME);
+        executeWork(PLAY_INSTALL_WORKER_UNIQUE_NAME);
+
+        // THEN provision failure is not reported
+        assertWorkNotEnqueued(ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME);
+    }
+
+    @Test
+    public void pauseProvision_thenMarkProvisionForced() throws Exception {
+        // GIVEN provision can be paused
+        assertThat(GlobalParametersClient.getInstance().isProvisionForced().get()).isFalse();
+        when(mMockStateController.setNextStateForEvent(eq(PROVISION_PAUSE))).thenReturn(
+                Futures.immediateVoidFuture());
+
+        // WHEN pauseProvision() is called.
+        mProvisionHelper.pauseProvision();
+
+        // THEN provision should be marked forced.
+        assertThat(GlobalParametersClient.getInstance().isProvisionForced().get()).isTrue();
+    }
+
+    @Test
+    public void pauseProvision_thenReportPause() throws Exception {
+        // GIVEN provision can be paused
+        assertThat(GlobalParametersClient.getInstance().isProvisionForced().get()).isFalse();
+        when(mMockStateController.setNextStateForEvent(eq(PROVISION_PAUSE))).thenReturn(
+                Futures.immediateVoidFuture());
+
+        // WHEN pauseProvision() is called.
+        mProvisionHelper.pauseProvision();
+
+        // THEN pause provision should be reported.
+        assertWorkEnqueued(REPORT_PROVISION_PAUSED_BY_USER_WORK);
+    }
+
+    @Test
+    public void pauseProvision_thenScheduleResume() throws Exception {
+        // GIVEN provision can be paused
+        assertThat(GlobalParametersClient.getInstance().isProvisionForced().get()).isFalse();
+        when(mMockStateController.setNextStateForEvent(eq(PROVISION_PAUSE))).thenReturn(
+                Futures.immediateVoidFuture());
+
+        // WHEN pauseProvision() is called.
+        mProvisionHelper.pauseProvision();
+
+        // THEN schedule resume
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleResumeProvisionAlarm();
+    }
+
+    @Test
+    public void pauseProvision_withException_thenMarkProvisionForced() throws Exception {
+        // GIVEN pause provisioning throws exception
+        assertThat(GlobalParametersClient.getInstance().isProvisionForced().get()).isFalse();
+        when(mMockStateController.setNextStateForEvent(eq(PROVISION_PAUSE))).thenReturn(
+                Futures.immediateFailedFuture(new Throwable()));
+
+        // WHEN pauseProvision() is called.
+        mProvisionHelper.pauseProvision();
+
+        // THEN provision should be marked forced
+        assertThat(GlobalParametersClient.getInstance().isProvisionForced().get()).isTrue();
+    }
+
+    @Test
+    public void pauseProvision_withException_thenNotScheduleResume() throws Exception {
+        // GIVEN pause provisioning throws exception
+        assertThat(GlobalParametersClient.getInstance().isProvisionForced().get()).isFalse();
+        when(mMockStateController.setNextStateForEvent(eq(PROVISION_PAUSE))).thenReturn(
+                Futures.immediateFailedFuture(new Throwable()));
+
+        // WHEN pauseProvision() is called.
+        mProvisionHelper.pauseProvision();
+
+        // THEN provision pause should not be reported
+        verify(mTestApp.getDeviceLockControllerScheduler(), never()).scheduleResumeProvisionAlarm();
+    }
+
+    @Test
+    public void pauseProvision_withException_thenNotReportPause() throws Exception {
+        // GIVEN pause provisioning throws exception
+        assertThat(GlobalParametersClient.getInstance().isProvisionForced().get()).isFalse();
+        when(mMockStateController.setNextStateForEvent(eq(PROVISION_PAUSE))).thenReturn(
+                Futures.immediateFailedFuture(new Throwable()));
+
+        // WHEN pauseProvision() is called.
+        mProvisionHelper.pauseProvision();
+
+        // THEN provision pause should not be reported
+        assertWorkNotEnqueued(REPORT_PROVISION_PAUSED_BY_USER_WORK);
+    }
+
+
+    private void executeWork(String uniqueWorkName) throws Exception {
+        List<WorkInfo> workInfoList = Futures.getChecked(
+                WorkManager.getInstance(mTestApp)
+                        .getWorkInfosForUniqueWork(uniqueWorkName), Exception.class);
+        assertThat(workInfoList.size()).isEqualTo(1);
+        mTestDriver.setAllConstraintsMet(workInfoList.get(0).getId());
+        ShadowLooper.runUiThreadTasks();
+    }
+
+    private void installKioskApp() {
+        ShadowPackageManager pm = Shadows.shadowOf(mTestApp.getPackageManager());
+        PackageInfo kioskPackageInfo = new PackageInfo();
+        kioskPackageInfo.packageName = TEST_KIOSK_PACKAGE;
+        pm.installPackage(kioskPackageInfo);
+    }
+
+    private void checkKioskAppNotInstalled() {
+        Preconditions.checkState(
+                !mTestApp.getPackageManager().getInstalledPackages(
+                                PackageManager.PackageInfoFlags.of(0))
+                        .stream().anyMatch(
+                                packageInfo -> TextUtils.equals(packageInfo.packageName,
+                                        TEST_KIOSK_PACKAGE)));
+    }
+
+    private void setupLifecycle() {
+        LifecycleRegistry mockLifecycle = new LifecycleRegistry(mMockLifecycleOwner);
+        mockLifecycle.setCurrentState(State.RESUMED);
+        when(mMockLifecycleOwner.getLifecycle()).thenReturn(mockLifecycle);
+    }
+
+    private static void setupSetupParameters() throws InterruptedException, ExecutionException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_KIOSK_PACKAGE);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+    }
+
+    private void verifyProgressesSet(List<ProvisioningProgress> progressList) {
+        verify(mProgressController, times(progressList.size())).setProvisioningProgress(
+                mProvisioningProgressArgumentCaptor.capture());
+        List<ProvisioningProgress> allValues = mProvisioningProgressArgumentCaptor.getAllValues();
+        assertThat(allValues).containsAtLeastElementsIn(progressList);
+    }
+
+    private void assertWorkNotEnqueued(String uniqueWorkerName) throws Exception {
+        List<WorkInfo> workInfoList = Futures.getChecked(WorkManager.getInstance(
+                mTestApp).getWorkInfosForUniqueWork(uniqueWorkerName), Exception.class);
+        assertThat(workInfoList).isEmpty();
+    }
+
+    private void assertWorkEnqueued(String uniqueWorkerName) throws Exception {
+        List<WorkInfo> workInfoList = Futures.getChecked(WorkManager.getInstance(
+                mTestApp).getWorkInfosForUniqueWork(uniqueWorkerName), Exception.class);
+        assertThat(workInfoList).isNotEmpty();
+    }
+
+    /**
+     * A {@link WorkerFactory} creates {@link ListenableWorker} which returns result based on
+     * caller's input.
+     */
+    private class TestWorkerFactory extends WorkerFactory {
+
+        private ArrayMap<String, Result> mWorkerResults = new ArrayMap<>();
+
+        private ArrayMap<String, Consumer<Data>> mWorkerInputDataAssertions = new ArrayMap<>();
+
+        public void setWorkResult(String workerClassName, Result result) {
+            mWorkerResults.put(workerClassName, result);
+        }
+
+        public void setWorkerInputDataAssert(String workerClassName, Consumer<Data> assertion) {
+            mWorkerInputDataAssertions.put(workerClassName, assertion);
+        }
+
+        @Override
+        public ListenableWorker createWorker(@NonNull Context appContext,
+                @NonNull String workerClassName, @NonNull WorkerParameters workerParameters) {
+            return new ListenableWorker(appContext, workerParameters) {
+                @NonNull
+                @Override
+                public ListenableFuture<Result> startWork() {
+                    mWorkerInputDataAssertions.getOrDefault(workerClassName,
+                            data -> {}).accept(getInputData());
+                    return Futures.immediateFuture(
+                            mWorkerResults.getOrDefault(workerClassName, Result.success()));
+                }
+            };
+        }
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionStateControllerImplTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionStateControllerImplTest.java
new file mode 100644
index 0000000..15012d3
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionStateControllerImplTest.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.pm.PackageManager;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.provider.Settings;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.work.testing.WorkManagerTestInitHelper;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent;
+import com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState;
+import com.android.devicelockcontroller.policy.ProvisionStateControllerImpl.StateTransitionException;
+import com.android.devicelockcontroller.receivers.LockedBootCompletedReceiver;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.UserParameters;
+
+import com.google.common.util.concurrent.Futures;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class ProvisionStateControllerImplTest {
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private DevicePolicyController mMockPolicyController;
+    @Mock
+    private DeviceStateController mMockDeviceStateController;
+
+    private TestDeviceLockControllerApplication mTestApp;
+    private ProvisionStateController mProvisionStateController;
+    private StatsLogger mStatsLogger;
+
+    @Before
+    public void setUp() {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        WorkManagerTestInitHelper.initializeTestWorkManager(mTestApp);
+        mProvisionStateController = new ProvisionStateControllerImpl(mTestApp,
+                mMockPolicyController, mMockDeviceStateController,
+                Executors.newSingleThreadExecutor());
+        mStatsLogger = mTestApp.getStatsLogger();
+    }
+
+    @Test
+    public void getState_shouldReturnDefaultProvisionState()
+            throws ExecutionException, InterruptedException {
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.UNPROVISIONED);
+    }
+
+    @Test
+    public void postSetNextStateForEventRequest_shouldReturnExpectedProvisionState()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        mProvisionStateController.postSetNextStateForEventRequest(ProvisionEvent.PROVISION_READY);
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.PROVISION_IN_PROGRESS);
+    }
+
+    @Test
+    public void setNextStateForEvent_shouldSetExpectedNextProvisionState()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        ComponentName lockedBootCompletedReceiver =
+                new ComponentName(mTestApp, LockedBootCompletedReceiver.class);
+        PackageManager packageManager = mTestApp.getPackageManager();
+        assertThat(packageManager.getComponentEnabledSetting(lockedBootCompletedReceiver))
+                .isEqualTo(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
+
+        // Successful call to this method should put the provisioning state in progress.
+        mProvisionStateController.setNextStateForEvent(ProvisionEvent.PROVISION_READY).get();
+
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.PROVISION_IN_PROGRESS);
+
+        // LockedBootCompletedReceiver should be enabled for provision in progress state
+        assertThat(packageManager.getComponentEnabledSetting(lockedBootCompletedReceiver))
+                .isEqualTo(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+
+        // Now transition from provision progress to pause state.
+        mProvisionStateController.setNextStateForEvent(ProvisionEvent.PROVISION_PAUSE).get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.PROVISION_PAUSED);
+
+        // Two times invocation of enforceCurrentPolicies method is expected because we are calling
+        // setNextStateForEvent twice.
+        verify(mMockPolicyController, times(2)).enforceCurrentPolicies();
+    }
+
+    @Test
+    public void setNextStateForEvent_shouldWriteStartTimeToUserParameters_whenProvisonReady()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        mProvisionStateController.setNextStateForEvent(ProvisionEvent.PROVISION_READY).get();
+
+        assertThat(UserParameters.getProvisioningStartTimeMillis(mTestApp))
+                .isEqualTo(SystemClock.elapsedRealtime());
+    }
+
+    @Test
+    public void setNextStateForEvent_shouldLogSuccessfulProvisioning_whenProvisionSuccess()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        UserParameters.setProvisionState(mTestApp, ProvisionState.KIOSK_PROVISIONED);
+
+        mProvisionStateController.setNextStateForEvent(ProvisionEvent.PROVISION_SUCCESS).get();
+
+        verify(mStatsLogger).logSuccessfulProvisioning();
+    }
+
+    @Test
+    public void setNextStateForEvent_withException_shouldRetainProvisionState()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.UNPROVISIONED);
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> mProvisionStateController.setNextStateForEvent(
+                        ProvisionEvent.PROVISION_PAUSE).get());
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(thrown).hasCauseThat().isInstanceOf(StateTransitionException.class);
+        assertThat(thrown).hasMessageThat().contains("Can not handle event: ");
+
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.UNPROVISIONED);
+        verify(mMockPolicyController, never()).enforceCurrentPolicies();
+    }
+
+    @Test
+    public void setNextStateForEvent_withException_shouldHandlePolicyEnforcementFailure()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mMockPolicyController.enforceCurrentPoliciesForCriticalFailure()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        mProvisionStateController.setNextStateForEvent(ProvisionEvent.PROVISION_READY).get();
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.PROVISION_IN_PROGRESS);
+
+        // Simulate exception in enforceCurrentPolicies call
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateFailedFuture(new Exception()));
+
+        assertThrows(Exception.class,
+                () -> mProvisionStateController.setNextStateForEvent(
+                        ProvisionEvent.PROVISION_PAUSE).get());
+        shadowOf(Looper.getMainLooper()).idle();
+
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.PROVISION_IN_PROGRESS);
+
+        verify(mMockPolicyController).enforceCurrentPoliciesForCriticalFailure();
+    }
+
+    @Test
+    public void notifyProvisioningReady_whenSetupIsNotComplete_shouldNotGoToProvisionInProgress()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        // Device setup is not complete
+        mProvisionStateController.notifyProvisioningReady();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.UNPROVISIONED);
+    }
+
+    @Test
+    public void notifyProvisioningReady_whenSetupIsComplete_shouldSetExpectedProvisionState()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        // Device setup is complete
+        ContentResolver contentResolver = mTestApp.getContentResolver();
+        Settings.Secure.putInt(contentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1);
+
+        mProvisionStateController.notifyProvisioningReady();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.PROVISION_IN_PROGRESS);
+    }
+
+    @Test
+    public void onUserUnlocked_shouldSetExpectedProvisionState()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        mProvisionStateController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.UNPROVISIONED);
+    }
+
+    @Test
+    public void onUserUnlocked_withProvisionReady_shouldSetExpectedProvisionState()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+
+        GlobalParametersClient.getInstance().setProvisionReady(true).get();
+        ContentResolver contentResolver = mTestApp.getContentResolver();
+        Settings.Secure.putInt(contentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1);
+
+        mProvisionStateController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.PROVISION_IN_PROGRESS);
+    }
+
+    @Test
+    public void onUserUnlocked_withProvisionPaused_shouldSetExpectedProvisionState()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        UserParameters.setProvisionState(mTestApp, ProvisionState.PROVISION_PAUSED);
+
+        mProvisionStateController.onUserUnlocked().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.PROVISION_PAUSED);
+    }
+
+    @Test
+    public void onUserSetupCompleted_withProvisionReady_shouldGoToProvisionInProgress()
+            throws ExecutionException, InterruptedException {
+        when(mMockPolicyController.enforceCurrentPolicies()).thenReturn(
+                Futures.immediateVoidFuture());
+        GlobalParametersClient.getInstance().setProvisionReady(true).get();
+        // Device setup is complete
+        ContentResolver contentResolver = mTestApp.getContentResolver();
+        Settings.Secure.putInt(contentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1);
+
+        mProvisionStateController.onUserSetupCompleted().get();
+
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mProvisionStateController.getState().get()).isEqualTo(
+                ProvisionState.PROVISION_IN_PROGRESS);
+    }
+
+    @Test
+    public void getDeviceStateController_shouldReturnExpectedDeviceStateController() {
+        assertThat(mProvisionStateController.getDeviceStateController()).isEqualTo(
+                mMockDeviceStateController);
+    }
+
+    @Test
+    public void getDevicePolicyController_shouldReturnExpectedDevicePolicyController() {
+        assertThat(mProvisionStateController.getDevicePolicyController()).isEqualTo(
+                mMockPolicyController);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionStateControllerStateTransitionTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionStateControllerStateTransitionTest.java
new file mode 100644
index 0000000..092c85b
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionStateControllerStateTransitionTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_FAILURE;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_KIOSK;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_PAUSE;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_READY;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_RESUME;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_RETRY;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_SUCCESS;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.KIOSK_PROVISIONED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_FAILED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_IN_PROGRESS;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_PAUSED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED;
+
+import com.google.common.truth.Truth;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.ParameterizedRobolectricTestRunner;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(ParameterizedRobolectricTestRunner.class)
+public class ProvisionStateControllerStateTransitionTest {
+
+    @ParameterizedRobolectricTestRunner.Parameter
+    @ProvisionStateController.ProvisionState
+    public int mState;
+
+    @ParameterizedRobolectricTestRunner.Parameter(1)
+    @ProvisionStateController.ProvisionEvent
+    public int mEvent;
+
+    @ParameterizedRobolectricTestRunner.Parameter(2)
+    @ProvisionStateController.ProvisionState
+    public int mNextState;
+
+    @ParameterizedRobolectricTestRunner.Parameters(name =
+            "Transition from {0} to {2} when {1} event happens")
+    public static List<Object[]> parameters() {
+        return Arrays.asList(new Object[][]{
+                {UNPROVISIONED, PROVISION_READY, PROVISION_IN_PROGRESS},
+                {PROVISION_FAILED, PROVISION_RETRY, PROVISION_IN_PROGRESS},
+                {PROVISION_IN_PROGRESS, PROVISION_KIOSK, KIOSK_PROVISIONED},
+                {PROVISION_IN_PROGRESS, PROVISION_FAILURE, PROVISION_FAILED},
+                {PROVISION_IN_PROGRESS, PROVISION_PAUSE, PROVISION_PAUSED},
+                {KIOSK_PROVISIONED, PROVISION_SUCCESS, PROVISION_SUCCEEDED},
+                {PROVISION_PAUSED, PROVISION_RESUME, PROVISION_IN_PROGRESS}
+        });
+    }
+
+    @Test
+    public void getNextState_nextStateIsExpectedBasedOnInputStateAndEvent() {
+        Truth.assertThat(ProvisionStateControllerImpl.getNextState(mState, mEvent)).isEqualTo(
+                mNextState);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionStateControllerThreadSafetyTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionStateControllerThreadSafetyTest.java
new file mode 100644
index 0000000..705551e
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/ProvisionStateControllerThreadSafetyTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_READY;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
+import static org.robolectric.annotation.LooperMode.Mode.LEGACY;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.policy.ProvisionStateControllerImpl.StateTransitionException;
+import com.android.devicelockcontroller.storage.UserParameters;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.LooperMode;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@LooperMode(LEGACY)
+@RunWith(RobolectricTestRunner.class)
+public class ProvisionStateControllerThreadSafetyTest {
+    private ProvisionStateController mProvisionStateController;
+
+    private static final int NUMBER_OF_THREADS = 100;
+
+    @Before
+    public void setUp() {
+        TestDeviceLockControllerApplication testApplication =
+                ApplicationProvider.getApplicationContext();
+        UserParameters.setProvisionState(testApplication, UNPROVISIONED);
+        DevicePolicyController policyController = testApplication.getPolicyController();
+        mProvisionStateController = new ProvisionStateControllerImpl(testApplication,
+                policyController, testApplication.getDeviceStateController(),
+                Executors.newCachedThreadPool());
+        when(policyController.enforceCurrentPolicies()).thenReturn(Futures.immediateVoidFuture());
+    }
+
+    @Test
+    public void setNextStateForEvent_shouldSetStateOnlyOnce_whenMultithreading() {
+        ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
+        Collection<ListenableFuture<Void>> results = Collections.synchronizedCollection(
+                new ArrayList<>());
+        CountDownLatch startLatch = new CountDownLatch(1);
+        CountDownLatch finishLatch = new CountDownLatch(NUMBER_OF_THREADS);
+
+        for (int i = 0; i < NUMBER_OF_THREADS; i++) {
+            executorService.submit(() -> {
+                try {
+                    startLatch.await();
+                } catch (InterruptedException e) {
+                    fail(String.format("Test threads interrupted, exception: %s", e));
+                }
+                results.add(
+                        mProvisionStateController.setNextStateForEvent(PROVISION_READY));
+                finishLatch.countDown();
+            });
+        }
+        // This aims to increase the possibility of a race condition by letting all the threads wait
+        // for the CountDownLatch and unblock them at the same time.
+        startLatch.countDown();
+
+        try {
+            finishLatch.await();
+        } catch (InterruptedException e) {
+            fail(String.format("Test threads interrupted, exception: %s", e));
+        }
+        int numOfSuccess = 0;
+
+        for (ListenableFuture<Void> result : results) {
+            try {
+                Futures.getUnchecked(result);
+                numOfSuccess++;
+            } catch (UncheckedExecutionException e) {
+                if (!e.getCause().getClass().equals(StateTransitionException.class)) {
+                    throw e;
+                }
+                // We expect ONLY 1 thread to successfully return the next state, so
+                // most of the results returned will produce a StateTransitionException as expected.
+            }
+        }
+        assertEquals(1, numOfSuccess);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/RolePolicyHandlerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/RolePolicyHandlerTest.java
new file mode 100644
index 0000000..a4f6afd
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/RolePolicyHandlerTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+import android.os.Bundle;
+import android.os.OutcomeReceiver;
+
+import com.android.devicelockcontroller.SystemDeviceLockManager;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class RolePolicyHandlerTest {
+    private static final String TEST_KIOSK_PACKAGE = "test.package1";
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private SystemDeviceLockManager mSystemDeviceLockManager;
+
+    private RolePolicyHandler mHandler;
+
+    @Before
+    public void setUp() throws ExecutionException, InterruptedException {
+        mHandler = new RolePolicyHandler(mSystemDeviceLockManager,
+                Executors.newSingleThreadExecutor());
+        setupSetupParameters();
+    }
+
+    @Test
+    public void onProvisioned_withSuccess_shouldCallExpectedServiceMethod()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnAddFinancedDeviceKioskRole(/* isSuccess =*/ true);
+
+        assertThat(mHandler.onProvisioned().get()).isTrue();
+
+        verify(mSystemDeviceLockManager).addFinancedDeviceKioskRole(eq(TEST_KIOSK_PACKAGE),
+                any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).removeFinancedDeviceKioskRole(anyString(),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onProvisioned_withFailure_shouldCallExpectedServiceMethod()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnAddFinancedDeviceKioskRole(/* isSuccess =*/ false);
+
+        assertThat(mHandler.onProvisioned().get()).isFalse();
+
+        verify(mSystemDeviceLockManager).addFinancedDeviceKioskRole(eq(TEST_KIOSK_PACKAGE),
+                any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).removeFinancedDeviceKioskRole(anyString(),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onCleared_withSuccess_shouldCallExpectedServiceMethod()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnRemoveFinancedDeviceKioskRole(/* isSuccess =*/ true);
+
+        assertThat(mHandler.onCleared().get()).isTrue();
+
+        verify(mSystemDeviceLockManager).removeFinancedDeviceKioskRole(eq(TEST_KIOSK_PACKAGE),
+                any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).addFinancedDeviceKioskRole(anyString(),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onCleared_withFailure_shouldCallExpectedServiceMethod()
+            throws ExecutionException, InterruptedException {
+        setExpectationsOnRemoveFinancedDeviceKioskRole(/* isSuccess =*/ false);
+
+        assertThat(mHandler.onCleared().get()).isFalse();
+
+        verify(mSystemDeviceLockManager).removeFinancedDeviceKioskRole(eq(TEST_KIOSK_PACKAGE),
+                any(Executor.class), any());
+        verify(mSystemDeviceLockManager, never()).addFinancedDeviceKioskRole(anyString(),
+                any(Executor.class), any());
+    }
+
+    @Test
+    public void onProvisionInProgress_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionInProgress().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+
+    @Test
+    public void onProvisionPaused_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionPaused().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onProvisionFailed_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onProvisionFailed().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onLocked_shouldDoNothing() throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onLocked().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    @Test
+    public void onUnlocked_shouldDoNothing() throws ExecutionException, InterruptedException {
+        assertThat(mHandler.onUnlocked().get()).isTrue();
+        verifyNoInteractions(mSystemDeviceLockManager);
+    }
+
+    private void setExpectationsOnAddFinancedDeviceKioskRole(boolean isSuccess) {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 2);
+            if (isSuccess) {
+                callback.onResult(/* result =*/ null);
+            } else {
+                callback.onError(new Exception());
+            }
+            return null;
+        }).when(mSystemDeviceLockManager).addFinancedDeviceKioskRole(anyString(),
+                any(Executor.class), any());
+    }
+
+    private void setExpectationsOnRemoveFinancedDeviceKioskRole(boolean isSuccess) {
+        doAnswer((Answer<Object>) invocation -> {
+            OutcomeReceiver<Void, Exception> callback = invocation.getArgument(/* callback =*/ 2);
+            if (isSuccess) {
+                callback.onResult(/* result =*/ null);
+            } else {
+                callback.onError(new Exception());
+            }
+            return null;
+        }).when(mSystemDeviceLockManager).removeFinancedDeviceKioskRole(anyString(),
+                any(Executor.class), any());
+    }
+
+    private static void setupSetupParameters() throws InterruptedException, ExecutionException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_KIOSK_PACKAGE);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/SetupControllerImplTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/SetupControllerImplTest.java
deleted file mode 100644
index 555b140..0000000
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/SetupControllerImplTest.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
-
-import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_SETUP_ACTIVITY;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_MANDATORY_PROVISION;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason.INSTALL_FAILED;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason.SETUP_FAILED;
-import static com.android.devicelockcontroller.policy.AbstractTask.ERROR_CODE_CREATE_SESSION_FAILED;
-import static com.android.devicelockcontroller.policy.SetupControllerImpl.transformErrorCodeToFailureType;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.after;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.robolectric.annotation.LooperMode.Mode.LEGACY;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.os.Bundle;
-import android.util.ArrayMap;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.lifecycle.Lifecycle.State;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.LifecycleRegistry;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.work.Configuration;
-import androidx.work.ListenableWorker;
-import androidx.work.WorkManager;
-import androidx.work.WorkerFactory;
-import androidx.work.WorkerParameters;
-import androidx.work.testing.WorkManagerTestInitHelper;
-
-import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
-import com.android.devicelockcontroller.common.DeviceLockConstants.SetupFailureReason;
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent;
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
-import com.android.devicelockcontroller.shadows.ShadowBuild;
-import com.android.devicelockcontroller.storage.SetupParametersClient;
-import com.android.devicelockcontroller.storage.SetupParametersService;
-
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.testing.TestingExecutors;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.LooperMode;
-import org.robolectric.shadows.ShadowPackageManager;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-@SuppressWarnings("UnusedMethod") //TODO: Increase test coverage with the existing helper methods.
-@LooperMode(LEGACY)
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowBuild.class})
-public final class SetupControllerImplTest {
-
-    private static final String TEST_SETUP_ACTIVITY = "packagename/.activity";
-    private static final String TEST_PACKAGE_NAME = "test.package.name";
-    public static final String DOWNLOAD_SUFFIX = "Download";
-    public static final String INSTALL_SUFFIX = "Install";
-    public static final int ASYNC_TIMEOUT_MILLIS = 500;
-
-    @Rule
-    public final MockitoRule mMocks = MockitoJUnit.rule();
-
-    private DeviceStateController mMockStateController;
-    private DevicePolicyController mMockPolicyController;
-    @Mock
-    private SetupController.SetupUpdatesCallbacks mMockCbs;
-    @Mock
-    private LifecycleOwner mMockLifecycleOwner;
-    private TestDeviceLockControllerApplication mTestApplication;
-    private String mFileLocation;
-    private SetupParametersClient mSetupParametersClient;
-    private TestWorkFactory mTestWorkFactory;
-
-    @Before
-    public void setUp() {
-        mTestApplication = ApplicationProvider.getApplicationContext();
-        mMockStateController = mTestApplication.getStateController();
-        mMockPolicyController = mTestApplication.getPolicyController();
-        when(mMockPolicyController.launchActivityInLockedMode()).thenReturn(
-                Futures.immediateFuture(true));
-        Shadows.shadowOf(mTestApplication).setComponentNameAndServiceForBindService(
-                new ComponentName(mTestApplication, SetupParametersService.class),
-                Robolectric.setupService(SetupParametersService.class).onBind(null));
-        mSetupParametersClient = SetupParametersClient.getInstance(
-                mTestApplication, TestingExecutors.sameThreadScheduledExecutor());
-        mFileLocation = mTestApplication.getFilesDir() + "/TEST_FILE_NAME";
-        createTestFile(mFileLocation);
-
-        mTestWorkFactory = new TestWorkFactory();
-        Configuration config =
-                new Configuration.Builder().setWorkerFactory(mTestWorkFactory).build();
-        WorkManagerTestInitHelper.initializeTestWorkManager(mTestApplication, config);
-    }
-
-    @Test
-    public void testInitialState_SetupFinished() {
-        Bundle b = new Bundle();
-        b.putString(EXTRA_KIOSK_SETUP_ACTIVITY, TEST_SETUP_ACTIVITY);
-        createParameters(b);
-        when(mMockStateController.getState()).thenReturn(DeviceState.KIOSK_SETUP);
-        when(mMockStateController.setNextStateForEvent(DeviceEvent.SETUP_COMPLETE)).thenReturn(
-                Futures.immediateVoidFuture());
-        SetupControllerImpl setupController =
-                new SetupControllerImpl(
-                        mTestApplication, mMockStateController, mMockPolicyController);
-        assertThat(setupController.getSetupState()).isEqualTo(
-                SetupController.SetupStatus.SETUP_FINISHED);
-        Futures.getUnchecked(setupController.finishSetup());
-        verify(mMockStateController).setNextStateForEvent(DeviceEvent.SETUP_COMPLETE);
-        verify(mMockPolicyController).launchActivityInLockedMode();
-        verify(mMockPolicyController, never()).wipeData();
-    }
-
-    @Test
-    public void testInitialState_mandatoryProvisioning_SetupFailed() {
-        Bundle bundle = new Bundle();
-        bundle.putBoolean(EXTRA_MANDATORY_PROVISION, true);
-        createParameters(bundle);
-        when(mMockStateController.getState()).thenReturn(DeviceState.SETUP_FAILED);
-        SetupControllerImpl setupController =
-                new SetupControllerImpl(
-                        mTestApplication, mMockStateController, mMockPolicyController);
-        Futures.getUnchecked(setupController.finishSetup());
-        assertThat(setupController.getSetupState()).isEqualTo(
-                SetupController.SetupStatus.SETUP_FAILED);
-        verify(mMockPolicyController, never()).launchActivityInLockedMode();
-        verify(mMockPolicyController).wipeData();
-    }
-
-    @Test
-    public void isKioskAppPreinstalled_nonDebuggableBuild_returnFalse() {
-        // GIVEN build is non-debuggable build and kiosk app is installed.
-        ShadowBuild.setIsDebuggable(false);
-        Bundle bundle = new Bundle();
-        bundle.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE_NAME);
-        createParameters(bundle);
-        ShadowPackageManager pm = Shadows.shadowOf(mTestApplication.getPackageManager());
-        PackageInfo kioskPackageInfo = new PackageInfo();
-        kioskPackageInfo.packageName = TEST_PACKAGE_NAME;
-        pm.installPackage(kioskPackageInfo);
-
-        SetupControllerImpl setupController =
-                new SetupControllerImpl(
-                        mTestApplication, mMockStateController, mMockPolicyController);
-
-        assertThat(Futures.getUnchecked(setupController.isKioskAppPreInstalled())).isFalse();
-    }
-
-    @Test
-    public void isKioskAppPreinstalled_debuggableBuild_kioskPreinstalled_returnTrue() {
-        // GIVEN build is debuggable build and kiosk app is installed
-        ShadowBuild.setIsDebuggable(true);
-        Bundle bundle = new Bundle();
-        bundle.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE_NAME);
-        createParameters(bundle);
-        ShadowPackageManager pm = Shadows.shadowOf(mTestApplication.getPackageManager());
-        PackageInfo kioskPackageInfo = new PackageInfo();
-        kioskPackageInfo.packageName = TEST_PACKAGE_NAME;
-        pm.installPackage(kioskPackageInfo);
-
-        SetupControllerImpl setupController =
-                new SetupControllerImpl(
-                        mTestApplication, mMockStateController, mMockPolicyController);
-
-
-        assertThat(Futures.getUnchecked(setupController.isKioskAppPreInstalled())).isTrue();
-    }
-
-    @Test
-    public void isKioskAppPreinstalled_debuggableBuild_kioskNotInstalled_returnFalse() {
-        // GIVEN build is debuggable build but kiosk app is not installed
-        ShadowBuild.setIsDebuggable(true);
-        Bundle bundle = new Bundle();
-        bundle.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE_NAME);
-        createParameters(bundle);
-
-        SetupControllerImpl setupController =
-                new SetupControllerImpl(
-                        mTestApplication, mMockStateController, mMockPolicyController);
-
-        assertThat(Futures.getUnchecked(setupController.isKioskAppPreInstalled())).isFalse();
-    }
-
-    @Test
-    public void installKioskAppForSecondaryUser_kioskAppInstalled_allTaskSucceed() {
-        // GIVEN all tasks succeed
-        when(mMockStateController.setNextStateForEvent(DeviceEvent.SETUP_SUCCESS)).thenReturn(
-                Futures.immediateVoidFuture());
-
-        setupLifecycle();
-        final SetupControllerImpl setupController = createSetupControllerImpl(mMockCbs);
-
-        // WHEN install kiosk app for secondary user
-        Futures.getUnchecked(setupController.installKioskAppForSecondaryUser(
-                WorkManager.getInstance(mTestApplication),
-                mMockLifecycleOwner));
-
-        verify(mMockStateController, timeout(ASYNC_TIMEOUT_MILLIS)).setNextStateForEvent(
-                eq(DeviceEvent.SETUP_SUCCESS));
-        verify(mMockCbs).setupCompleted();
-    }
-
-
-    @Test
-    public void testInitialState_SetupNotStarted() {
-        when(mMockStateController.getState()).thenReturn(DeviceState.SETUP_IN_PROGRESS);
-        SetupControllerImpl setupController =
-                new SetupControllerImpl(
-                        mTestApplication, mMockStateController, mMockPolicyController);
-        assertThat(setupController.getSetupState()).isEqualTo(
-                SetupController.SetupStatus.SETUP_NOT_STARTED);
-    }
-
-    @Test
-    public void testSetupUpdatesCallbacks_failureCallback() {
-        AtomicBoolean result = new AtomicBoolean(true);
-        AtomicInteger reason = new AtomicInteger(-1);
-        SetupController.SetupUpdatesCallbacks callbacks =
-                new SetupController.SetupUpdatesCallbacks() {
-                    @Override
-                    public void setupCompleted() {
-                    }
-
-                    @Override
-                    public void setupFailed(int failReason) {
-                        result.set(false);
-                        reason.set(failReason);
-                    }
-                };
-        when(mMockStateController.setNextStateForEvent(DeviceEvent.SETUP_FAILURE)).thenReturn(
-                Futures.immediateVoidFuture());
-        SetupControllerImpl setupController = createSetupControllerImpl(callbacks);
-        setupController.setupFlowTaskFailureCallbackHandler(SetupFailureReason.DOWNLOAD_FAILED);
-        assertThat(result.get()).isFalse();
-        assertThat(reason.get()).isEqualTo(SetupFailureReason.DOWNLOAD_FAILED);
-        assertThat(setupController.getSetupState()).isEqualTo(
-                SetupController.SetupStatus.SETUP_FAILED);
-    }
-
-    @Test
-    public void testSetupUpdatesCallbacks_successCallback() {
-        AtomicBoolean result = new AtomicBoolean(false);
-        SetupController.SetupUpdatesCallbacks callbacks =
-                new SetupController.SetupUpdatesCallbacks() {
-                    @Override
-                    public void setupCompleted() {
-                        result.set(true);
-                    }
-
-                    @Override
-                    public void setupFailed(int reason) {
-                    }
-                };
-
-        when(mMockStateController.setNextStateForEvent(DeviceEvent.SETUP_SUCCESS)).thenReturn(
-                Futures.immediateVoidFuture());
-
-        SetupControllerImpl setupController = createSetupControllerImpl(callbacks);
-        setupController.setupFlowTaskSuccessCallbackHandler();
-        assertThat(result.get()).isTrue();
-        assertThat(setupController.getSetupState()).isEqualTo(
-                SetupController.SetupStatus.SETUP_FINISHED);
-    }
-
-    @Test
-    public void testSetupUpdatesCallbacks_removeListener() {
-        SetupControllerImpl setupController = createSetupControllerImpl(mMockCbs);
-        setupController.removeListener(mMockCbs);
-        when(mMockStateController.setNextStateForEvent(DeviceEvent.SETUP_SUCCESS)).thenReturn(
-                Futures.immediateVoidFuture());
-
-        setupController.setupFlowTaskSuccessCallbackHandler();
-        verify(mMockCbs, after(ASYNC_TIMEOUT_MILLIS).never()).setupCompleted();
-    }
-
-    @Test
-    public void testTransformErrorCodeToFailureType() {
-        assertThat(transformErrorCodeToFailureType(ERROR_CODE_CREATE_SESSION_FAILED))
-                .isEqualTo(INSTALL_FAILED);
-        int invalidErrorCode = 100;
-        assertThat(transformErrorCodeToFailureType(invalidErrorCode)).isEqualTo(SETUP_FAILED);
-    }
-
-    private static void createTestFile(String fileLocation) {
-        try (FileOutputStream outputStream = new FileOutputStream(fileLocation)) {
-            outputStream.write(new byte[]{1, 2, 3, 4, 5});
-        } catch (IOException e) {
-            throw new AssertionError("Exception", e);
-        }
-    }
-
-    private void createParameters(Bundle b) {
-        try {
-            Futures.getChecked(mSetupParametersClient.createPrefs(b), ExecutionException.class);
-        } catch (ExecutionException e) {
-            throw new AssertionError("Failed to create setup parameters!", e);
-        }
-    }
-
-    private void setupLifecycle() {
-        LifecycleRegistry mockLifecycle = new LifecycleRegistry(mMockLifecycleOwner);
-        mockLifecycle.setCurrentState(State.RESUMED);
-        when(mMockLifecycleOwner.getLifecycle()).thenReturn(mockLifecycle);
-    }
-
-    private SetupControllerImpl createSetupControllerImpl(
-            SetupController.SetupUpdatesCallbacks callbacks) {
-        SetupControllerImpl setupController =
-                new SetupControllerImpl(mTestApplication, mMockStateController,
-                        mMockPolicyController);
-        setupController.addListener(callbacks);
-        return setupController;
-    }
-
-    private final class TestWorkFactory extends WorkerFactory {
-
-        private final ListeningExecutorService mExecutorService;
-
-        private final ArrayMap<String, Integer> mResultMap =
-                new ArrayMap<>();
-
-        TestWorkFactory() {
-            mExecutorService = TestingExecutors.sameThreadScheduledExecutor();
-        }
-
-        @Nullable
-        @Override
-        public ListenableWorker createWorker(
-                @NonNull Context context,
-                @NonNull String workerClassName,
-                @NonNull WorkerParameters workerParameters) {
-            return new AbstractTask(context, workerParameters) {
-                @NonNull
-                @Override
-                public ListenableFuture<Result> startWork() {
-                    return mExecutorService.submit(() -> {
-                        final Integer resultCode = mResultMap.get(workerClassName);
-                        return resultCode == null || resultCode < 0
-                                ? Result.success() : failure(resultCode);
-                    });
-                }
-            };
-        }
-    }
-}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/StartLockTaskModeWorkerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/StartLockTaskModeWorkerTest.java
new file mode 100644
index 0000000..48ae6ba
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/StartLockTaskModeWorkerTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.devicelockcontroller.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.ActivityManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.annotation.NonNull;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.work.ListenableWorker;
+import androidx.work.ListenableWorker.Result;
+import androidx.work.WorkerFactory;
+import androidx.work.WorkerParameters;
+import androidx.work.testing.TestListenableWorkerBuilder;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.testing.TestingExecutors;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.Executors;
+
+/**
+ * Tests for {@link StartLockTaskModeWorker}
+ */
+@RunWith(RobolectricTestRunner.class)
+public final class StartLockTaskModeWorkerTest {
+
+    private static final String PACKAGE_NAME = "test.package";
+    private static final String COMPONENT_CLASS_NAME = "TestActivity";
+
+    @Rule
+    public final MockitoRule mMocks = MockitoJUnit.rule();
+
+    private final ListeningExecutorService mBgExecutor =
+            MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
+
+    // Mock of DevicePolicyManager. Cannot use shadow as shadow requires a non-null admin even
+    // though the real implementation allows nullable admin
+    @Mock
+    private DevicePolicyManager mDpm;
+    // Mock of ActivityManager. Cannot use shadow as we need to modify behavior before and after
+    // activity start since the shadow context does not change the lock task state
+    @Mock
+    private ActivityManager mAm;
+    private TestDeviceLockControllerApplication mTestApp;
+    private DevicePolicyController mDevicePolicyController;
+    private Intent mLockTaskIntent;
+    private StartLockTaskModeWorker mWorker;
+
+    @Before
+    public void setUp() throws Exception {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        mWorker = TestListenableWorkerBuilder.from(mTestApp, StartLockTaskModeWorker.class)
+                .setWorkerFactory(
+                        new WorkerFactory() {
+                            @Override
+                            public ListenableWorker createWorker(
+                                    @NonNull Context context, @NonNull String workerClassName,
+                                    @NonNull WorkerParameters workerParameters) {
+                                return workerClassName.equals(
+                                        StartLockTaskModeWorker.class.getName())
+                                        ? new StartLockTaskModeWorker(mTestApp,
+                                                mDpm,
+                                                mAm,
+                                                workerParameters,
+                                                TestingExecutors.sameThreadScheduledExecutor())
+                                        : null /* worker */;
+                            }
+                        }
+                ).build();
+
+        shadowOf(mTestApp.getSystemService(ActivityManager.class)).setLockTaskModeState(
+                ActivityManager.LOCK_TASK_MODE_NONE);
+        mLockTaskIntent = new Intent()
+                .setComponent(new ComponentName(PACKAGE_NAME, COMPONENT_CLASS_NAME));
+        mDevicePolicyController = mTestApp.getPolicyController();
+        when(mDevicePolicyController.getLaunchIntentForCurrentState()).thenReturn(
+                Futures.immediateFuture(mLockTaskIntent));
+        when(mDevicePolicyController.enforceCurrentPoliciesForCriticalFailure()).thenReturn(
+                Futures.immediateVoidFuture());
+        when(mDpm.isLockTaskPermitted(PACKAGE_NAME)).thenReturn(true);
+    }
+
+    @Test
+    public void doWork_launchesActivityInLockedTaskMode() throws Exception {
+        // GIVEN device is not locked and then locked after worker finishes
+        when(mAm.getLockTaskModeState())
+                .thenReturn(ActivityManager.LOCK_TASK_MODE_NONE)
+                .thenReturn(ActivityManager.LOCK_TASK_MODE_LOCKED);
+
+        // WHEN the work finishes
+        final Result result = mBgExecutor.submit(() -> mWorker.startWork().get()).get();
+
+        // THEN the launched intent starts with the lock task flag
+        assertThat(result).isEqualTo(Result.success());
+        Intent launchedIntent = shadowOf(mTestApp).getNextStartedActivity();
+        assertThat(launchedIntent.getPackage()).isEqualTo(mLockTaskIntent.getPackage());
+        assertThat(launchedIntent.getComponent()).isEqualTo(mLockTaskIntent.getComponent());
+        assertThat(launchedIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK).isNotEqualTo(0);
+        assertThat(launchedIntent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_TASK).isNotEqualTo(0);
+        verify(mDpm).addPersistentPreferredActivity(any(), any(),
+                eq(launchedIntent.getComponent()));
+    }
+
+    @Test
+    public void doWork_hitsException_failsAndEnforcesCriticalFailure() throws Exception {
+        // GIVEN device is not locked and getting intent throws exception
+        when(mAm.getLockTaskModeState())
+                .thenReturn(ActivityManager.LOCK_TASK_MODE_NONE);
+        when(mDevicePolicyController.getLaunchIntentForCurrentState()).thenThrow(
+                new RuntimeException());
+
+        // WHEN the work finishes
+        final Result result = mBgExecutor.submit(() -> mWorker.startWork().get()).get();
+
+        // THEN we enforce a critical failure
+        assertThat(result).isEqualTo(Result.failure());
+        verify(mDevicePolicyController).enforceCurrentPoliciesForCriticalFailure();
+    }
+
+    @Test
+    public void doWork_alreadyLockedDoesNothing() throws Exception {
+        // GIVEN device is already locked
+        when(mAm.getLockTaskModeState())
+                .thenReturn(ActivityManager.LOCK_TASK_MODE_LOCKED);
+
+        // WHEN the work finishes
+        final Result result = mBgExecutor.submit(() -> mWorker.startWork().get()).get();
+
+        // THEN the work succeeds and there is no launched intent
+        assertThat(result).isEqualTo(Result.success());
+        Intent launchedIntent = shadowOf(mTestApp).getNextStartedActivity();
+        assertThat(launchedIntent).isNull();
+    }
+
+    @Test
+    public void doWork_failsWhenNoLaunchIntent() throws Exception {
+        // GIVEN device is not locked and launch intent is null
+        when(mAm.getLockTaskModeState())
+                .thenReturn(ActivityManager.LOCK_TASK_MODE_NONE);
+        when(mDevicePolicyController.getLaunchIntentForCurrentState()).thenReturn(null);
+
+        // WHEN the work finishes
+        final Result result = mBgExecutor.submit(() -> mWorker.startWork().get()).get();
+
+        // THEN the work fails
+        assertThat(result).isEqualTo(Result.failure());
+    }
+
+    @Test
+    public void doWork_failsLaunchIntentNotPermitted() throws Exception {
+        // GIVEN device is not locked and launch intent package is not permitted
+        when(mAm.getLockTaskModeState())
+                .thenReturn(ActivityManager.LOCK_TASK_MODE_NONE);
+        when(mDpm.isLockTaskPermitted(PACKAGE_NAME)).thenReturn(false);
+
+        // WHEN the work finishes
+        final Result result = mBgExecutor.submit(() -> mWorker.startWork().get()).get();
+
+        // THEN the work fails
+        assertThat(result).isEqualTo(Result.failure());
+    }
+
+    @Test
+    public void doWork_retriesIfNotInLockTaskMode() throws Exception {
+        // GIVEN device is not locked and still not locked after worker finishes
+        when(mAm.getLockTaskModeState())
+                .thenReturn(ActivityManager.LOCK_TASK_MODE_NONE)
+                .thenReturn(ActivityManager.LOCK_TASK_MODE_NONE);
+
+        // WHEN the work finishes
+        final Result result = mBgExecutor.submit(() -> mWorker.startWork().get()).get();
+
+        // THEN the work retries
+        assertThat(result).isEqualTo(Result.retry());
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/UserRestrictionsPolicyHandlerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/UserRestrictionsPolicyHandlerTest.java
new file mode 100644
index 0000000..be490ed
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/policy/UserRestrictionsPolicyHandlerTest.java
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.policy;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_DISALLOW_INSTALLING_FROM_UNKNOWN_SOURCES;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_DISABLE_OUTGOING_CALLS;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.os.Bundle;
+import android.os.UserManager;
+
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public final class UserRestrictionsPolicyHandlerTest {
+    private static final String TEST_PACKAGE = "test.package1";
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Mock
+    private DevicePolicyManager mMockDpm;
+    @Mock
+    private UserManager mMockUserManager;
+    @Captor
+    private ArgumentCaptor<String> mSetUserRestrictionCaptor;
+    @Captor
+    private ArgumentCaptor<String> mClearUserRestrictionCaptor;
+
+    @Test
+    public void onProvisionInProgressDebug_withoutKioskPackageName_shouldThrowException() {
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ true,
+                Executors.newSingleThreadExecutor());
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> handler.onProvisionInProgress().get());
+
+        assertThat(thrown).hasCauseThat().isInstanceOf(IllegalStateException.class);
+        assertThat(thrown).hasMessageThat().contains("Setup parameters does not exist!");
+    }
+
+    @Test
+    public void onProvisionInProgress_withoutKioskPackageName_shouldThrowException() {
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        ExecutionException thrown = assertThrows(ExecutionException.class,
+                () -> handler.onProvisionInProgress().get());
+
+        assertThat(thrown).hasCauseThat().isInstanceOf(IllegalStateException.class);
+        assertThat(thrown).hasMessageThat().contains("Setup parameters does not exist!");
+    }
+
+    @Test
+    public void onProvisionInProgressDebug_withSetExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ true,
+                Executors.newSingleThreadExecutor());
+
+        handler.onProvisionInProgress().get();
+
+        verify(mMockDpm).addUserRestriction(eq(null), mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT});
+        verify(mMockDpm, never()).clearUserRestriction(eq(null),
+                mClearUserRestrictionCaptor.capture());
+    }
+
+    @Test
+    public void onProvisionInProgress_withSetExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onProvisionInProgress().get();
+
+        verify(mMockDpm, times(2)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_DEBUGGING_FEATURES});
+    }
+
+    @Test
+    public void onProvisionInProgress_withDisableOutgoingCallShouldSetExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        preferences.putBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS, true);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onProvisionInProgress().get();
+
+        verify(mMockDpm, times(2)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_DEBUGGING_FEATURES});
+    }
+
+    @Test
+    public void onProvisionInProgress_withDisallowUnknownSourcesShouldSetExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        preferences.putBoolean(EXTRA_DISALLOW_INSTALLING_FROM_UNKNOWN_SOURCES, true);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onProvisionInProgress().get();
+
+        verify(mMockDpm, times(3)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_DEBUGGING_FEATURES,
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES});
+    }
+
+    @Test
+    public void onLockedDebug_withDisableOutgoingCallShouldSetExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        preferences.putBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS, true);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ true,
+                Executors.newSingleThreadExecutor());
+
+        handler.onLocked().get();
+
+        verify(mMockDpm, times(2)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_OUTGOING_CALLS});
+        verify(mMockDpm, never()).clearUserRestriction(eq(null),
+                mClearUserRestrictionCaptor.capture());
+    }
+
+    @Test
+    public void onLocked_withDisableOutgoingCallShouldSetExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        preferences.putBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS, true);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onLocked().get();
+
+        verify(mMockDpm, times(3)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_DEBUGGING_FEATURES,
+                        UserManager.DISALLOW_OUTGOING_CALLS});
+    }
+
+    @Test
+    public void onLocked_withDisableOutgoingCallAndUnknownSourcesShouldSetExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onLocked().get();
+
+        verify(mMockDpm, times(4)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_DEBUGGING_FEATURES,
+                        UserManager.DISALLOW_OUTGOING_CALLS,
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES});
+    }
+
+    @Test
+    public void onCleared_shouldClearExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onLocked().get();
+
+        verify(mMockDpm, times(4)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_DEBUGGING_FEATURES,
+                        UserManager.DISALLOW_OUTGOING_CALLS,
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES});
+
+        userRestrictions.putBoolean(UserManager.DISALLOW_SAFE_BOOT, true);
+        userRestrictions.putBoolean(UserManager.DISALLOW_DEBUGGING_FEATURES, true);
+        userRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
+        userRestrictions.putBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+        reset(mMockDpm);
+
+        handler.onCleared().get();
+
+        verify(mMockDpm, times(4)).clearUserRestriction(eq(null),
+                mClearUserRestrictionCaptor.capture());
+        List<String> allClearRestrictions = mClearUserRestrictionCaptor.getAllValues();
+        assertThat(allClearRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_DEBUGGING_FEATURES,
+                        UserManager.DISALLOW_OUTGOING_CALLS,
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES});
+    }
+
+    @Test
+    public void onClearedDebug_shouldClearExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ true,
+                Executors.newSingleThreadExecutor());
+
+        handler.onLocked().get();
+        verify(mMockDpm, times(3)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_OUTGOING_CALLS,
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES});
+        verify(mMockDpm, never()).clearUserRestriction(eq(null),
+                mClearUserRestrictionCaptor.capture());
+
+        userRestrictions.putBoolean(UserManager.DISALLOW_SAFE_BOOT, true);
+        userRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
+        userRestrictions.putBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+        reset(mMockDpm);
+
+        handler.onCleared().get();
+
+        verify(mMockDpm, times(3)).clearUserRestriction(eq(null),
+                mClearUserRestrictionCaptor.capture());
+        List<String> allClearRestrictions = mClearUserRestrictionCaptor.getAllValues();
+        assertThat(allClearRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_OUTGOING_CALLS,
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES});
+    }
+
+    @Test
+    public void onUnlockedDebug_withDisableOutgoingCallShouldSetExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        preferences.putBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS, true);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ true,
+                Executors.newSingleThreadExecutor());
+
+        handler.onUnlocked().get();
+
+        verify(mMockDpm, times(1)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT});
+        verify(mMockDpm, never()).clearUserRestriction(eq(null),
+                mClearUserRestrictionCaptor.capture());
+    }
+
+    @Test
+    public void onUnlocked_withDisableOutgoingCallShouldSetExpectedUserRestrictions()
+            throws ExecutionException, InterruptedException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        preferences.putBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS, true);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onUnlocked().get();
+
+        verify(mMockDpm, times(2)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_DEBUGGING_FEATURES});
+    }
+
+    @Test
+    public void onUnlocked_withDisableOutgoingCallAndUnknownSourcesShouldSetExpectedRestrictions()
+            throws ExecutionException, InterruptedException {
+        setupSetupParameters();
+
+        Bundle userRestrictions = new Bundle();
+        when(mMockUserManager.getUserRestrictions()).thenReturn(userRestrictions);
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onUnlocked().get();
+
+        verify(mMockDpm, times(3)).addUserRestriction(eq(null),
+                mSetUserRestrictionCaptor.capture());
+        List<String> allUserRestrictions = mSetUserRestrictionCaptor.getAllValues();
+        assertThat(allUserRestrictions).containsExactlyElementsIn(
+                new String[]{UserManager.DISALLOW_SAFE_BOOT,
+                        UserManager.DISALLOW_DEBUGGING_FEATURES,
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES});
+    }
+
+    @Test
+    public void onProvisionPaused_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onProvisionPaused().get();
+
+        verifyNoInteractions(mMockDpm);
+        verifyNoInteractions(mMockUserManager);
+    }
+
+    @Test
+    public void onProvisionFailed_shouldDoNothing()
+            throws ExecutionException, InterruptedException {
+        UserRestrictionsPolicyHandler handler = new UserRestrictionsPolicyHandler(mMockDpm,
+                mMockUserManager,
+                /* isDebug =*/ false,
+                Executors.newSingleThreadExecutor());
+
+        handler.onProvisionFailed().get();
+
+        verifyNoInteractions(mMockDpm);
+        verifyNoInteractions(mMockUserManager);
+    }
+
+    private static void setupSetupParameters() throws InterruptedException, ExecutionException {
+        Bundle preferences = new Bundle();
+        preferences.putString(EXTRA_KIOSK_PACKAGE, TEST_PACKAGE);
+        preferences.putBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS, true);
+        preferences.putBoolean(EXTRA_DISALLOW_INSTALLING_FROM_UNKNOWN_SOURCES, true);
+        SetupParametersClient.getInstance().createPrefs(preferences).get();
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/grpc/ProvisioningConfigurationTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/grpc/ProvisioningConfigurationTest.java
new file mode 100644
index 0000000..1c9e8f2
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/grpc/ProvisioningConfigurationTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.provision.grpc;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_DISABLE_OUTGOING_CALLS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public final class ProvisioningConfigurationTest {
+    @Test
+    public void configurationToBundle_withOutgoingCallsDisabled_shouldStoreCorrectState() {
+        final Bundle configurationBundle =
+                createProvisioningConfiguration(/* enableOutgoingCalls= */ false).toBundle();
+        assertThat(configurationBundle.getBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS)).isTrue();
+    }
+
+    @Test
+    public void configurationToBundle_withOutgoingCallsEnabled_shouldStoreCorrectState() {
+        final Bundle configurationBundle =
+                createProvisioningConfiguration(/* enableOutgoingCalls= */ true).toBundle();
+        assertThat(configurationBundle.getBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS)).isFalse();
+    }
+
+    private static ProvisioningConfiguration createProvisioningConfiguration(
+            boolean enableOutgoingCalls) {
+        return new ProvisioningConfiguration(
+                /* kioskAppProviderName= */ "test_provider",
+                /* kioskAppPackageName= */ "test_package",
+                /* kioskAppAllowlistPackages= */ List.of("test_allowed_app1", "test_allowed_app2"),
+                enableOutgoingCalls,
+                /* kioskAppEnableEnableNotifications= */ true,
+                /* disallowInstallingFromUnknownSources= */ false,
+                /* termsAndConditionsUrl= */ "test_terms_and_configurations_url",
+                /* supportUrl= */ "test_support_url"
+        );
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInHelperTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInHelperTest.java
index 1773d2d..a78cde5 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInHelperTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInHelperTest.java
@@ -16,39 +16,43 @@
 
 package com.android.devicelockcontroller.provision.worker;
 
+import static android.os.Looper.getMainLooper;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceIdType.DEVICE_ID_TYPE_IMEI;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceIdType.DEVICE_ID_TYPE_MEID;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.READY_FOR_PROVISION;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.RETRY_CHECK_IN;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.STOP_CHECK_IN;
+import static com.android.devicelockcontroller.stats.StatsLogger.CheckInRetryReason.CONFIG_UNAVAILABLE;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.robolectric.annotation.LooperMode.Mode.LEGACY;
 
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
 import android.telephony.TelephonyManager;
 import android.util.ArraySet;
 
 import androidx.annotation.Nullable;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.work.Configuration;
-import androidx.work.WorkInfo;
-import androidx.work.WorkManager;
 import androidx.work.testing.SynchronousExecutor;
 import androidx.work.testing.WorkManagerTestInitHelper;
 
 import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
 import com.android.devicelockcontroller.common.DeviceId;
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceCheckInStatus;
-import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent;
+import com.android.devicelockcontroller.policy.FinalizationController;
 import com.android.devicelockcontroller.provision.grpc.GetDeviceCheckInStatusGrpcResponse;
 import com.android.devicelockcontroller.provision.grpc.ProvisioningConfiguration;
+import com.android.devicelockcontroller.receivers.ProvisionReadyReceiver;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
 import com.android.devicelockcontroller.storage.GlobalParametersClient;
 
 import com.google.common.util.concurrent.Futures;
@@ -60,15 +64,13 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.Shadows;
 import org.robolectric.annotation.LooperMode;
+import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.shadows.ShadowTelephonyManager;
 
 import java.time.Duration;
 import java.time.Instant;
 import java.util.List;
 import java.util.Objects;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
 @LooperMode(LEGACY)
 @RunWith(RobolectricTestRunner.class)
@@ -77,7 +79,6 @@
     static final Duration TEST_NEGATIVE_CHECK_RETRY_DURATION =
             Duration.ZERO.minus(TEST_CHECK_RETRY_DURATION);
     public static final boolean IS_PROVISIONING_MANDATORY = false;
-    private static final int GET_WORK_INFO_TIMEOUT_MILLIS = 500;
     private TestDeviceLockControllerApplication mTestApplication;
     static final int TOTAL_SLOT_COUNT = 2;
     static final int TOTAL_ID_COUNT = 4;
@@ -95,7 +96,6 @@
     static final ProvisioningConfiguration TEST_CONFIGURATION = new ProvisioningConfiguration(
             /* kioskAppProviderName= */ "test_provider",
             /* kioskAppPackageName= */ "test_package",
-            /* kioskAppMainActivity= */ "test_activity",
             /* kioskAppAllowlistPackages= */ List.of("test_allowed_app1", "test_allowed_app2"),
             /* kioskAppEnableOutgoingCalls= */ false,
             /* kioskAppEnableEnableNotifications= */ true,
@@ -105,14 +105,23 @@
     );
     static final int DEVICE_ID_TYPE_BITMAP =
             (1 << DEVICE_ID_TYPE_IMEI) | (1 << DEVICE_ID_TYPE_MEID);
+
+    private FinalizationController mFinalizationController;
     private DeviceCheckInHelper mHelper;
 
     private ShadowTelephonyManager mTelephonyManager;
     private GlobalParametersClient mGlobalParametersClient;
+    private DeviceLockControllerScheduler mScheduler;
+    private StatsLogger mStatsLogger;
+    private ShadowPackageManager mPackageManager;
 
     @Before
     public void setUp() {
         mTestApplication = ApplicationProvider.getApplicationContext();
+        mScheduler = mTestApplication.getDeviceLockControllerScheduler();
+        mFinalizationController = mTestApplication.getFinalizationController();
+        when(mFinalizationController.notifyRestrictionsCleared()).thenReturn(
+                Futures.immediateVoidFuture());
 
         mTelephonyManager = Shadows.shadowOf(
                 mTestApplication.getSystemService(TelephonyManager.class));
@@ -123,10 +132,16 @@
                         .setExecutor(new SynchronousExecutor())
                         .build());
         mGlobalParametersClient = GlobalParametersClient.getInstance();
+        mStatsLogger = ((StatsLoggerProvider) mTestApplication).getStatsLogger();
+        mPackageManager = Shadows.shadowOf(mTestApplication.getPackageManager());
     }
 
     @Test
     public void getDeviceAvailableUniqueIds_shouldReturnAllAvailableUniqueIds() {
+        mPackageManager.setSystemFeature(PackageManager.FEATURE_TELEPHONY_GSM,
+                /* supported= */ true);
+        mPackageManager.setSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA,
+                /* supported= */ true);
         mTelephonyManager.setActiveModemCount(TOTAL_SLOT_COUNT);
         mTelephonyManager.setImei(/* slotIndex= */ 0, IMEI_1);
         mTelephonyManager.setImei(/* slotIndex= */ 1, IMEI_2);
@@ -139,73 +154,70 @@
     }
 
     @Test
-    public void testHandleGetDeviceCheckInStatusResponse_stopCheckIn_shouldSetNeedCheckInFalse() {
+    public void testHandleGetDeviceCheckInStatusResponse_stopCheckIn_clearsRestrictions() {
         final GetDeviceCheckInStatusGrpcResponse response = createStopResponse();
 
-        assertThat(mHelper.handleGetDeviceCheckInStatusResponse(response)).isTrue();
-        assertThat(Futures.getUnchecked(mGlobalParametersClient.needCheckIn())).isFalse();
+        assertThat(mHelper.handleGetDeviceCheckInStatusResponse(response,
+                mock(DeviceLockControllerScheduler.class))).isTrue();
+        Shadows.shadowOf(getMainLooper()).idle();
+        verify(mFinalizationController).notifyRestrictionsCleared();
     }
 
     @Test
-    public void
-            handleProvisionReadyResponse_validConfiguration_shouldSetStateAndStartLockTaskMode() {
+    public void handleProvisionReadyResponse_validConfiguration_shouldSendBroadcast() {
         GetDeviceCheckInStatusGrpcResponse response = createReadyResponse(TEST_CONFIGURATION);
-        DeviceStateController stateController = mTestApplication.getStateController();
-        DevicePolicyController policyController = mTestApplication.getPolicyController();
-        when(stateController.setNextStateForEvent(DeviceEvent.PROVISIONING_SUCCESS)).thenReturn(
-                Futures.immediateVoidFuture());
 
-        assertThat(mHelper.handleProvisionReadyResponse(
-                response, stateController, policyController)).isTrue();
+        assertThat(mHelper.handleProvisionReadyResponse(response)).isTrue();
 
-        verify(stateController).setNextStateForEvent(eq(DeviceEvent.PROVISIONING_SUCCESS));
-        verify(policyController).enqueueStartLockTaskModeWorker(eq(IS_PROVISIONING_MANDATORY));
-        assertThat(Futures.getUnchecked(mGlobalParametersClient.needCheckIn())).isFalse();
+        assertThat(Futures.getUnchecked(mGlobalParametersClient.isProvisionReady())).isTrue();
+        List<Intent> intents = Shadows.shadowOf(mTestApplication).getBroadcastIntents();
+        assertThat(intents.size()).isEqualTo(1);
+        assertThat(intents.get(0).getComponent().getClassName()).isEqualTo(
+                ProvisionReadyReceiver.class.getName());
     }
 
     @Test
-    public void testHandleProvisionReadyResponse_invalidConfiguration_shouldNotSetState() {
+    public void testHandleProvisionReadyResponse_invalidConfiguration_shouldNotSendBroadcast() {
         GetDeviceCheckInStatusGrpcResponse response = createReadyResponse(
                 /* configuration= */ null);
-        DeviceStateController stateController = mTestApplication.getStateController();
-        DevicePolicyController policyController = mTestApplication.getPolicyController();
 
-        assertThat(mHelper.handleProvisionReadyResponse(
-                response, stateController, policyController)).isFalse();
+        assertThat(mHelper.handleProvisionReadyResponse(response)).isFalse();
 
-        verify(stateController, never()).setNextStateForEvent(eq(DeviceEvent.PROVISIONING_SUCCESS));
+        assertThat(Futures.getUnchecked(mGlobalParametersClient.isProvisionReady())).isFalse();
+        List<Intent> intents = Shadows.shadowOf(mTestApplication).getBroadcastIntents();
+        assertThat(intents.size()).isEqualTo(0);
     }
 
     @Test
-    public void testHandleGetDeviceCheckInStatusResponse_retryCheckIn_shouldEnqueueNewCheckInWork()
-            throws ExecutionException, InterruptedException, TimeoutException {
-        final GetDeviceCheckInStatusGrpcResponse response = createRetryResponse(
-                Instant.now().plus(TEST_CHECK_RETRY_DURATION));
+    public void handleProvisionReadyResponse_invalidConfiguration_shouldLogRetryCheckIn() {
+        GetDeviceCheckInStatusGrpcResponse response = createReadyResponse(
+                /* configuration= */ null);
 
-        assertThat(mHelper.handleGetDeviceCheckInStatusResponse(response)).isTrue();
+        mHelper.handleProvisionReadyResponse(response);
 
-        WorkManager workManager = WorkManager.getInstance(mTestApplication);
-
-        List<WorkInfo> workInfo = workManager.getWorkInfosForUniqueWork(
-                DeviceCheckInHelper.CHECK_IN_WORK_NAME).get(GET_WORK_INFO_TIMEOUT_MILLIS,
-                TimeUnit.MILLISECONDS);
-        assertThat(workInfo.size()).isEqualTo(1);
+        verify(mStatsLogger).logCheckInRetry(CONFIG_UNAVAILABLE);
     }
 
     @Test
-    public void handleGetDeviceCheckInStatusResponse_retryCheckIn_durationIsNegative_shouldRetry()
-            throws ExecutionException, InterruptedException, TimeoutException {
+    public void testHandleGetDeviceCheckInStatusResponse_retryCheckIn_shouldScheduleRetryWork() {
         final GetDeviceCheckInStatusGrpcResponse response = createRetryResponse(
-                Instant.now().plus(TEST_NEGATIVE_CHECK_RETRY_DURATION));
+                SystemClock.currentNetworkTimeClock().instant().plus(TEST_CHECK_RETRY_DURATION));
 
-        assertThat(mHelper.handleGetDeviceCheckInStatusResponse(response)).isTrue();
+        assertThat(mHelper.handleGetDeviceCheckInStatusResponse(response, mScheduler)).isTrue();
 
-        WorkManager workManager = WorkManager.getInstance(mTestApplication);
+        verify(mScheduler).scheduleRetryCheckInWork(eq(TEST_CHECK_RETRY_DURATION));
+    }
 
-        List<WorkInfo> workInfo = workManager.getWorkInfosForUniqueWork(
-                DeviceCheckInHelper.CHECK_IN_WORK_NAME).get(GET_WORK_INFO_TIMEOUT_MILLIS,
-                TimeUnit.MILLISECONDS);
-        assertThat(workInfo.size()).isEqualTo(1);
+    @Test
+    public void handleGetDeviceCheckInStatusResponse_retryCheckIn_durationIsNegative_shouldRetry() {
+        final GetDeviceCheckInStatusGrpcResponse response = createRetryResponse(
+                SystemClock.currentNetworkTimeClock().instant().plus(
+                        TEST_NEGATIVE_CHECK_RETRY_DURATION));
+
+        assertThat(mHelper.handleGetDeviceCheckInStatusResponse(response, mScheduler)).isTrue();
+
+        verify(mScheduler).scheduleRetryCheckInWork(eq(Duration.ZERO));
+
     }
 
     private static GetDeviceCheckInStatusGrpcResponse createStopResponse() {
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInWorkerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInWorkerTest.java
index 449dadd..b2b7c34 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInWorkerTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/DeviceCheckInWorkerTest.java
@@ -17,9 +17,11 @@
 package com.android.devicelockcontroller.provision.worker;
 
 import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceIdType.DEVICE_ID_TYPE_IMEI;
+import static com.android.devicelockcontroller.provision.worker.DeviceCheckInWorker.RETRY_ON_FAILURE_DELAY;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
@@ -27,7 +29,9 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.util.ArraySet;
 
 import androidx.annotation.NonNull;
@@ -36,11 +40,19 @@
 import androidx.work.ListenableWorker.Result;
 import androidx.work.WorkerFactory;
 import androidx.work.WorkerParameters;
-import androidx.work.testing.TestWorkerBuilder;
+import androidx.work.testing.TestListenableWorkerBuilder;
 
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
 import com.android.devicelockcontroller.common.DeviceId;
 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
 import com.android.devicelockcontroller.provision.grpc.GetDeviceCheckInStatusGrpcResponse;
+import com.android.devicelockcontroller.receivers.CheckInBootCompletedReceiver;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.testing.TestingExecutors;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -51,9 +63,6 @@
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
 
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
 @RunWith(RobolectricTestRunner.class)
 public class DeviceCheckInWorkerTest {
     public static final ArraySet<DeviceId> TEST_DEVICE_IDS = new ArraySet<>(
@@ -69,16 +78,16 @@
     private DeviceCheckInClient mClient;
     @Mock
     private GetDeviceCheckInStatusGrpcResponse mResponse;
+    private StatsLogger mStatsLogger;
     private DeviceCheckInWorker mWorker;
+    private Context mContext = ApplicationProvider.getApplicationContext();
 
     @Before
     public void setUp() throws Exception {
-        final Context context = ApplicationProvider.getApplicationContext();
-        final Executor executor = Executors.newSingleThreadExecutor();
         when(mClient.getDeviceCheckInStatus(
                 eq(TEST_DEVICE_IDS), anyString(), isNull())).thenReturn(mResponse);
-        mWorker = TestWorkerBuilder.from(
-                        context, DeviceCheckInWorker.class, executor)
+        mWorker = TestListenableWorkerBuilder.from(
+                        mContext, DeviceCheckInWorker.class)
                 .setWorkerFactory(
                         new WorkerFactory() {
                             @Override
@@ -87,36 +96,107 @@
                                     @NonNull WorkerParameters workerParameters) {
                                 return workerClassName.equals(DeviceCheckInWorker.class.getName())
                                         ? new DeviceCheckInWorker(
-                                        context, workerParameters, mHelper, mClient)
+                                        context, workerParameters, mHelper, mClient,
+                                        TestingExecutors.sameThreadScheduledExecutor())
                                         : null;
                             }
                         }).build();
+        StatsLoggerProvider loggerProvider =
+                (StatsLoggerProvider) mContext.getApplicationContext();
+        mStatsLogger = loggerProvider.getStatsLogger();
     }
 
+
     @Test
-    public void checkIn_allInfoAvailable_checkInResponseSuccessful_succeeded() {
+    public void checkIn_allInfoAvailable_checkInResponseSuccessfulAndHandleable_successAndLogged() {
         // GIVEN all device info available
-        setDeviceIdAvailability(true);
-        setCarrierInfoAvailability(true);
+        setDeviceIdAvailability(/* isAvailable= */ true);
+        setCarrierInfoAvailability(/* isAvailable= */ true);
 
         // GIVEN check-in response is successful
-        setCheckInRequestSuccessful();
+        setUpSuccessfulCheckInResponse(/* isHandleable= */ true);
 
         // WHEN work runs
-        final Result result = mWorker.doWork();
+        final Result result = Futures.getUnchecked(mWorker.startWork());
 
         // THEN work succeeded
         assertThat(result).isEqualTo(Result.success());
+        // THEN check in request was logged
+        verify(mStatsLogger).logGetDeviceCheckInStatus();
+        verify(mStatsLogger).logSuccessfulCheckIn();
+    }
+
+    @Test
+    public void checkIn_allInfoAvailable_checkInResponseSuccessfulNotHandleable_retryAndLogged() {
+        // GIVEN all device info available
+        setDeviceIdAvailability(/* isAvailable= */ true);
+        setCarrierInfoAvailability(/* isAvailable= */ true);
+
+        // GIVEN check-in response is successful
+        setUpSuccessfulCheckInResponse(/* isHandleable= */ false);
+
+        // WHEN work runs
+        final Result result = Futures.getUnchecked(mWorker.startWork());
+
+        // THEN work succeeded
+        assertThat(result).isEqualTo(Result.retry());
+        // THEN check in request was logged, but successful check in is NOT
+        verify(mStatsLogger).logGetDeviceCheckInStatus();
+        verify(mStatsLogger, never()).logSuccessfulCheckIn();
+    }
+
+    @Test
+    public void checkIn_allInfoAvailable_checkInResponseHasRecoverableError_retryAndLogCheckIn() {
+        // GIVEN all device info available
+        setDeviceIdAvailability(/* isAvailable= */ true);
+        setCarrierInfoAvailability(/* isAvailable= */ true);
+
+        // GIVEN check-in response has recoverable failure.
+        setUpFailedCheckInResponse(/* isRecoverable= */ true);
+
+        // WHEN work runs
+        final Result result = Futures.getUnchecked(mWorker.startWork());
+
+        // THEN work succeeded
+        assertThat(result).isEqualTo(Result.retry());
+        // THEN attempt of check in request WAS logged, but the successful check in was NOT logged.
+        verify(mStatsLogger).logGetDeviceCheckInStatus();
+        verify(mStatsLogger, never()).logSuccessfulCheckIn();
+    }
+
+    @Test
+    public void checkIn_allInfoAvailable_checkInResponseHasNonRecoverableError_failAndLogCheckIn() {
+        // GIVEN all device info available
+        setDeviceIdAvailability(/* isAvailable= */ true);
+        setCarrierInfoAvailability(/* isAvailable= */ true);
+
+        // GIVEN check-in response has non-recoverable failure.
+        setUpFailedCheckInResponse(/* isRecoverable= */ false);
+
+        // WHEN work runs
+        final Result result = Futures.getUnchecked(mWorker.startWork());
+
+        // THEN work succeeded
+        assertThat(result).isEqualTo(Result.failure());
+
+        // THEN scheduled retry work
+        DeviceLockControllerScheduler scheduler =
+                ((TestDeviceLockControllerApplication) ApplicationProvider.getApplicationContext())
+                        .getDeviceLockControllerScheduler();
+        verify(scheduler).scheduleRetryCheckInWork(eq(RETRY_ON_FAILURE_DELAY));
+        // THEN attempt of check in request WAS logged, but the successful check in was NOT logged.
+        verify(mStatsLogger).logGetDeviceCheckInStatus();
+        verify(mStatsLogger, never()).logSuccessfulCheckIn();
     }
 
     @Test
     public void checkIn_carrierInfoUnavailable_shouldAtLeastSendCheckInRequest() {
         // GIVEN only device ids available
-        setDeviceIdAvailability(true);
-        setCarrierInfoAvailability(false);
+        setDeviceIdAvailability(/* isAvailable= */ true);
+        setCarrierInfoAvailability(/* isAvailable= */ false);
 
         // WHEN work runs
-        mWorker.doWork();
+        Futures.getUnchecked(mWorker.startWork());
 
         // THEN check-in is requested
         verify(mClient).getDeviceCheckInStatus(eq(TEST_DEVICE_IDS), eq(EMPTY_CARRIER_INFO),
@@ -126,15 +206,22 @@
     @Test
     public void checkIn_deviceIdsUnavailable_shouldNotSendCheckInRequest() {
         // GIVEN only device ids available
-        setDeviceIdAvailability(false);
-        setCarrierInfoAvailability(false);
+        setDeviceIdAvailability(/* isAvailable= */ false);
+        setCarrierInfoAvailability(/* isAvailable= */ false);
 
         // WHEN work runs
-        mWorker.doWork();
+        Futures.getUnchecked(mWorker.startWork());
 
         // THEN check-in is not requested
         verify(mClient, never()).getDeviceCheckInStatus(eq(TEST_DEVICE_IDS), eq(EMPTY_CARRIER_INFO),
                 isNull());
+
+        // THEN CheckInBootCompletedReceiver should be disabled
+        assertThat(mContext.getPackageManager()
+                .getComponentEnabledSetting(new ComponentName(mContext,
+                        CheckInBootCompletedReceiver.class)))
+                .isEqualTo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+
     }
 
     private void setDeviceIdAvailability(boolean isAvailable) {
@@ -147,8 +234,15 @@
                 isAvailable ? TEST_CARRIER_INFO : EMPTY_CARRIER_INFO);
     }
 
-    private void setCheckInRequestSuccessful() {
+    private void setUpSuccessfulCheckInResponse(boolean isHandleable) {
+        when(mResponse.hasRecoverableError()).thenReturn(false);
         when(mResponse.isSuccessful()).thenReturn(true);
-        when(mHelper.handleGetDeviceCheckInStatusResponse(mResponse)).thenReturn(true);
+        when(mHelper.handleGetDeviceCheckInStatusResponse(eq(mResponse), any())).thenReturn(
+                isHandleable);
+    }
+
+    private void setUpFailedCheckInResponse(boolean isRecoverable) {
+        when(mResponse.hasRecoverableError()).thenReturn(isRecoverable);
+        when(mResponse.isSuccessful()).thenReturn(false);
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/IsDeviceInApprovedCountryWorkerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/IsDeviceInApprovedCountryWorkerTest.java
index 5715569..98f0bb5 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/IsDeviceInApprovedCountryWorkerTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/IsDeviceInApprovedCountryWorkerTest.java
@@ -21,6 +21,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -32,10 +33,15 @@
 import androidx.work.ListenableWorker.Result;
 import androidx.work.WorkerFactory;
 import androidx.work.WorkerParameters;
-import androidx.work.testing.TestWorkerBuilder;
+import androidx.work.testing.TestListenableWorkerBuilder;
 
 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
 import com.android.devicelockcontroller.provision.grpc.IsDeviceInApprovedCountryGrpcResponse;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.testing.TestingExecutors;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -46,9 +52,6 @@
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
 
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
 @RunWith(RobolectricTestRunner.class)
 public final class IsDeviceInApprovedCountryWorkerTest {
     @Rule
@@ -58,14 +61,14 @@
     @Mock
     private IsDeviceInApprovedCountryGrpcResponse mResponse;
     private IsDeviceInApprovedCountryWorker mWorker;
+    private StatsLogger mStatsLogger;
 
     @Before
     public void setUp() throws Exception {
         final Context context = ApplicationProvider.getApplicationContext();
-        final Executor executor = Executors.newSingleThreadExecutor();
         when(mClient.isDeviceInApprovedCountry(any())).thenReturn(mResponse);
-        mWorker = TestWorkerBuilder.from(
-                        context, IsDeviceInApprovedCountryWorker.class, executor)
+        mWorker = TestListenableWorkerBuilder.from(
+                        context, IsDeviceInApprovedCountryWorker.class)
                 .setWorkerFactory(
                         new WorkerFactory() {
                             @Override
@@ -75,44 +78,57 @@
                                 return workerClassName.equals(
                                         IsDeviceInApprovedCountryWorker.class.getName())
                                         ? new IsDeviceInApprovedCountryWorker(
-                                        context, workerParameters, mClient)
+                                        context, workerParameters, mClient,
+                                        TestingExecutors.sameThreadScheduledExecutor())
                                         : null;
                             }
                         }).build();
+        StatsLoggerProvider loggerProvider =
+                (StatsLoggerProvider) context.getApplicationContext();
+        mStatsLogger = loggerProvider.getStatsLogger();
     }
 
     @Test
-    public void doWork_responseIsSuccessful_isInApprovedCountry_correctResult() {
+    public void doWork_responseIsSuccessful_isInApprovedCountry_correctResultAndLog() {
         when(mResponse.isSuccessful()).thenReturn(true);
         when(mResponse.isDeviceInApprovedCountry()).thenReturn(true);
         Result expected = Result.success(
                 new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, true).build());
 
-        Result actual = mWorker.doWork();
+        Result actual = Futures.getUnchecked(mWorker.startWork());
 
         assertThat(actual).isEqualTo(expected);
+        assertThat(actual.getOutputData().hasKeyWithValueOfType(KEY_IS_IN_APPROVED_COUNTRY,
+                Boolean.class)).isTrue();
+        verify(mStatsLogger).logIsDeviceInApprovedCountry();
     }
 
     @Test
-    public void doWork_responseIsSuccessful_isNotInApprovedCountry_correctResult() {
+    public void doWork_responseIsSuccessful_isNotInApprovedCountry_correctResultAndLog() {
         when(mResponse.isSuccessful()).thenReturn(true);
         when(mResponse.isDeviceInApprovedCountry()).thenReturn(false);
         Result expected = Result.success(
                 new Data.Builder().putBoolean(KEY_IS_IN_APPROVED_COUNTRY, false).build());
 
-        Result actual = mWorker.doWork();
+        Result actual = Futures.getUnchecked(mWorker.startWork());
 
         assertThat(actual).isEqualTo(expected);
+        assertThat(actual.getOutputData().hasKeyWithValueOfType(KEY_IS_IN_APPROVED_COUNTRY,
+                Boolean.class)).isTrue();
+        verify(mStatsLogger).logIsDeviceInApprovedCountry();
     }
 
     @Test
-    public void doWork_responseIsNotSuccessful_failureResult() {
+    public void doWork_responseIsNotSuccessful_failureResultAndLog() {
         when(mResponse.isSuccessful()).thenReturn(false);
         when(mResponse.isDeviceInApprovedCountry()).thenReturn(false);
         Result expected = Result.failure();
 
-        Result actual = mWorker.doWork();
+        Result actual = Futures.getUnchecked(mWorker.startWork());
 
         assertThat(actual).isEqualTo(expected);
+        assertThat(actual.getOutputData().hasKeyWithValueOfType(KEY_IS_IN_APPROVED_COUNTRY,
+                Boolean.class)).isFalse();
+        verify(mStatsLogger).logIsDeviceInApprovedCountry();
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/PauseProvisioningWorkerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/PauseProvisioningWorkerTest.java
index 0b72b1b..f2d79d7 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/PauseProvisioningWorkerTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/PauseProvisioningWorkerTest.java
@@ -16,12 +16,10 @@
 
 package com.android.devicelockcontroller.provision.worker;
 
-import static com.android.devicelockcontroller.provision.worker.PauseProvisioningWorker.PROVISION_PAUSED_HOUR;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -33,15 +31,16 @@
 import androidx.work.ListenableWorker.Result;
 import androidx.work.WorkerFactory;
 import androidx.work.WorkerParameters;
-import androidx.work.testing.TestWorkerBuilder;
+import androidx.work.testing.TestListenableWorkerBuilder;
 
 import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
-import com.android.devicelockcontroller.policy.DevicePolicyController;
 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
 import com.android.devicelockcontroller.provision.grpc.PauseDeviceProvisioningGrpcResponse;
-import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
 
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.testing.TestingExecutors;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -52,10 +51,6 @@
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
 
-import java.time.Duration;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
 @RunWith(RobolectricTestRunner.class)
 public final class PauseProvisioningWorkerTest {
     @Rule
@@ -64,16 +59,16 @@
     private DeviceCheckInClient mClient;
     @Mock
     private PauseDeviceProvisioningGrpcResponse mResponse;
+    private StatsLogger mStatsLogger;
     private PauseProvisioningWorker mWorker;
     private TestDeviceLockControllerApplication mTestApp;
 
     @Before
     public void setUp() throws Exception {
         mTestApp = ApplicationProvider.getApplicationContext();
-        final Executor executor = Executors.newSingleThreadExecutor();
         when(mClient.pauseDeviceProvisioning(anyInt())).thenReturn(mResponse);
-        mWorker = TestWorkerBuilder.from(
-                        mTestApp, PauseProvisioningWorker.class, executor)
+        mWorker = TestListenableWorkerBuilder.from(
+                        mTestApp, PauseProvisioningWorker.class)
                 .setWorkerFactory(
                         new WorkerFactory() {
                             @Override
@@ -83,44 +78,31 @@
                                 return workerClassName.equals(
                                         PauseProvisioningWorker.class.getName())
                                         ? new PauseProvisioningWorker(context,
-                                        workerParameters, mClient)
+                                        workerParameters, mClient,
+                                        TestingExecutors.sameThreadScheduledExecutor())
                                         : null;
                             }
                         }).build();
+        StatsLoggerProvider loggerProvider =
+                (StatsLoggerProvider) mTestApp.getApplicationContext();
+        mStatsLogger = loggerProvider.getStatsLogger();
     }
 
     @Test
-    public void doWork_responseIsSuccessful_provisionShouldBeForced_globalParameterIsSet() {
+    public void doWork_responseIsSuccessful_resultSuccessAndLogged() {
         when(mResponse.isSuccessful()).thenReturn(true);
-        when(mResponse.shouldForceProvisioning()).thenReturn(true);
-        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
 
-        assertThat(mWorker.doWork()).isEqualTo(Result.success());
-
-        verify(devicePolicyController).enqueueStartLockTaskModeWorkerWithDelay(eq(false), eq(
-                Duration.ofHours(PROVISION_PAUSED_HOUR)));
-        assertThat(Futures.getUnchecked(
-                GlobalParametersClient.getInstance().isProvisionForced())).isEqualTo(true);
-    }
-
-    @Test
-    public void doWork_responseIsSuccessful_provisionShouldNotBeForced_globalParameterIsSet() {
-        when(mResponse.isSuccessful()).thenReturn(true);
-        when(mResponse.shouldForceProvisioning()).thenReturn(false);
-        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
-
-        assertThat(mWorker.doWork()).isEqualTo(Result.success());
-
-        verify(devicePolicyController).enqueueStartLockTaskModeWorkerWithDelay(eq(false), eq(
-                Duration.ofHours(PROVISION_PAUSED_HOUR)));
-        assertThat(Futures.getUnchecked(
-                GlobalParametersClient.getInstance().isProvisionForced())).isEqualTo(false);
+        assertThat(Futures.getUnchecked(mWorker.startWork())).isEqualTo(Result.success());
+        // THEN pause device provisioning was logged
+        verify(mStatsLogger).logPauseDeviceProvisioning();
     }
 
     @Test
     public void doWork_responseIsNotSuccessful_resultFailure() {
         when(mResponse.isSuccessful()).thenReturn(false);
 
-        assertThat(mWorker.doWork()).isEqualTo(Result.failure());
+        assertThat(Futures.getUnchecked(mWorker.startWork())).isEqualTo(Result.failure());
+        // THEN pause device provisioning was NOT logged
+        verify(mStatsLogger, never()).logPauseDeviceProvisioning();
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceLockProgramCompleteWorkerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceLockProgramCompleteWorkerTest.java
index 73a9d6a..c81a978 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceLockProgramCompleteWorkerTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceLockProgramCompleteWorkerTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -28,10 +29,17 @@
 import androidx.work.ListenableWorker.Result;
 import androidx.work.WorkerFactory;
 import androidx.work.WorkerParameters;
-import androidx.work.testing.TestWorkerBuilder;
+import androidx.work.testing.TestListenableWorkerBuilder;
 
+import com.android.devicelockcontroller.policy.FinalizationController;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
 import com.android.devicelockcontroller.provision.grpc.DeviceFinalizeClient;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.testing.TestingExecutors;
+
+import io.grpc.Status;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -41,25 +49,27 @@
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
 
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
-import io.grpc.Status;
-
 @RunWith(RobolectricTestRunner.class)
 public final class ReportDeviceLockProgramCompleteWorkerTest {
     @Rule
     public final MockitoRule mMocks = MockitoJUnit.rule();
     @Mock
     private DeviceFinalizeClient mClient;
+    @Mock
+    private PolicyObjectsProvider mPolicyObjectsProvider;
+    @Mock
+    private FinalizationController mFinalizationController;
     private ReportDeviceLockProgramCompleteWorker mWorker;
 
     @Before
     public void setUp() throws Exception {
         final Context context = ApplicationProvider.getApplicationContext();
-        final Executor executor = Executors.newSingleThreadExecutor();
-        mWorker = TestWorkerBuilder.from(
-                        context, ReportDeviceLockProgramCompleteWorker.class, executor)
+        when(mPolicyObjectsProvider.getFinalizationController())
+                .thenReturn(mFinalizationController);
+        when(mFinalizationController.notifyFinalizationReportResult(any()))
+                .thenReturn(Futures.immediateVoidFuture());
+        mWorker = TestListenableWorkerBuilder.from(
+                        context, ReportDeviceLockProgramCompleteWorker.class)
                 .setWorkerFactory(
                         new WorkerFactory() {
                             @Override
@@ -69,7 +79,8 @@
                                 return workerClassName.equals(
                                         ReportDeviceLockProgramCompleteWorker.class.getName())
                                         ? new ReportDeviceLockProgramCompleteWorker(context,
-                                        workerParameters, mClient)
+                                        workerParameters, mClient, mPolicyObjectsProvider,
+                                        TestingExecutors.sameThreadScheduledExecutor())
                                         : null;
                             }
                         }).build();
@@ -80,7 +91,7 @@
         when(mClient.reportDeviceProgramComplete()).thenReturn(
                 new DeviceFinalizeClient.ReportDeviceProgramCompleteResponse());
 
-        assertThat(mWorker.doWork()).isEqualTo(Result.success());
+        assertThat(Futures.getUnchecked(mWorker.startWork())).isEqualTo(Result.success());
     }
 
     @Test
@@ -88,14 +99,14 @@
         when(mClient.reportDeviceProgramComplete()).thenReturn(
                 new DeviceFinalizeClient.ReportDeviceProgramCompleteResponse(Status.UNAVAILABLE));
 
-        assertThat(mWorker.doWork()).isEqualTo(Result.retry());
+        assertThat(Futures.getUnchecked(mWorker.startWork())).isEqualTo(Result.retry());
     }
 
     @Test
     public void doWork_responseHasFatalError_returnFailure() {
         when(mClient.reportDeviceProgramComplete()).thenReturn(
-                new DeviceFinalizeClient.ReportDeviceProgramCompleteResponse(Status.UNKNOWN));
+                new DeviceFinalizeClient.ReportDeviceProgramCompleteResponse(Status.UNIMPLEMENTED));
 
-        assertThat(mWorker.doWork()).isEqualTo(Result.failure());
+        assertThat(Futures.getUnchecked(mWorker.startWork())).isEqualTo(Result.failure());
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorkerResponseTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorkerResponseTest.java
new file mode 100644
index 0000000..ef72a12
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorkerResponseTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.provision.worker;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_DISMISSIBLE_UI;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_FACTORY_RESET;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_PERSISTENT_UI;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_RETRY;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_SUCCESS;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_UNSPECIFIED;
+
+import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
+
+import com.google.common.truth.Truth;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.ParameterizedRobolectricTestRunner;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(ParameterizedRobolectricTestRunner.class)
+public final class ReportDeviceProvisionStateWorkerResponseTest {
+    @ParameterizedRobolectricTestRunner.Parameter
+    public boolean mWithDelay;
+
+    @ParameterizedRobolectricTestRunner.Parameter(1)
+    @DeviceProvisionState
+    public int mLastState;
+
+    @ParameterizedRobolectricTestRunner.Parameter(2)
+    @DeviceProvisionState
+    public int mNextState;
+
+    /**
+     * Parameters
+     */
+    @ParameterizedRobolectricTestRunner.Parameters(name =
+            "Schedule next step with delay: {0}, when last step is {1} and next step is {2}.")
+    public static List<Object[]> parameters() {
+        return Arrays.asList(new Object[][]{
+                {false, PROVISION_STATE_UNSPECIFIED, PROVISION_STATE_RETRY},
+                {true, PROVISION_STATE_UNSPECIFIED, PROVISION_STATE_DISMISSIBLE_UI},
+                {true, PROVISION_STATE_UNSPECIFIED, PROVISION_STATE_PERSISTENT_UI},
+                {true, PROVISION_STATE_UNSPECIFIED, PROVISION_STATE_FACTORY_RESET},
+                {true, PROVISION_STATE_UNSPECIFIED, PROVISION_STATE_SUCCESS},
+                {false, PROVISION_STATE_RETRY, PROVISION_STATE_RETRY},
+                {true, PROVISION_STATE_RETRY, PROVISION_STATE_DISMISSIBLE_UI},
+                {true, PROVISION_STATE_RETRY, PROVISION_STATE_PERSISTENT_UI},
+                {true, PROVISION_STATE_RETRY, PROVISION_STATE_FACTORY_RESET},
+                {true, PROVISION_STATE_RETRY, PROVISION_STATE_SUCCESS},
+                {false, PROVISION_STATE_DISMISSIBLE_UI, PROVISION_STATE_DISMISSIBLE_UI},
+                {false, PROVISION_STATE_DISMISSIBLE_UI, PROVISION_STATE_PERSISTENT_UI},
+                {false, PROVISION_STATE_DISMISSIBLE_UI, PROVISION_STATE_FACTORY_RESET},
+                {false, PROVISION_STATE_PERSISTENT_UI, PROVISION_STATE_FACTORY_RESET},
+        });
+    }
+
+    @Test
+    public void shouldScheduleWithDelay_returnCorrectValue() {
+        Truth.assertThat(ReportDeviceProvisionStateWorker.shouldRunNextStepImmediately(mLastState,
+                mNextState)).isEqualTo(mWithDelay);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorkerTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorkerTest.java
index ca707d0..33400b2 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorkerTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/provision/worker/ReportDeviceProvisionStateWorkerTest.java
@@ -16,41 +16,41 @@
 
 package com.android.devicelockcontroller.provision.worker;
 
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_DISMISSIBLE_UI;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_FACTORY_RESET;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_PERSISTENT_UI;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_RETRY;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_SUCCESS;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_UNSPECIFIED;
-import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceEvent.PROVISIONING_SUCCESS;
-import static com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker.UNEXPECTED_PROVISION_STATE_ERROR_MESSAGE;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.os.Looper;
 
 import androidx.annotation.NonNull;
 import androidx.test.core.app.ApplicationProvider;
+import androidx.work.Configuration;
 import androidx.work.ListenableWorker;
 import androidx.work.ListenableWorker.Result;
 import androidx.work.WorkerFactory;
 import androidx.work.WorkerParameters;
-import androidx.work.testing.TestWorkerBuilder;
+import androidx.work.testing.SynchronousExecutor;
+import androidx.work.testing.TestListenableWorkerBuilder;
+import androidx.work.testing.WorkManagerTestInitHelper;
 
 import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
-import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.DeviceStateController;
 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
 import com.android.devicelockcontroller.provision.grpc.ReportDeviceProvisionStateGrpcResponse;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+import com.android.devicelockcontroller.storage.UserParameters;
 
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -60,31 +60,35 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.Shadows;
 
-import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 
 @RunWith(RobolectricTestRunner.class)
 public final class ReportDeviceProvisionStateWorkerTest {
-    public static final int UNEXPECTED_VALUE = -1;
+    private static final int TEST_DAYS_LEFT_UNTIL_RESET = 3;
     @Rule
     public final MockitoRule mMocks = MockitoJUnit.rule();
     @Mock
     private DeviceCheckInClient mClient;
     @Mock
     private ReportDeviceProvisionStateGrpcResponse mResponse;
+    private StatsLogger mStatsLogger;
     private ReportDeviceProvisionStateWorker mWorker;
     private TestDeviceLockControllerApplication mTestApp;
 
     @Before
     public void setUp() throws Exception {
         mTestApp = ApplicationProvider.getApplicationContext();
-        final Executor executor = Executors.newSingleThreadExecutor();
-        when(mClient.reportDeviceProvisionState(anyInt(), anyInt(), anyBoolean())).thenReturn(
+        WorkManagerTestInitHelper.initializeTestWorkManager(mTestApp,
+                new Configuration.Builder()
+                        .setMinimumLoggingLevel(android.util.Log.DEBUG)
+                        .setExecutor(new SynchronousExecutor())
+                        .build());
+
+        when(mClient.reportDeviceProvisionState(anyInt(), anyBoolean(), anyInt())).thenReturn(
                 mResponse);
-        mWorker = TestWorkerBuilder.from(
-                        mTestApp, ReportDeviceProvisionStateWorker.class, executor)
+        mWorker = TestListenableWorkerBuilder.from(
+                        mTestApp, ReportDeviceProvisionStateWorker.class)
                 .setWorkerFactory(
                         new WorkerFactory() {
                             @Override
@@ -94,100 +98,56 @@
                                 return workerClassName.equals(
                                         ReportDeviceProvisionStateWorker.class.getName())
                                         ? new ReportDeviceProvisionStateWorker(context,
-                                        workerParameters, mClient)
+                                        workerParameters, mClient,
+                                        MoreExecutors.listeningDecorator(
+                                                Executors.newSingleThreadExecutor()))
                                         : null;
                             }
                         }).build();
+        StatsLoggerProvider loggerProvider =
+                (StatsLoggerProvider) mTestApp.getApplicationContext();
+        mStatsLogger = loggerProvider.getStatsLogger();
     }
 
     @Test
-    public void doWork_responseHasRecoverableError_returnRetry() {
+    public void doWork_responseHasRecoverableError_returnRetryAndNotLogged() {
         when(mResponse.hasRecoverableError()).thenReturn(true);
 
-        assertThat(mWorker.doWork()).isEqualTo(Result.retry());
+        assertThat(Futures.getUnchecked(mWorker.startWork())).isEqualTo(Result.retry());
+        // THEN report provisioning state or complete was NOT logged
+        verify(mStatsLogger, never()).logReportDeviceProvisionState();
     }
 
     @Test
-    public void doWork_responseHasFatalError_returnFailure() {
+    public void doWork_responseHasFatalError_returnFailureAndNotLogged() {
         when(mResponse.hasFatalError()).thenReturn(true);
 
-        assertThat(mWorker.doWork()).isEqualTo(Result.failure());
+        assertThat(Futures.getUnchecked(mWorker.startWork())).isEqualTo(Result.failure());
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleNextProvisionFailedStepAlarm(
+                /* shouldGoOffImmediately= */ eq(false));
+        // THEN report provisioning state or complete was NOT logged
+        verify(mStatsLogger, never()).logReportDeviceProvisionState();
     }
 
     @Test
-    public void doWork_nextProvisionStateUnExpected_shouldThrowException() {
-        when(mResponse.isSuccessful()).thenReturn(true);
-        when(mResponse.getNextClientProvisionState()).thenReturn(UNEXPECTED_VALUE);
-        try {
-            mWorker.doWork();
-        } catch (IllegalStateException actualException) {
-            assertThat(actualException).hasMessageThat().isEqualTo(
-                    UNEXPECTED_PROVISION_STATE_ERROR_MESSAGE);
-            return;
-        }
-        throw new AssertionError("Expected exception is not thrown!");
-    }
-
-    @Test
-    public void doWork_nextProvisionStateUnspecified_shouldReturnSuccess() {
-        when(mResponse.isSuccessful()).thenReturn(true);
-        when(mResponse.getNextClientProvisionState()).thenReturn(PROVISION_STATE_UNSPECIFIED);
-
-        assertThat(mWorker.doWork()).isEqualTo(Result.success());
-    }
-
-    @Test
-    public void doWork_nextProvisionStateSuccess_shouldReturnSuccess() {
-        when(mResponse.isSuccessful()).thenReturn(true);
-        when(mResponse.getNextClientProvisionState()).thenReturn(PROVISION_STATE_SUCCESS);
-
-        assertThat(mWorker.doWork()).isEqualTo(Result.success());
-    }
-
-    @Test
-    public void doWork_nextProvisionStateRetry_shouldRetrySetup() {
-        when(mResponse.isSuccessful()).thenReturn(true);
-        when(mResponse.getNextClientProvisionState()).thenReturn(PROVISION_STATE_RETRY);
-        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
-        DeviceStateController deviceStateController = mTestApp.getStateController();
-        when(deviceStateController.setNextStateForEvent(PROVISIONING_SUCCESS)).thenReturn(
-                Futures.immediateVoidFuture());
-
-        assertThat(mWorker.doWork()).isEqualTo(Result.success());
-
-        Shadows.shadowOf(Looper.getMainLooper()).idle();
-        verify(deviceStateController).setNextStateForEvent(eq(PROVISIONING_SUCCESS));
-        verify(devicePolicyController).enqueueStartLockTaskModeWorker(eq(false));
-    }
-
-    @Test
-    public void doWork_nextProvisionStateDissmissableUI_shouldReturnSuccess() {
-        when(mResponse.isSuccessful()).thenReturn(true);
-        when(mResponse.getNextClientProvisionState()).thenReturn(PROVISION_STATE_DISMISSIBLE_UI);
-
-        // TODO(b/284003841): add test content
-
-        assertThat(mWorker.doWork()).isEqualTo(Result.success());
-    }
-
-    @Test
-    public void doWork_nextProvisionStatePersistentUI_shouldReturnSuccess() {
-        when(mResponse.isSuccessful()).thenReturn(true);
-        when(mResponse.getNextClientProvisionState()).thenReturn(PROVISION_STATE_PERSISTENT_UI);
-
-        // TODO(b/284003841): add test content
-
-        assertThat(mWorker.doWork()).isEqualTo(Result.success());
-    }
-
-    @Test
-    public void doWork_nextProvisionStateFactoryReset_shouldResetDevice() {
+    public void doWork_responseIsSuccessful_globalParametersShouldBeSet_returnSuccessAndLogReportState()
+            throws Exception {
         when(mResponse.isSuccessful()).thenReturn(true);
         when(mResponse.getNextClientProvisionState()).thenReturn(PROVISION_STATE_FACTORY_RESET);
-        DevicePolicyController devicePolicyController = mTestApp.getPolicyController();
+        when(mResponse.getDaysLeftUntilReset()).thenReturn(TEST_DAYS_LEFT_UNTIL_RESET);
 
-        assertThat(mWorker.doWork()).isEqualTo(Result.success());
+        assertThat(Futures.getUnchecked(mWorker.startWork())).isEqualTo(Result.success());
 
-        verify(devicePolicyController).wipeData();
+        GlobalParametersClient globalParameters = GlobalParametersClient.getInstance();
+        assertThat(globalParameters.getLastReceivedProvisionState().get()).isEqualTo(
+                PROVISION_STATE_FACTORY_RESET);
+        Executors.newSingleThreadExecutor().submit(
+                () -> assertThat(UserParameters.getDaysLeftUntilReset(mTestApp)).isEqualTo(
+                        TEST_DAYS_LEFT_UNTIL_RESET)).get();
+
+        verify(mTestApp.getDeviceLockControllerScheduler()).scheduleNextProvisionFailedStepAlarm(
+                /* shouldGoOffImmediately= */ eq(true));
+        // THEN report provisioning state was logged
+        verify(mStatsLogger).logReportDeviceProvisionState();
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/BootUtilsTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/BootUtilsTest.java
deleted file mode 100644
index 2300901..0000000
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/BootUtilsTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
-
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
-import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.DeviceStateController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public final class BootUtilsTest {
-    private DeviceStateController mStateController;
-    private DevicePolicyController mPolicyController;
-    private TestDeviceLockControllerApplication mTestApplication;
-
-    @Before
-    public void setup() {
-        mTestApplication = ApplicationProvider.getApplicationContext();
-        mStateController = mTestApplication.getStateController();
-        mPolicyController = mTestApplication.getPolicyController();
-    }
-
-    @Test
-    public void startLockTaskModeAtBoot_success() {
-        when(mStateController.isLocked()).thenReturn(true);
-        BootUtils.startLockTaskModeAtBoot(mTestApplication);
-        verify(mPolicyController).enqueueStartLockTaskModeWorker(eq(true));
-    }
-
-    @Test
-    public void startLockTaskModeAtBoot_deviceIsNotLocked_doesNotLaunchActivityInLockedMode() {
-        when(mStateController.isLocked()).thenReturn(false);
-        BootUtils.startLockTaskModeAtBoot(mTestApplication);
-        verify(mPolicyController, never()).enqueueStartLockTaskModeWorker(anyBoolean());
-    }
-}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/CheckInBootCompletedReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/CheckInBootCompletedReceiverTest.java
index 0ba0e8b..dccd54c 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/CheckInBootCompletedReceiverTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/CheckInBootCompletedReceiverTest.java
@@ -18,72 +18,85 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
 import static org.mockito.Mockito.when;
 
+import android.content.BroadcastReceiver.PendingResult;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.UserHandle;
 
 import androidx.test.core.app.ApplicationProvider;
-import androidx.work.Configuration;
-import androidx.work.WorkInfo;
-import androidx.work.WorkManager;
-import androidx.work.testing.SynchronousExecutor;
-import androidx.work.testing.WorkManagerTestInitHelper;
 
-import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.provision.worker.DeviceCheckInHelper;
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
 @RunWith(RobolectricTestRunner.class)
-public class CheckInBootCompletedReceiverTest {
+public final class CheckInBootCompletedReceiverTest {
 
-    private DeviceStateController mDeviceStateController;
-    private DeviceCheckInHelper mDeviceCheckInHelper;
-    private WorkManager mWorkManager;
+    public static final Intent INTENT = new Intent(Intent.ACTION_BOOT_COMPLETED);
+    private DeviceLockControllerScheduler mScheduler;
+    private CheckInBootCompletedReceiver mReceiver;
+    private TestDeviceLockControllerApplication mTestApp;
 
     @Before
     public void setUp() {
-        final Context context = ApplicationProvider.getApplicationContext();
-        mDeviceStateController = mock(DeviceStateController.class);
-        mDeviceCheckInHelper = new DeviceCheckInHelper(context);
-        WorkManagerTestInitHelper.initializeTestWorkManager(context,
-                new Configuration.Builder()
-                        .setMinimumLoggingLevel(android.util.Log.DEBUG)
-                        .setExecutor(new SynchronousExecutor())
-                        .build());
-        mWorkManager = WorkManager.getInstance(context);
+        HandlerThread handlerThread = new HandlerThread("test");
+        handlerThread.start();
+        Handler handler = handlerThread.getThreadHandler();
+        mReceiver = new CheckInBootCompletedReceiver(
+                MoreExecutors.newSequentialExecutor(handler::post));
+        mTestApp = ApplicationProvider.getApplicationContext();
+        mScheduler = mTestApp.getDeviceLockControllerScheduler();
     }
 
     @Test
-    public void onReceive_checkInIsNeeded_shouldEnqueueCheckInWork()
-            throws ExecutionException, InterruptedException, TimeoutException {
-        when(mDeviceStateController.isCheckInNeeded()).thenReturn(true);
+    public void onReceive_shouldCallMaybeScheduleInitialCheckIn() {
+        when(mScheduler.maybeScheduleInitialCheckIn()).thenReturn(Futures.immediateVoidFuture());
 
-        CheckInBootCompletedReceiver.checkInIfNeeded(mDeviceStateController, mDeviceCheckInHelper);
+        final PendingResult pendingResult = new PendingResult(
+                1 /* resultCode */,
+                "resultData",
+                new Bundle(),
+                0 /* type */,
+                true /* ordered */,
+                false /*sticky*/,
+                null /* ibinder token */,
+                0 /* userid */,
+                0 /* flags */);
+        mReceiver.setPendingResult(pendingResult);
 
-        List<WorkInfo> workInfo = mWorkManager.getWorkInfosForUniqueWork(
-                DeviceCheckInHelper.CHECK_IN_WORK_NAME).get(500, TimeUnit.MILLISECONDS);
-        assertThat(workInfo.size()).isEqualTo(1);
+        mReceiver.onReceive(mTestApp, INTENT);
+
+        verify(mScheduler).maybeScheduleInitialCheckIn();
     }
 
     @Test
-    public void onReceive_checkInNotNeeded_shouldNotEnqueueCheckInWork()
-            throws ExecutionException, InterruptedException, TimeoutException {
-        when(mDeviceStateController.isCheckInNeeded()).thenReturn(false);
+    public void onReceive_notSystemUser_disablesReceiver() {
+        Context secondaryUserContext = mTestApp.createContextAsUser(
+                UserHandle.of(/* userId= */ 1), /* flags= */ 0);
+        PackageManager packageManager = secondaryUserContext.getPackageManager();
 
-        CheckInBootCompletedReceiver.checkInIfNeeded(mDeviceStateController, mDeviceCheckInHelper);
+        mReceiver.onReceive(secondaryUserContext, INTENT);
 
-        List<WorkInfo> workInfo = mWorkManager.getWorkInfosForUniqueWork(
-                DeviceCheckInHelper.CHECK_IN_WORK_NAME).get(500, TimeUnit.MILLISECONDS);
-        assertThat(workInfo).isEmpty();
+        ComponentName receiverCmp =
+                new ComponentName(secondaryUserContext, CheckInBootCompletedReceiver.class);
+        assertThat(packageManager.getComponentEnabledSetting(receiverCmp))
+                .isEqualTo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+        verifyNoInteractions(mScheduler);
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/FinalizationBootCompletedReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/FinalizationBootCompletedReceiverTest.java
new file mode 100644
index 0000000..ca2ce49
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/FinalizationBootCompletedReceiverTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import static org.mockito.Mockito.verify;
+
+import android.content.Intent;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public final class FinalizationBootCompletedReceiverTest {
+
+    public static final Intent INTENT = new Intent(Intent.ACTION_BOOT_COMPLETED);
+
+    private TestDeviceLockControllerApplication mTestApplication;
+    private FinalizationBootCompletedReceiver mReceiver;
+
+    @Before
+    public void setUp() {
+        mTestApplication = ApplicationProvider.getApplicationContext();
+        mReceiver = new FinalizationBootCompletedReceiver();
+    }
+
+    @Test
+    public void onReceive_initializeFinalizationController() {
+        mReceiver.onReceive(mTestApplication, INTENT);
+
+        verify(mTestApplication.getFinalizationController()).enforceInitialState();
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/LockTaskBootCompletedReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/LockTaskBootCompletedReceiverTest.java
deleted file mode 100644
index fe9ceba..0000000
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/LockTaskBootCompletedReceiverTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Intent;
-
-import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
-import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.DeviceStateController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class LockTaskBootCompletedReceiverTest {
-
-    private static final Intent BOOT_COMPLETED_INTENT = new Intent(
-            Intent.ACTION_BOOT_COMPLETED);
-
-    private LockTaskBootCompletedReceiver mLockTaskBootCompletedReceiver;
-    private DeviceStateController mStateController;
-    private DevicePolicyController mPolicyController;
-    private TestDeviceLockControllerApplication mTestApplication;
-
-    @Before
-    public void setUp() {
-        mTestApplication = getApplicationContext();
-        mStateController = mTestApplication.getStateController();
-        mPolicyController = mTestApplication.getPolicyController();
-
-        when(mStateController.isLocked()).thenReturn(true);
-        mLockTaskBootCompletedReceiver = new LockTaskBootCompletedReceiver();
-    }
-
-    @Test
-    public void onReceive_startLockTaskMode() {
-        mLockTaskBootCompletedReceiver.onReceive(mTestApplication, BOOT_COMPLETED_INTENT);
-
-        verify(mPolicyController).enqueueStartLockTaskModeWorker(eq(true));
-    }
-}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/LockedBootCompletedReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/LockedBootCompletedReceiverTest.java
index 7e56015..fc99ac4 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/LockedBootCompletedReceiverTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/LockedBootCompletedReceiverTest.java
@@ -16,84 +16,60 @@
 
 package com.android.devicelockcontroller.receivers;
 
-import static com.google.common.truth.Truth.assertThat;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_FAILED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_PAUSED;
 
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.content.ComponentName;
-import android.content.pm.PackageManager;
+import android.content.Intent;
 
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
-import com.android.devicelockcontroller.policy.DevicePolicyController;
-import com.android.devicelockcontroller.policy.DeviceStateController;
-import com.android.devicelockcontroller.shadows.ShadowApplicationPackageManager;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.testing.TestingExecutors;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowPackageManager;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowApplicationPackageManager.class})
-public class LockedBootCompletedReceiverTest {
+public final class LockedBootCompletedReceiverTest {
+    public static final Intent INTENT = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED);
     private final TestDeviceLockControllerApplication mTestApplication =
             ApplicationProvider.getApplicationContext();
-    private PackageManager mPm;
-    private ShadowPackageManager mShadowPackageManager;
-    private DeviceStateController mStateController;
-    private DevicePolicyController mPolicyController;
+    private ProvisionStateController mProvisionStateController;
+    private LockedBootCompletedReceiver mReceiver;
+    private DeviceLockControllerScheduler mScheduler;
 
     @Before
     public void setUp() {
-        mStateController = mTestApplication.getStateController();
-        mPolicyController = mTestApplication.getPolicyController();
-        mPm = mTestApplication.getPackageManager();
-        mShadowPackageManager = Shadows.shadowOf(mTestApplication.getPackageManager());
-
+        mProvisionStateController = mTestApplication.getProvisionStateController();
+        mScheduler = mTestApplication.getDeviceLockControllerScheduler();
+        mReceiver = new LockedBootCompletedReceiver(TestingExecutors.sameThreadScheduledExecutor());
     }
 
     @Test
-    public void
-            startLockTaskModeIfApplicable_whenDeviceIsInSetupState_doesNotStartLockTaskMode() {
-        when(mStateController.isInSetupState()).thenReturn(true);
-        when(mStateController.isLocked()).thenReturn(true);
+    public void onReceive_provisionPaused_shouldRescheduleResume() {
+        when(mProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(PROVISION_PAUSED));
 
-        LockedBootCompletedReceiver.startLockTaskModeIfApplicable(mTestApplication);
+        mReceiver.onReceive(mTestApplication, INTENT);
 
-        verify(mPolicyController, never()).enqueueStartLockTaskModeWorker(anyBoolean());
-
-        final ComponentName componentName =
-                new ComponentName(mTestApplication, LockTaskBootCompletedReceiver.class);
-        assertThat(mPm.getComponentEnabledSetting(componentName))
-                .isEqualTo(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
-        assertThat(mShadowPackageManager.getComponentEnabledSettingFlags(componentName))
-                .isEqualTo(PackageManager.DONT_KILL_APP);
+        verify(mScheduler).notifyRebootWhenProvisionPaused();
     }
 
     @Test
-    public void
-            startLockTaskModeIfApplicable_whenDeviceIsNotInSetupState_startLockTaskMode() {
-        when(mStateController.isInSetupState()).thenReturn(false);
-        when(mStateController.isLocked()).thenReturn(true);
+    public void onReceive_provisionFailed_shouldRescheduleFailedStepAndReset() {
+        when(mProvisionStateController.getState()).thenReturn(
+                Futures.immediateFuture(PROVISION_FAILED));
+        mReceiver.onReceive(mTestApplication, INTENT);
 
-        LockedBootCompletedReceiver.startLockTaskModeIfApplicable(mTestApplication);
-
-        verify(mPolicyController).enqueueStartLockTaskModeWorker(eq(true));
-
-        final ComponentName componentName =
-                new ComponentName(mTestApplication, LockTaskBootCompletedReceiver.class);
-        assertThat(mPm.getComponentEnabledSetting(componentName))
-                .isEqualTo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
-        assertThat(mShadowPackageManager.getComponentEnabledSettingFlags(componentName))
-                .isEqualTo(PackageManager.DONT_KILL_APP);
+        verify(mScheduler).notifyRebootWhenProvisionFailed();
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/NextProvisionFailedStepReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/NextProvisionFailedStepReceiverTest.java
new file mode 100644
index 0000000..14c918a
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/NextProvisionFailedStepReceiverTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_DISMISSIBLE_UI;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_PERSISTENT_UI;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_RETRY;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_SUCCESS;
+import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_UNSPECIFIED;
+import static com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker.REPORT_PROVISION_STATE_WORK_NAME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.annotation.LooperMode.Mode.LEGACY;
+
+import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerThread;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.work.Configuration;
+import androidx.work.NetworkType;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+import androidx.work.testing.SynchronousExecutor;
+import androidx.work.testing.WorkManagerTestInitHelper;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+
+import com.google.common.util.concurrent.MoreExecutors;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.LooperMode;
+import org.robolectric.shadows.ShadowLooper;
+
+import java.util.List;
+
+@LooperMode(LEGACY)
+@RunWith(RobolectricTestRunner.class)
+public class NextProvisionFailedStepReceiverTest {
+
+    private GlobalParametersClient mGlobalParameters;
+    private NextProvisionFailedStepReceiver mReceiver;
+    private TestDeviceLockControllerApplication mTestApp;
+    private Intent mIntent;
+    private ShadowLooper mShadowLooper;
+
+    @Before
+    public void setUp() throws Exception {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        mGlobalParameters = GlobalParametersClient.getInstance();
+        HandlerThread handlerThread = new HandlerThread("test");
+        handlerThread.start();
+        Handler handler = handlerThread.getThreadHandler();
+        mShadowLooper = Shadows.shadowOf(handler.getLooper());
+        mReceiver = new NextProvisionFailedStepReceiver(
+                MoreExecutors.newSequentialExecutor(handler::post));
+        mIntent = new Intent(mTestApp, NextProvisionFailedStepReceiver.class);
+
+        Configuration config = new Configuration.Builder()
+                .setMinimumLoggingLevel(android.util.Log.DEBUG)
+                .setExecutor(new SynchronousExecutor())
+                .build();
+        WorkManagerTestInitHelper.initializeTestWorkManager(mTestApp, config);
+    }
+
+    @Ignore //TODO(b/288107276): Figure out how to fix this test
+    @Test
+    public void onReceive_nextProvisionStateDismissibleUI_shouldReportState() throws Exception {
+        // GIVEN last received provision state is DISMISSIBLE_UI
+        mGlobalParameters.setLastReceivedProvisionState(PROVISION_STATE_DISMISSIBLE_UI).get();
+
+        mReceiver.onReceive(mTestApp, mIntent);
+        mShadowLooper.idle();
+
+        verifyReportProvisionStateWorkScheduled(WorkManager.getInstance(mTestApp));
+    }
+
+    @Test
+    public void onReceive_nextProvisionStatePersistentUI_shouldReportState() throws Exception {
+        // GIVEN last received provision state is PROVISION_STATE_PERSISTENT_UI
+        mGlobalParameters.setLastReceivedProvisionState(PROVISION_STATE_PERSISTENT_UI).get();
+
+        mReceiver.onReceive(mTestApp, mIntent);
+        mShadowLooper.idle();
+
+        verifyReportProvisionStateWorkScheduled(WorkManager.getInstance(mTestApp));
+    }
+
+    @Ignore //TODO(b/288937639): Figure out how to verify the expectation
+    @Test
+    public void onReceive_nextProvisionStateFactoryReset_shouldResetDevice() {
+    }
+
+    @Test
+    public void onReceive_nextProvisionStateUnspecified_shouldNotReportState() throws Exception {
+        // GIVEN last received provision state is PROVISION_STATE_UNSPECIFIED
+        mGlobalParameters.setLastReceivedProvisionState(PROVISION_STATE_UNSPECIFIED).get();
+
+        mReceiver.onReceive(mTestApp, mIntent);
+        mShadowLooper.idle();
+
+        verifyReportProvisionStateWorkNotScheduled(WorkManager.getInstance(mTestApp));
+    }
+
+    @Test
+    public void doWork_nextProvisionStateSuccess_shouldNotReportState() throws Exception {
+        // GIVEN last received provision state is PROVISION_STATE_SUCCESS
+        mGlobalParameters.setLastReceivedProvisionState(PROVISION_STATE_SUCCESS).get();
+
+        mReceiver.onReceive(mTestApp, mIntent);
+        mShadowLooper.idle();
+
+        verifyReportProvisionStateWorkNotScheduled(WorkManager.getInstance(mTestApp));
+    }
+
+    @Test
+    public void doWork_nextProvisionStateRetry_shouldNotReportState() throws Exception {
+        // GIVEN last received provision state is PROVISION_STATE_RETRY
+        mGlobalParameters.setLastReceivedProvisionState(PROVISION_STATE_RETRY).get();
+
+        mReceiver.onReceive(mTestApp, mIntent);
+        mShadowLooper.idle();
+
+        verifyReportProvisionStateWorkNotScheduled(WorkManager.getInstance(mTestApp));
+    }
+
+    private static void verifyReportProvisionStateWorkScheduled(WorkManager workManager)
+            throws Exception {
+        // THEN report provision work should be scheduled
+        List<WorkInfo> actualWorks = workManager.getWorkInfosForUniqueWork(
+                REPORT_PROVISION_STATE_WORK_NAME).get();
+        assertThat(actualWorks.size()).isEqualTo(1);
+        WorkInfo actualWorkInfo = actualWorks.get(0);
+        assertThat(actualWorkInfo.getConstraints().getRequiredNetworkType()).isEqualTo(
+                NetworkType.CONNECTED);
+    }
+
+    private static void verifyReportProvisionStateWorkNotScheduled(WorkManager workManager)
+            throws Exception {
+        // THEN report provision work should not be scheduled
+        List<WorkInfo> actualWorks = workManager.getWorkInfosForUniqueWork(
+                REPORT_PROVISION_STATE_WORK_NAME).get();
+        assertThat(actualWorks.size()).isEqualTo(0);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/RecordBootTimestampReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/RecordBootTimestampReceiverTest.java
new file mode 100644
index 0000000..2904a27
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/RecordBootTimestampReceiverTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Intent;
+import android.os.SystemClock;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.storage.UserParameters;
+import com.android.devicelockcontroller.util.ThreadUtils;
+
+import com.google.common.collect.Range;
+import com.google.common.util.concurrent.Futures;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.time.Clock;
+import java.time.Instant;
+
+@RunWith(RobolectricTestRunner.class)
+public final class RecordBootTimestampReceiverTest {
+    private static final Intent INTENT = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED);
+    private RecordBootTimestampReceiver mReceiver;
+    private final TestDeviceLockControllerApplication mTestApplication =
+            ApplicationProvider.getApplicationContext();
+    // Maximum allowed drift due to difference in sampling between current time and elapsed time.
+    private static final long MAX_DRIFT = 500;
+
+    @Before
+    public void setUp() {
+        mReceiver = new RecordBootTimestampReceiver();
+    }
+
+    @Test
+    public void onReceive_shouldRecordBootTime() {
+        long bootTime = Instant.now(Clock.systemUTC())
+                .minusMillis(SystemClock.elapsedRealtime()).toEpochMilli();
+
+        // Receiver records boot time to user parameters.
+        mReceiver.onReceive(mTestApplication, INTENT);
+
+        Futures.getUnchecked(
+                Futures.submit(
+                        () -> assertThat(
+                                UserParameters.getBootTimeMillis(mTestApplication))
+                                .isIn(Range.closed(bootTime, bootTime + MAX_DRIFT)),
+                        ThreadUtils.getSequentialSchedulerExecutor()));
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/ResetDeviceReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/ResetDeviceReceiverTest.java
new file mode 100644
index 0000000..6e1f317
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/ResetDeviceReceiverTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_MANDATORY_PROVISION;
+
+import static org.mockito.Mockito.verify;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.stats.StatsLogger;
+import com.android.devicelockcontroller.stats.StatsLoggerProvider;
+import com.android.devicelockcontroller.storage.SetupParametersClient;
+
+import com.google.common.util.concurrent.testing.TestingExecutors;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.ExecutionException;
+
+@RunWith(RobolectricTestRunner.class)
+public class ResetDeviceReceiverTest {
+    private SetupParametersClient mSetupParameters;
+    private Intent mIntent;
+    private TestDeviceLockControllerApplication mTestApp;
+    private ResetDeviceReceiver mReceiver;
+    private StatsLogger mStatsLogger;
+
+    @Before
+    public void setUp() throws Exception {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        mSetupParameters = SetupParametersClient.getInstance();
+        mIntent = new Intent(mTestApp, ResetDeviceReceiver.class);
+        mReceiver = new ResetDeviceReceiver(TestingExecutors.sameThreadScheduledExecutor());
+        StatsLoggerProvider loggerProvider =
+                (StatsLoggerProvider) mTestApp.getApplicationContext();
+        mStatsLogger = loggerProvider.getStatsLogger();
+    }
+
+    @Test
+    public void onReceive_shouldLogToStatsLoggerWhenCalled_whenProvisionIsMandatory()
+            throws ExecutionException, InterruptedException {
+        final Bundle bundle = new Bundle();
+        bundle.putBoolean(EXTRA_MANDATORY_PROVISION, true);
+        mSetupParameters.createPrefs(bundle).get();
+
+        mReceiver.onReceive(mTestApp, mIntent);
+
+        verify(mStatsLogger).logDeviceReset(/* isProvisionMandatory= */true);
+    }
+
+    @Test
+    public void onReceive_shouldLogToStatsLoggerWhenCalled_whenProvisionIsNotMandatory()
+            throws ExecutionException, InterruptedException {
+        final Bundle bundle = new Bundle();
+        bundle.putBoolean(EXTRA_MANDATORY_PROVISION, false);
+        mSetupParameters.createPrefs(bundle).get();
+
+        mReceiver.onReceive(mTestApp, mIntent);
+
+        verify(mStatsLogger).logDeviceReset(/* isProvisionMandatory= */false);
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/ResumeProvisionReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/ResumeProvisionReceiverTest.java
new file mode 100644
index 0000000..fba01fb
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/ResumeProvisionReceiverTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_RESUME;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.content.Intent;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
+import com.android.devicelockcontroller.policy.ProvisionStateController;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class ResumeProvisionReceiverTest {
+
+
+    @Test
+    public void onReceive_setStateSuccess() {
+        ResumeProvisionReceiver resumeProvisionReceiver = new ResumeProvisionReceiver();
+        TestDeviceLockControllerApplication testApp = ApplicationProvider.getApplicationContext();
+        Intent intent = new Intent(testApp, ResumeProvisionReceiver.class);
+        ProvisionStateController stateController =
+                ((PolicyObjectsProvider) testApp).getProvisionStateController();
+
+        resumeProvisionReceiver.onReceive(testApp, intent);
+
+        verify(stateController).postSetNextStateForEventRequest(eq(PROVISION_RESUME));
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/TimeChangedBroadcastReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/TimeChangedBroadcastReceiverTest.java
new file mode 100644
index 0000000..d4870d0
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/TimeChangedBroadcastReceiverTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import static org.mockito.Mockito.verify;
+
+import android.content.Intent;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public final class TimeChangedBroadcastReceiverTest {
+    private TestDeviceLockControllerApplication mTestApp;
+    private TimeChangedBroadcastReceiver mReceiver;
+
+    @Before
+    public void setUp() {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        mReceiver = new TimeChangedBroadcastReceiver();
+    }
+
+    @Test
+    public void onReceive_shouldNotifySchedulerTimeChanged() {
+        // WHEN time changed broadcast received
+        mReceiver.onReceive(mTestApp, new Intent(Intent.ACTION_TIME_CHANGED));
+
+        // THEN should should notify scheduler time changed.
+        verify(mTestApp.getDeviceLockControllerScheduler()).notifyTimeChanged();
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/WorkFailureAlarmReceiverTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/WorkFailureAlarmReceiverTest.java
new file mode 100644
index 0000000..08b4a01
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/receivers/WorkFailureAlarmReceiverTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.receivers;
+
+import static com.android.devicelockcontroller.WorkManagerExceptionHandler.ALARM_REASON;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.WorkManagerExceptionHandler;
+import com.android.devicelockcontroller.WorkManagerExceptionHandler.AlarmReason;
+import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler;
+import com.android.devicelockcontroller.storage.GlobalParametersClient;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(RobolectricTestRunner.class)
+public final class WorkFailureAlarmReceiverTest {
+    private static final long TIMEOUT_MILLIS = 1000;
+
+    private DeviceLockControllerScheduler mScheduler;
+    private TestDeviceLockControllerApplication mTestApp;
+    private Handler mHandler;
+
+    @Before
+    public void setUp() {
+        final HandlerThread handlerThread = new HandlerThread("BroadcastHandlerThread");
+        handlerThread.start();
+        mHandler = handlerThread.getThreadHandler();
+
+        mTestApp = ApplicationProvider.getApplicationContext();
+        mScheduler = mTestApp.getDeviceLockControllerScheduler();
+    }
+
+    @Test
+    public void onReceive_reasonInitialization_shouldCallMaybeScheduleInitialCheckIn()
+            throws Exception {
+        GlobalParametersClient.getInstance().setProvisionReady(false).get();
+
+        when(mScheduler.maybeScheduleInitialCheckIn()).thenReturn(Futures.immediateVoidFuture());
+
+        final ListenableFuture<Void> broadcastComplete =
+                sendBroadcastToWorkFailureAlarmReceiver(AlarmReason.INITIALIZATION);
+
+        shadowOf(Looper.getMainLooper()).idle();
+
+        broadcastComplete.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+
+        verify(mScheduler).maybeScheduleInitialCheckIn();
+        verifyNoMoreInteractions(mScheduler);
+    }
+
+    @Test
+    public void onReceive_reasonInitialCheckIn_shouldCallMaybeScheduleInitialCheckIn()
+            throws Exception {
+        GlobalParametersClient.getInstance().setProvisionReady(false).get();
+
+        when(mScheduler.maybeScheduleInitialCheckIn()).thenReturn(Futures.immediateVoidFuture());
+
+        final ListenableFuture<Void> broadcastComplete =
+                sendBroadcastToWorkFailureAlarmReceiver(AlarmReason.INITIAL_CHECK_IN);
+
+        shadowOf(Looper.getMainLooper()).idle();
+
+        broadcastComplete.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+
+        verify(mScheduler).maybeScheduleInitialCheckIn();
+        verifyNoMoreInteractions(mScheduler);
+    }
+
+    @Test
+    public void onReceive_reasonRetryCheckIn_shouldCallScheduleRetryCheckInWork() throws Exception {
+        GlobalParametersClient.getInstance().setProvisionReady(false).get();
+
+        when(mScheduler.scheduleRetryCheckInWork(any(Duration.class)))
+                .thenReturn(Futures.immediateVoidFuture());
+
+        final ListenableFuture<Void> broadcastComplete =
+                sendBroadcastToWorkFailureAlarmReceiver(AlarmReason.RETRY_CHECK_IN);
+
+        shadowOf(Looper.getMainLooper()).idle();
+
+        broadcastComplete.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+
+        verify(mScheduler).scheduleRetryCheckInWork(eq(Duration.ZERO));
+        verifyNoMoreInteractions(mScheduler);
+    }
+
+    @Test
+    public void onReceive_reasonRescheduleCheckIn_shouldCallNotifyNeedRescheduleCheckIn()
+            throws Exception {
+        GlobalParametersClient.getInstance().setProvisionReady(false).get();
+
+        when(mScheduler.notifyNeedRescheduleCheckIn()).thenReturn(Futures.immediateVoidFuture());
+
+        final ListenableFuture<Void> broadcastComplete =
+                sendBroadcastToWorkFailureAlarmReceiver(AlarmReason.RESCHEDULE_CHECK_IN);
+
+        shadowOf(Looper.getMainLooper()).idle();
+
+        broadcastComplete.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+
+        verify(mScheduler).notifyNeedRescheduleCheckIn();
+        verifyNoMoreInteractions(mScheduler);
+    }
+
+    @Test
+    public void onReceive_whenProvisionReady_doesNotSchedule() throws Exception {
+        GlobalParametersClient.getInstance().setProvisionReady(true).get();
+
+        when(mScheduler.maybeScheduleInitialCheckIn()).thenReturn(Futures.immediateVoidFuture());
+
+        final ListenableFuture<Void> broadcastComplete =
+                sendBroadcastToWorkFailureAlarmReceiver(AlarmReason.INITIALIZATION);
+
+        shadowOf(Looper.getMainLooper()).idle();
+
+        broadcastComplete.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+
+        verifyNoInteractions(mScheduler);
+    }
+
+    private Intent getIntentForAlarmReason(@AlarmReason int alarmReason) {
+        final Intent intent = new Intent(mTestApp,
+                WorkManagerExceptionHandler.WorkFailureAlarmReceiver.class);
+        final Bundle bundle = new Bundle();
+        bundle.putInt(ALARM_REASON, alarmReason);
+        intent.putExtras(bundle);
+        return intent;
+    }
+
+    private ListenableFuture<Void> sendBroadcastToWorkFailureAlarmReceiver(
+            @AlarmReason int alarmReason) {
+        final SettableFuture<Void> broadcastComplete = SettableFuture.create();
+
+        mTestApp.sendOrderedBroadcast(
+                getIntentForAlarmReason(alarmReason),
+                null /* receiverPermission */,
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        broadcastComplete.set(null);
+                    }
+                },
+                mHandler /* scheduler */,
+                0 /* initialCode */,
+                null /* initialData */,
+                null /* initialExtras */);
+
+        return broadcastComplete;
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/schedule/DeviceLockControllerSchedulerImplTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/schedule/DeviceLockControllerSchedulerImplTest.java
new file mode 100644
index 0000000..b5269ba
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/schedule/DeviceLockControllerSchedulerImplTest.java
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.schedule;
+
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_PAUSED;
+import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED;
+import static com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerImpl.DEVICE_CHECK_IN_WORK_NAME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.os.SystemClock;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.work.Configuration;
+import androidx.work.ExistingWorkPolicy;
+import androidx.work.NetworkType;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+import androidx.work.testing.SynchronousExecutor;
+import androidx.work.testing.WorkManagerTestInitHelper;
+
+import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
+import com.android.devicelockcontroller.common.DeviceLockConstants;
+import com.android.devicelockcontroller.provision.worker.DeviceCheckInWorker;
+import com.android.devicelockcontroller.shadows.ShadowBuild;
+import com.android.devicelockcontroller.storage.UserParameters;
+import com.android.devicelockcontroller.util.ThreadUtils;
+
+import com.google.common.util.concurrent.Futures;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowAlarmManager;
+
+import java.time.Clock;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(RobolectricTestRunner.class)
+public final class DeviceLockControllerSchedulerImplTest {
+    private static final long PROVISION_PAUSED_MILLIS = TimeUnit.MINUTES.toMillis(
+            DeviceLockControllerSchedulerImpl.PROVISION_PAUSED_MINUTES_DEFAULT);
+    private static final Duration TEST_RETRY_CHECK_IN_DELAY = Duration.ofDays(30);
+    private static final long TEST_NEXT_CHECK_IN_TIME_MILLIS = Duration.ofHours(10).toMillis();
+    private static final long TEST_RESUME_PROVISION_TIME_MILLIS = Duration.ofHours(20).toMillis();
+    private static final long TEST_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS = Duration.ofHours(
+            2).toMillis();
+    private static final long TEST_RESET_DEVICE_TIME_MILLIS = Duration.ofHours(
+            50).toMillis();
+
+    private static final long PROVISION_STATE_REPORT_INTERVAL_MILLIS = TimeUnit.MINUTES.toMillis(
+            DeviceLockControllerSchedulerImpl.PROVISION_STATE_REPORT_INTERVAL_DEFAULT_MINUTES);
+    private static final long TEST_CURRENT_TIME_MILLIS = Duration.ofHours(5).toMillis();
+    private static final Clock TEST_CLOCK = Clock.fixed(
+            Instant.ofEpochMilli(TEST_CURRENT_TIME_MILLIS),
+            ZoneOffset.UTC);
+    public static final long TEST_POSITIVE_DELTA_MILLIS = Duration.ofHours(5).toMillis();
+    public static final long TEST_NEGATIVE_DELTA_MILLIS = Duration.ofHours(-5).toMillis();
+    private static final long RESET_DEVICE_MILLIS = TimeUnit.MINUTES.toMillis(
+            DeviceLockConstants.NON_MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE);
+    DeviceLockControllerSchedulerImpl mScheduler;
+    TestDeviceLockControllerApplication mTestApp;
+
+    @Before
+    public void setUp() throws Exception {
+        mTestApp = ApplicationProvider.getApplicationContext();
+        mScheduler = new DeviceLockControllerSchedulerImpl(mTestApp, TEST_CLOCK,
+                mTestApp.getProvisionStateController());
+        Configuration config = new Configuration.Builder()
+                .setMinimumLoggingLevel(android.util.Log.DEBUG)
+                .setExecutor(new SynchronousExecutor())
+                .build();
+        WorkManagerTestInitHelper.initializeTestWorkManager(mTestApp, config);
+    }
+
+    @Test
+    public void correctExpectedToRunTime_retryCheckInExpected_positiveDelta_shouldUpdate() {
+        // GIVEN retry check in is expected
+        UserParameters.setNextCheckInTimeMillis(mTestApp, TEST_NEXT_CHECK_IN_TIME_MILLIS);
+
+        // GIVEN time change delta is positive.
+        UserParameters.setBootTimeMillis(mTestApp,
+                TEST_CURRENT_TIME_MILLIS - TEST_POSITIVE_DELTA_MILLIS
+                        - SystemClock.elapsedRealtime());
+
+
+        runBySequentialExecutor(() -> {
+            // WHEN correct expected to run time for UNPROVISIONED state
+            mScheduler.correctStoredTime(UNPROVISIONED);
+
+            // THEN next check in time should be updated
+            long expectedToRunAfterChange =
+                    TEST_NEXT_CHECK_IN_TIME_MILLIS + TEST_POSITIVE_DELTA_MILLIS;
+            assertThat(UserParameters.getNextCheckInTimeMillis(mTestApp)).isEqualTo(
+                    expectedToRunAfterChange);
+        });
+    }
+
+
+    @Test
+    public void correctExpectedToRunTime_retryCheckInExpected_negativeDelta_shouldUpdate() {
+        // GIVEN retry check in is expected
+        UserParameters.setNextCheckInTimeMillis(mTestApp, TEST_NEXT_CHECK_IN_TIME_MILLIS);
+
+        // GIVEN time change delta is negative.
+        UserParameters.setBootTimeMillis(mTestApp,
+                TEST_CURRENT_TIME_MILLIS - TEST_NEGATIVE_DELTA_MILLIS
+                        - SystemClock.elapsedRealtime());
+
+        runBySequentialExecutor(() -> {
+            // WHEN correct expected to run time for UNPROVISIONED state
+            mScheduler.correctStoredTime(UNPROVISIONED);
+
+            // THEN next check in time should be updated
+            long expectedToRunAfterChange =
+                    TEST_NEXT_CHECK_IN_TIME_MILLIS + TEST_NEGATIVE_DELTA_MILLIS;
+            assertThat(UserParameters.getNextCheckInTimeMillis(mTestApp)).isEqualTo(
+                    expectedToRunAfterChange);
+        });
+    }
+
+    @Test
+    public void correctExpectedToRunTime_resumeProvisionExpected_positiveDelta_shouldUpdate() {
+        // GIVEN retry check in is expected
+        UserParameters.setResumeProvisionTimeMillis(mTestApp, TEST_RESUME_PROVISION_TIME_MILLIS);
+
+        // GIVEN time change delta is positive.
+        UserParameters.setBootTimeMillis(mTestApp,
+                TEST_CURRENT_TIME_MILLIS - TEST_POSITIVE_DELTA_MILLIS
+                        - SystemClock.elapsedRealtime());
+
+        runBySequentialExecutor(() -> {
+            // WHEN correct expected to run time for PROVISION_PAUSED state
+            mScheduler.correctStoredTime(PROVISION_PAUSED);
+
+            // THEN next check in time should be updated
+            long expectedToRunAfterChange =
+                    TEST_RESUME_PROVISION_TIME_MILLIS + TEST_POSITIVE_DELTA_MILLIS;
+            assertThat(UserParameters.getResumeProvisionTimeMillis(mTestApp)).isEqualTo(
+                    expectedToRunAfterChange);
+        });
+    }
+
+    @Test
+    public void correctExpectedToRunTime_resumeProvisionExpected_negativeDelta_shouldUpdate() {
+        // GIVEN retry check in is expected
+        UserParameters.setResumeProvisionTimeMillis(mTestApp, TEST_RESUME_PROVISION_TIME_MILLIS);
+
+        // GIVEN time change delta is negative.
+        UserParameters.setBootTimeMillis(mTestApp,
+                TEST_CURRENT_TIME_MILLIS - TEST_NEGATIVE_DELTA_MILLIS
+                        - SystemClock.elapsedRealtime());
+
+        runBySequentialExecutor(() -> {
+            // WHEN correct expected to run time for PROVISION_PAUSED state
+            mScheduler.correctStoredTime(PROVISION_PAUSED);
+
+            // THEN next check in time should be updated
+            long expectedToRunAfterChange =
+                    TEST_RESUME_PROVISION_TIME_MILLIS + TEST_NEGATIVE_DELTA_MILLIS;
+            assertThat(UserParameters.getResumeProvisionTimeMillis(mTestApp)).isEqualTo(
+                    expectedToRunAfterChange);
+        });
+    }
+
+    @Test
+    public void scheduleResumeProvisionAlarm() {
+        // GIVEN no alarm is scheduled and no expected resume time
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+        runBySequentialExecutor(() ->
+                assertThat(UserParameters.getResumeProvisionTimeMillis(mTestApp)).isEqualTo(0));
+
+        // WHEN resume provision alarm is scheduled
+        mScheduler.scheduleResumeProvisionAlarm();
+
+        // THEN correct alarm should be scheduled
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+        // THEN alarm should be scheduled at correct time
+        long actualTriggerTime = alarmManager.peekNextScheduledAlarm().triggerAtTime;
+        assertThat(actualTriggerTime).isEqualTo(
+                SystemClock.elapsedRealtime() + PROVISION_PAUSED_MILLIS);
+
+        // THEN expected trigger time should be stored in storage
+        runBySequentialExecutor(() -> {
+            assertThat(UserParameters.getResumeProvisionTimeMillis(mTestApp)).isEqualTo(
+                    TEST_CURRENT_TIME_MILLIS + PROVISION_PAUSED_MILLIS);
+        });
+    }
+
+    @Test
+    public void rescheduleResumeProvisionAlarm() {
+        // GIVEN no alarm is scheduled
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+
+        // GIVEN expected resume time in storage
+        UserParameters.setResumeProvisionTimeMillis(mTestApp, TEST_RESUME_PROVISION_TIME_MILLIS);
+
+        // WHEN resume provision alarm is rescheduled
+        runBySequentialExecutor(mScheduler::rescheduleResumeProvisionAlarmIfNeeded);
+
+        // THEN correct alarm should be scheduled at correct time
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+
+        long expectedTriggerTime = SystemClock.elapsedRealtime()
+                + (TEST_RESUME_PROVISION_TIME_MILLIS - TEST_CURRENT_TIME_MILLIS);
+        assertThat(alarmManager.peekNextScheduledAlarm().triggerAtTime).isEqualTo(
+                expectedTriggerTime);
+    }
+
+    @Test
+    public void scheduleInitialCheckInWork() throws Exception {
+        // GIVEN check-in work is not scheduled
+        WorkManager workManager = WorkManager.getInstance(mTestApp);
+        assertThat(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME).get()).isEmpty();
+
+        // WHEN schedule initial check-in work
+        mScheduler.scheduleInitialCheckInWork();
+
+        // THEN check-in work should be scheduled
+        List<WorkInfo> actualWorks = Futures.getUnchecked(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME));
+        assertThat(actualWorks.size()).isEqualTo(1);
+        WorkInfo actualWorkInfo = actualWorks.get(0);
+        assertThat(actualWorkInfo.getConstraints().getRequiredNetworkType()).isEqualTo(
+                NetworkType.CONNECTED);
+        assertThat(actualWorkInfo.getInitialDelayMillis()).isEqualTo(0);
+    }
+
+    @Test
+    public void scheduleRetryCheckInWork() throws Exception {
+        // GIVEN check-in work is not scheduled
+        WorkManager workManager = WorkManager.getInstance(mTestApp);
+        assertThat(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME).get()).isEmpty();
+
+        // WHEN schedule retry check-in work
+        mScheduler.scheduleRetryCheckInWork(TEST_RETRY_CHECK_IN_DELAY);
+
+        // THEN retry check-in work should be scheduled
+        List<WorkInfo> actualWorks = Futures.getUnchecked(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME));
+        assertThat(actualWorks.size()).isEqualTo(1);
+        WorkInfo actualWorkInfo = actualWorks.get(0);
+        assertThat(actualWorkInfo.getConstraints().getRequiredNetworkType()).isEqualTo(
+                NetworkType.CONNECTED);
+        assertThat(actualWorkInfo.getInitialDelayMillis()).isEqualTo(
+                TEST_RETRY_CHECK_IN_DELAY.toMillis());
+
+        // THEN expected trigger time is stored in storage
+        long expectedTriggerTime =
+                TEST_CURRENT_TIME_MILLIS + TEST_RETRY_CHECK_IN_DELAY.toMillis();
+        runBySequentialExecutor(
+                () -> assertThat(UserParameters.getNextCheckInTimeMillis(mTestApp)).isEqualTo(
+                        expectedTriggerTime));
+    }
+
+    @Test
+    public void rescheduleRetryCheckInWork() {
+        // GIVEN check-in work is scheduled with original delay
+        OneTimeWorkRequest request =
+                new OneTimeWorkRequest.Builder(DeviceCheckInWorker.class)
+                        .setInitialDelay(TEST_RETRY_CHECK_IN_DELAY).build();
+        WorkManager workManager = WorkManager.getInstance(mTestApp);
+        workManager.enqueueUniqueWork(DEVICE_CHECK_IN_WORK_NAME,
+                ExistingWorkPolicy.REPLACE,
+                request);
+
+        // GIVEN expected trigger time
+        UserParameters.setNextCheckInTimeMillis(mTestApp, TEST_NEXT_CHECK_IN_TIME_MILLIS);
+
+        // WHEN reschedule retry check-in work
+        runBySequentialExecutor(mScheduler::rescheduleRetryCheckInWork);
+
+        // THEN retry check-in work should be scheduled with correct delay
+        List<WorkInfo> actualWorks = Futures.getUnchecked(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME));
+        assertThat(actualWorks.size()).isEqualTo(1);
+        WorkInfo actualWorkInfo = actualWorks.get(0);
+        assertThat(actualWorkInfo.getConstraints().getRequiredNetworkType()).isEqualTo(
+                NetworkType.CONNECTED);
+
+        long expectedDelay = TEST_NEXT_CHECK_IN_TIME_MILLIS - TEST_CURRENT_TIME_MILLIS;
+        assertThat(actualWorkInfo.getInitialDelayMillis()).isEqualTo(expectedDelay);
+    }
+
+    @Test
+    public void maybeScheduleInitialCheckIn_needInitialCheckIn_enqueuesWorker() throws Exception {
+        // Make sure the initial state is "initial check in needed"
+        runBySequentialExecutor(
+                () -> assertThat(UserParameters.needInitialCheckIn(mTestApp)).isTrue());
+
+        // GIVEN check-in work is not scheduled
+        WorkManager workManager = WorkManager.getInstance(mTestApp);
+        assertThat(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME).get()).isEmpty();
+
+        // WHEN maybe schedule initial check-in work
+        mScheduler.maybeScheduleInitialCheckIn().get();
+
+        // THEN check-in work should be scheduled
+        assertThat(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME).get()).isNotEmpty();
+    }
+
+    @Test
+    public void maybeScheduleInitialCheckIn_NoNeedInitialCheckIn_noWorker() throws Exception {
+        // GIVEN initial check in marked as scheduled
+        UserParameters.initialCheckInScheduled(mTestApp);
+
+        // GIVEN check-in work is not scheduled
+        WorkManager workManager = WorkManager.getInstance(mTestApp);
+        assertThat(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME).get()).isEmpty();
+
+        // WHEN maybe schedule initial check-in work
+        mScheduler.maybeScheduleInitialCheckIn().get();
+
+        // THEN check-in work should not be scheduled
+        assertThat(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME).get()).isEmpty();
+    }
+
+    @Test
+    public void maybeScheduleInitialCheckIn_noNeedCheckIn_reschedule() throws Exception {
+        // GIVEN check-in work is scheduled with original delay
+        OneTimeWorkRequest request =
+                new OneTimeWorkRequest.Builder(DeviceCheckInWorker.class)
+                        .setInitialDelay(TEST_RETRY_CHECK_IN_DELAY).build();
+        WorkManager workManager = WorkManager.getInstance(mTestApp);
+        workManager.enqueueUniqueWork(DEVICE_CHECK_IN_WORK_NAME,
+                ExistingWorkPolicy.REPLACE,
+                request);
+
+        // GIVEN initial check in marked as scheduled
+        UserParameters.initialCheckInScheduled(mTestApp);
+
+        // GIVEN expected trigger time
+        UserParameters.setNextCheckInTimeMillis(mTestApp, TEST_NEXT_CHECK_IN_TIME_MILLIS);
+
+        // WHEN maybe schedule initial check-in work
+        mScheduler.maybeScheduleInitialCheckIn().get();
+
+        // THEN retry check-in work should be scheduled with correct delay
+        List<WorkInfo> actualWorks = Futures.getUnchecked(workManager.getWorkInfosForUniqueWork(
+                DEVICE_CHECK_IN_WORK_NAME));
+        assertThat(actualWorks.size()).isEqualTo(1);
+        WorkInfo actualWorkInfo = actualWorks.get(0);
+        assertThat(actualWorkInfo.getConstraints().getRequiredNetworkType()).isEqualTo(
+                NetworkType.CONNECTED);
+
+        long expectedDelay = TEST_NEXT_CHECK_IN_TIME_MILLIS - TEST_CURRENT_TIME_MILLIS;
+        assertThat(actualWorkInfo.getInitialDelayMillis()).isEqualTo(expectedDelay);
+    }
+
+    @Test
+    public void scheduleNextProvisionFailedStepAlarm_initialStep_defaultDelay() {
+        // GIVEN no alarm is scheduled
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+
+        // GIVEN no existing timestamp
+        runBySequentialExecutor(() -> assertThat(
+                UserParameters.getNextProvisionFailedStepTimeMills(mTestApp)).isEqualTo(0));
+
+        // WHEN schedule next provision failed step alarm
+        runBySequentialExecutor(
+                () -> mScheduler.scheduleNextProvisionFailedStepAlarm(
+                        /* shouldGoOffImmediately= */ false));
+
+        // THEN correct alarm should be scheduled
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+        // THEN alarm should be scheduled at correct time
+        long actualTriggerTime = alarmManager.peekNextScheduledAlarm().triggerAtTime;
+        assertThat(actualTriggerTime).isEqualTo(
+                SystemClock.elapsedRealtime() + PROVISION_STATE_REPORT_INTERVAL_MILLIS);
+
+        // THEN expected trigger time should be stored in storage
+        runBySequentialExecutor(() -> assertThat(
+                UserParameters.getNextProvisionFailedStepTimeMills(mTestApp)).isEqualTo(
+                TEST_CURRENT_TIME_MILLIS + PROVISION_STATE_REPORT_INTERVAL_MILLIS));
+    }
+
+    @Test
+    public void scheduleNextProvisionFailedStepAlarm_initialStep_noDelay() {
+        // GIVEN no alarm is scheduled
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+
+        // GIVEN no existing timestamp
+        runBySequentialExecutor(() -> assertThat(
+                UserParameters.getNextProvisionFailedStepTimeMills(mTestApp)).isEqualTo(0));
+
+        // WHEN schedule next provision failed step alarm
+        runBySequentialExecutor(
+                () -> mScheduler.scheduleNextProvisionFailedStepAlarm(
+                        /* shouldGoOffImmediately= */ true));
+
+        // THEN correct alarm should be scheduled
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+        // THEN alarm should be scheduled at correct time
+        long actualTriggerTime = alarmManager.peekNextScheduledAlarm().triggerAtTime;
+        assertThat(actualTriggerTime).isEqualTo(SystemClock.elapsedRealtime());
+
+        // THEN expected trigger time should be stored in storage
+        runBySequentialExecutor(() -> assertThat(
+                UserParameters.getNextProvisionFailedStepTimeMills(mTestApp)).isEqualTo(
+                TEST_CURRENT_TIME_MILLIS));
+    }
+
+    @Test
+    public void scheduleNextProvisionFailedStepAlarm_debuggable_initialStep_noDelay() {
+        // GIVEN build is debuggable build
+        ShadowBuild.setIsDebuggable(true);
+
+        // GIVEN no alarm is scheduled
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+
+        // GIVEN no existing timestamp
+        runBySequentialExecutor(() -> assertThat(
+                UserParameters.getNextProvisionFailedStepTimeMills(mTestApp)).isEqualTo(0));
+
+        // WHEN schedule next provision failed step alarm
+        runBySequentialExecutor(
+                () -> mScheduler.scheduleNextProvisionFailedStepAlarm(
+                        /* shouldGoOffImmediately= */ true));
+
+        // THEN correct alarm should be scheduled
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+        // THEN alarm should be scheduled at correct time
+        long actualTriggerTime = alarmManager.peekNextScheduledAlarm().triggerAtTime;
+        assertThat(actualTriggerTime).isEqualTo(SystemClock.elapsedRealtime());
+
+        // THEN expected trigger time should be stored in storage
+        runBySequentialExecutor(() -> assertThat(
+                UserParameters.getNextProvisionFailedStepTimeMills(mTestApp)).isEqualTo(
+                TEST_CURRENT_TIME_MILLIS));
+    }
+
+    @Test
+    public void scheduleNextProvisionFailedStepAlarm_followUpStep_defaultDelay() {
+        // GIVEN no alarm is scheduled
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+
+        // GIVEN timestamp exists for last performed step.
+        UserParameters.setNextProvisionFailedStepTimeMills(mTestApp,
+                TEST_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS);
+
+        // WHEN schedule next provision failed step alarm
+        runBySequentialExecutor(
+                () -> mScheduler.scheduleNextProvisionFailedStepAlarm(
+                        /* shouldGoOffImmediately= */ false));
+
+        // THEN correct alarm should be scheduled
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+        // THEN alarm should be scheduled at correct time
+        long actualTriggerTime = alarmManager.peekNextScheduledAlarm().triggerAtTime;
+        long expectedTriggerTime = TEST_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS
+                + PROVISION_STATE_REPORT_INTERVAL_MILLIS - TEST_CURRENT_TIME_MILLIS
+                + SystemClock.elapsedRealtime();
+        assertThat(actualTriggerTime).isEqualTo(expectedTriggerTime);
+
+
+        // THEN expected trigger time should be stored in storage
+        runBySequentialExecutor(() -> assertThat(
+                UserParameters.getNextProvisionFailedStepTimeMills(mTestApp)).isEqualTo(
+                TEST_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS
+                        + PROVISION_STATE_REPORT_INTERVAL_MILLIS));
+    }
+
+    @Test
+    public void scheduleNextProvisionFailedStepAlarm_followUpStep_noDelay() {
+        // GIVEN no alarm is scheduled
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+
+        // GIVEN timestamp exists for last performed step.
+        UserParameters.setNextProvisionFailedStepTimeMills(mTestApp,
+                TEST_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS);
+
+        // WHEN schedule next provision failed step alarm
+        runBySequentialExecutor(
+                () -> mScheduler.scheduleNextProvisionFailedStepAlarm(
+                        /* shouldGoOffImmediately= */ true));
+
+        // THEN correct alarm should be scheduled
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+        // THEN alarm should be scheduled at correct time
+        long actualTriggerTime = alarmManager.peekNextScheduledAlarm().triggerAtTime;
+        long expectedTriggerTime =
+                TEST_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS - TEST_CURRENT_TIME_MILLIS
+                        + SystemClock.elapsedRealtime();
+        assertThat(actualTriggerTime).isEqualTo(expectedTriggerTime);
+
+
+        // THEN expected trigger time should be stored in storage
+        runBySequentialExecutor(() -> assertThat(
+                UserParameters.getNextProvisionFailedStepTimeMills(mTestApp)).isEqualTo(
+                TEST_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS));
+    }
+
+    @Test
+    public void scheduleResetDeviceAlarm() {
+        // GIVEN no alarm is scheduled
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+        runBySequentialExecutor(
+                () -> assertThat(UserParameters.getResetDeviceTimeMillis(mTestApp)).isEqualTo(0));
+
+        // WHEN schedule reset device alarm
+        mScheduler.scheduleResetDeviceAlarm();
+
+        // THEN correct alarm should be scheduled
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+        // THEN alarm should be scheduled at correct time
+        long actualTriggerTime = alarmManager.peekNextScheduledAlarm().triggerAtTime;
+        assertThat(actualTriggerTime).isEqualTo(
+                SystemClock.elapsedRealtime() + RESET_DEVICE_MILLIS);
+
+        // THEN expected trigger time should be stored in storage
+        runBySequentialExecutor(
+                () -> assertThat(UserParameters.getResetDeviceTimeMillis(mTestApp)).isEqualTo(
+                        TEST_CURRENT_TIME_MILLIS + RESET_DEVICE_MILLIS));
+    }
+
+    @Test
+    public void rescheduleNextProvisionFailedStepAlarm() {
+        // GIVEN no alarm is scheduled
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+
+        // GIVEN expected time in storage
+        UserParameters.setNextProvisionFailedStepTimeMills(mTestApp,
+                TEST_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS);
+
+        // WHEN next provision failed step alarm is rescheduled
+        runBySequentialExecutor(mScheduler::rescheduleNextProvisionFailedStepAlarmIfNeeded);
+
+        // THEN correct alarm should be scheduled at correct time
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+        long expectedTriggerTime = SystemClock.elapsedRealtime()
+                + (TEST_NEXT_PROVISION_FAILED_STEP_TIME_MILLIS - TEST_CURRENT_TIME_MILLIS);
+        assertThat(alarmManager.peekNextScheduledAlarm().triggerAtTime).isEqualTo(
+                expectedTriggerTime);
+    }
+
+    @Test
+    public void rescheduleResetDeviceAlarm() {
+        // GIVEN no alarm is scheduled
+        ShadowAlarmManager alarmManager = Shadows.shadowOf(
+                mTestApp.getSystemService(AlarmManager.class));
+        assertThat(alarmManager.peekNextScheduledAlarm()).isNull();
+
+        // GIVEN expected reset device time in storage
+        UserParameters.setResetDeviceTimeMillis(mTestApp, TEST_RESET_DEVICE_TIME_MILLIS);
+
+        // WHEN reset device alarm is rescheduled
+        runBySequentialExecutor(mScheduler::rescheduleResetDeviceAlarmIfNeeded);
+
+        // THEN correct alarm should be scheduled at correct time
+        PendingIntent actualPendingIntent = alarmManager.peekNextScheduledAlarm().operation;
+        assertThat(actualPendingIntent.isBroadcast()).isTrue();
+
+        long expectedTriggerTime = SystemClock.elapsedRealtime()
+                + (TEST_RESET_DEVICE_TIME_MILLIS - TEST_CURRENT_TIME_MILLIS);
+        assertThat(alarmManager.peekNextScheduledAlarm().triggerAtTime).isEqualTo(
+                expectedTriggerTime);
+    }
+
+    private static void runBySequentialExecutor(Runnable runnable) {
+        Futures.getUnchecked(
+                Futures.submit(runnable, ThreadUtils.getSequentialSchedulerExecutor()));
+    }
+}
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/AbstractGlobalParametersTestBase.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/AbstractGlobalParametersTestBase.java
index bccbc82..d024003 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/AbstractGlobalParametersTestBase.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/AbstractGlobalParametersTestBase.java
@@ -19,14 +19,8 @@
 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
 
 abstract class AbstractGlobalParametersTestBase {
-    static final String ALLOWLIST_PACKAGE_0 = "allowlist.package.0";
-    static final String ALLOWLIST_PACKAGE_1 = "allowlist.package.1";
-
-    static final String KIOSK_SIGNING_CERT = "signing_certificate";
-    static final boolean NEED_CHECK_IN = false;
     static final String REGISTERED_DEVICE_ID = "test_id";
     static final boolean FORCED_PROVISION = true;
-    static final String ENROLLMENT_TOKEN = "test_enrollment_token";
 
     @DeviceProvisionState
     static final int LAST_RECEIVED_PROVISION_STATE = DeviceProvisionState.PROVISION_STATE_RETRY;
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/AbstractSetupParametersTestBase.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/AbstractSetupParametersTestBase.java
index bd96991..b0697b1 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/AbstractSetupParametersTestBase.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/AbstractSetupParametersTestBase.java
@@ -22,7 +22,6 @@
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_DISABLE_OUTGOING_CALLS;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
-import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_SETUP_ACTIVITY;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_MANDATORY_PROVISION;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_PROVISIONING_TYPE;
 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_SUPPORT_URL;
@@ -38,7 +37,6 @@
 abstract class AbstractSetupParametersTestBase {
     protected static final String KIOSK_PACKAGE = "package";
     protected static final String KIOSK_OVERRIDE_PACKAGE = "override.package";
-    protected static final String SETUP_ACTIVITY = "setup-activity";
     protected static final boolean DISABLE_OUTGOING_CALLS = true;
     protected static final boolean ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE = true;
     protected static final String KIOSK_ALLOWLIST_PACKAGE_0 = "package.name.0";
@@ -54,7 +52,6 @@
     protected static Bundle createParamsBundle() {
         final Bundle bundle = new Bundle();
         bundle.putString(EXTRA_KIOSK_PACKAGE, KIOSK_PACKAGE);
-        bundle.putString(EXTRA_KIOSK_SETUP_ACTIVITY, SETUP_ACTIVITY);
         bundle.putBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS, DISABLE_OUTGOING_CALLS);
         bundle.putBoolean(
                 EXTRA_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE,
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/GlobalParametersServiceTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/GlobalParametersServiceTest.java
index 7f90310..c824e46 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/GlobalParametersServiceTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/GlobalParametersServiceTest.java
@@ -28,9 +28,6 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.android.controller.ServiceController;
 
-import java.util.ArrayList;
-import java.util.List;
-
 @RunWith(RobolectricTestRunner.class)
 public class GlobalParametersServiceTest extends AbstractGlobalParametersTestBase {
     private IGlobalParametersService mIGlobalParametersService;
@@ -46,26 +43,6 @@
     }
 
     @Test
-    public void getLockTaskAllowlist_shouldReturnExpectedAllowlist() throws RemoteException {
-        assertThat(mIGlobalParametersService.getLockTaskAllowlist()).isEmpty();
-        final ArrayList<String> expectedAllowlist = new ArrayList<>();
-        expectedAllowlist.add(ALLOWLIST_PACKAGE_0);
-        expectedAllowlist.add(ALLOWLIST_PACKAGE_1);
-        mIGlobalParametersService.setLockTaskAllowlist(expectedAllowlist);
-        final List<String> actualAllowlist = mIGlobalParametersService.getLockTaskAllowlist();
-        assertThat(actualAllowlist).containsExactlyElementsIn(expectedAllowlist);
-    }
-
-    @Test
-    public void needCheckIn_shouldReturnExpectedResult() throws RemoteException {
-        assertThat(mIGlobalParametersService.needCheckIn()).isNotEqualTo(NEED_CHECK_IN);
-
-        mIGlobalParametersService.setNeedCheckIn(NEED_CHECK_IN);
-
-        assertThat(mIGlobalParametersService.needCheckIn()).isEqualTo(NEED_CHECK_IN);
-    }
-
-    @Test
     public void getRegisteredId_shouldReturnExpectedResult() throws RemoteException {
         assertThat(mIGlobalParametersService.getRegisteredDeviceId()).isNull();
 
@@ -85,15 +62,6 @@
     }
 
     @Test
-    public void getEnrollmentToken_shouldReturnExpectedResult() throws RemoteException {
-        assertThat(mIGlobalParametersService.getEnrollmentToken()).isNull();
-
-        mIGlobalParametersService.setEnrollmentToken(ENROLLMENT_TOKEN);
-
-        assertThat(mIGlobalParametersService.getEnrollmentToken()).isEqualTo(ENROLLMENT_TOKEN);
-    }
-
-    @Test
     public void getLastReceivedProvisionState_shouldReturnExpectedResult() throws RemoteException {
         assertThat(mIGlobalParametersService.getLastReceivedProvisionState()).isNotEqualTo(
                 LAST_RECEIVED_PROVISION_STATE);
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/GlobalParametersTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/GlobalParametersTest.java
index 37ade8d..a7b374b 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/GlobalParametersTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/GlobalParametersTest.java
@@ -16,6 +16,8 @@
 
 package com.android.devicelockcontroller.storage;
 
+import static com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState.FINALIZED;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
@@ -27,9 +29,6 @@
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 
-import java.util.ArrayList;
-import java.util.List;
-
 @RunWith(RobolectricTestRunner.class)
 public final class GlobalParametersTest extends AbstractGlobalParametersTestBase {
     private Context mContext;
@@ -40,35 +39,6 @@
     }
 
     @Test
-    public void getLockTaskAllowlist_shouldReturnExpectedAllowlist() {
-        assertThat(GlobalParameters.getLockTaskAllowlist(mContext)).isEmpty();
-        final ArrayList<String> expectedAllowlist = new ArrayList<>();
-        expectedAllowlist.add(ALLOWLIST_PACKAGE_0);
-        expectedAllowlist.add(ALLOWLIST_PACKAGE_1);
-        GlobalParameters.setLockTaskAllowlist(mContext, expectedAllowlist);
-        final List<String> actualAllowlist = GlobalParameters.getLockTaskAllowlist(mContext);
-        assertThat(actualAllowlist).containsExactlyElementsIn(expectedAllowlist);
-    }
-
-    @Test
-    public void getKioskSigningCertificate_shouldReturnExpectedResult() {
-        assertThat(GlobalParameters.getKioskSignature(mContext)).isNull();
-
-        GlobalParameters.setKioskSignature(mContext, KIOSK_SIGNING_CERT);
-
-        assertThat(GlobalParameters.getKioskSignature(mContext)).isEqualTo(KIOSK_SIGNING_CERT);
-    }
-
-    @Test
-    public void needCheckIn_shouldReturnExpectedResult() {
-        assertThat(GlobalParameters.needCheckIn(mContext)).isNotEqualTo(NEED_CHECK_IN);
-
-        GlobalParameters.setNeedCheckIn(mContext, NEED_CHECK_IN);
-
-        assertThat(GlobalParameters.needCheckIn(mContext)).isEqualTo(NEED_CHECK_IN);
-    }
-
-    @Test
     public void getRegisteredId_shouldReturnExpectedResult() {
         assertThat(GlobalParameters.getRegisteredDeviceId(mContext)).isNull();
 
@@ -88,15 +58,6 @@
     }
 
     @Test
-    public void getEnrollmentToken_shouldReturnExpectedResult() {
-        assertThat(GlobalParameters.getEnrollmentToken(mContext)).isNull();
-
-        GlobalParameters.setEnrollmentToken(mContext, ENROLLMENT_TOKEN);
-
-        assertThat(GlobalParameters.getEnrollmentToken(mContext)).isEqualTo(ENROLLMENT_TOKEN);
-    }
-
-    @Test
     public void getLastReceivedProvisionState_shouldReturnExpectedResult() {
         assertThat(GlobalParameters.getLastReceivedProvisionState(mContext)).isNotEqualTo(
                 LAST_RECEIVED_PROVISION_STATE);
@@ -106,4 +67,13 @@
         assertThat(GlobalParameters.getLastReceivedProvisionState(mContext)).isEqualTo(
                 LAST_RECEIVED_PROVISION_STATE);
     }
+
+    @Test
+    public void getFinalizationState_shouldReturnExpectedResult() {
+        assertThat(GlobalParameters.getFinalizationState(mContext)).isNotEqualTo(FINALIZED);
+
+        GlobalParameters.setFinalizationState(mContext, FINALIZED);
+
+        assertThat(GlobalParameters.getFinalizationState(mContext)).isEqualTo(FINALIZED);
+    }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/SetupParametersServiceTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/SetupParametersServiceTest.java
index f3fbdd0..9e99265 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/SetupParametersServiceTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/SetupParametersServiceTest.java
@@ -52,7 +52,6 @@
         mISetupParametersService.createPrefs(bundle);
 
         assertThat(mISetupParametersService.getKioskPackage()).isEqualTo(KIOSK_PACKAGE);
-        assertThat(mISetupParametersService.getKioskSetupActivity()).isEqualTo(SETUP_ACTIVITY);
         assertThat(mISetupParametersService.getOutgoingCallsDisabled()).isTrue();
         assertThat(mISetupParametersService.isNotificationsInLockTaskModeEnabled()).isTrue();
 
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/SetupParametersTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/SetupParametersTest.java
index d591686..77cbd8e 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/SetupParametersTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/SetupParametersTest.java
@@ -46,7 +46,6 @@
         SetupParameters.createPrefs(mContext, bundle);
 
         assertThat(SetupParameters.getKioskPackage(mContext)).isEqualTo(KIOSK_PACKAGE);
-        assertThat(SetupParameters.getKioskSetupActivity(mContext)).isEqualTo(SETUP_ACTIVITY);
         assertThat(SetupParameters.getOutgoingCallsDisabled(mContext)).isTrue();
         assertThat(SetupParameters.isNotificationsInLockTaskModeEnabled(mContext)).isTrue();
 
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/UserParametersTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/UserParametersTest.java
index efeb094..aec56c8 100644
--- a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/UserParametersTest.java
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/storage/UserParametersTest.java
@@ -22,13 +22,14 @@
 
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
 @RunWith(RobolectricTestRunner.class)
 public final class UserParametersTest {
     private Context mContext;
@@ -40,18 +41,15 @@
         mContext = ApplicationProvider.getApplicationContext();
     }
 
-    @Test
-    public void getDeviceState_shouldReturnExpectedCurrentDeviceState() {
-        assertThat(UserParameters.getDeviceState(mContext)).isEqualTo(DeviceState.UNPROVISIONED);
-        UserParameters.setDeviceState(mContext, DeviceState.SETUP_SUCCEEDED);
-        assertThat(UserParameters.getDeviceState(mContext)).isEqualTo(DeviceState.SETUP_SUCCEEDED);
-    }
 
     @Test
-    public void getPackageOverridingHome_shouldReturnExpectedOverridingHomePackage() {
-        assertThat(UserParameters.getPackageOverridingHome(mContext)).isNull();
-        UserParameters.setPackageOverridingHome(mContext, PACKAGE_OVERRIDING_HOME);
-        assertThat(UserParameters.getPackageOverridingHome(mContext))
-                .isEqualTo(PACKAGE_OVERRIDING_HOME);
+    public void getPackageOverridingHome_shouldReturnExpectedOverridingHomePackage()
+            throws ExecutionException, InterruptedException {
+        Executors.newSingleThreadExecutor().submit(() -> {
+            assertThat(UserParameters.getPackageOverridingHome(mContext)).isNull();
+            UserParameters.setPackageOverridingHome(mContext, PACKAGE_OVERRIDING_HOME);
+            assertThat(UserParameters.getPackageOverridingHome(mContext))
+                    .isEqualTo(PACKAGE_OVERRIDING_HOME);
+        }).get();
     }
 }
diff --git a/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/util/ThreadAssertsTest.java b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/util/ThreadAssertsTest.java
new file mode 100644
index 0000000..24e6d26
--- /dev/null
+++ b/DeviceLockController/tests/robolectric/src/com/android/devicelockcontroller/util/ThreadAssertsTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2023 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 com.android.devicelockcontroller.util;
+
+import static org.junit.Assert.assertThrows;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
+@RunWith(RobolectricTestRunner.class)
+public class ThreadAssertsTest {
+    @Before
+    public void setUp() {
+        ApplicationProvider.getApplicationContext();
+    }
+
+    @Test
+    public void assertWorkerThread_workThread() throws Exception {
+        runOnWorkThread(() -> ThreadAsserts.assertWorkerThread(
+                "assertWorkerThread_workThread"));
+    }
+
+    @Test
+    public void assertWorkerThread_mainThread_shouldThrowException() {
+        assertThrows(IllegalStateException.class,
+                () -> ThreadAsserts.assertWorkerThread("assertWorkerThread_workThread"));
+    }
+
+    @Test
+    public void assertMainThread_mainThread() {
+        ThreadAsserts.assertMainThread("assertMainThread_mainThread");
+    }
+
+    @Test
+    public void assertMainThread_workThread_shouldThrowException() throws Exception {
+        runOnWorkThread(() -> assertThrows(IllegalStateException.class,
+                () -> ThreadAsserts.assertMainThread("assertWorkerThread_workThread")));
+    }
+
+    private static void runOnWorkThread(Runnable task)
+            throws InterruptedException, ExecutionException {
+        Executors.newSingleThreadExecutor().submit(task).get();
+    }
+}
diff --git a/OWNERS b/OWNERS
index 07f6ba3..0fcc31e 100644
--- a/OWNERS
+++ b/OWNERS
@@ -3,3 +3,4 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
diff --git a/apex/Android.bp b/apex/Android.bp
index 6827bf7..48251a4 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -96,7 +96,10 @@
 }
 
 sdk {
-    name: "devicelock-sdk",
-    bootclasspath_fragments: ["com.android.devicelock-bootclasspath-fragment"],
-    systemserverclasspath_fragments: ["com.android.devicelock-systemserverclasspath-fragment"],
+    name: "devicelock-module-sdk",
+    apexes: [
+        // Adds exportable dependencies of the APEX to the sdk,
+        // e.g. *classpath_fragments.
+        "com.android.devicelock",
+    ],
 }
diff --git a/apex/AndroidManifest.xml b/apex/AndroidManifest.xml
index b2446e2..9261256 100644
--- a/apex/AndroidManifest.xml
+++ b/apex/AndroidManifest.xml
@@ -26,9 +26,5 @@
 
     <!-- APEX does not have classes.dex -->
     <application android:hasCode="false">
-        <apex-system-service
-            android:name="com.android.server.devicelock.DeviceLockService"
-            android:path="/apex/com.android.devicelock/javalib/service-devicelock.jar"
-        />
     </application>
 </manifest>
diff --git a/framework/Android.bp b/framework/Android.bp
index d73a44a..30cc6e4 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -40,7 +40,7 @@
 
 java_sdk_library {
     name: "framework-devicelock",
-    srcs: [":framework-devicelock-sources" ],
+    srcs: [":framework-devicelock-sources"],
     defaults: ["framework-module-defaults"],
     permitted_packages: ["android.devicelock"],
     impl_library_visibility: ["//packages/modules/DeviceLock:__subpackages__"],
@@ -48,5 +48,6 @@
         "com.android.devicelock",
     ],
     sdk_version: "module_current",
+    min_sdk_version: "UpsideDownCake",
     libs: ["framework-annotations-lib"],
 }
diff --git a/framework/java/android/devicelock/DeviceLockManager.java b/framework/java/android/devicelock/DeviceLockManager.java
index 9013032..0d6aa6d 100644
--- a/framework/java/android/devicelock/DeviceLockManager.java
+++ b/framework/java/android/devicelock/DeviceLockManager.java
@@ -29,7 +29,6 @@
 import android.os.OutcomeReceiver;
 import android.os.RemoteException;
 import android.text.TextUtils;
-import android.util.Log;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -69,52 +68,6 @@
      */
     public static final int DEVICE_LOCK_ROLE_FINANCING = 0;
 
-    private static SecurityException getSecurityException() {
-        return new SecurityException("Need MANAGE_DEVICE_LOCK_STATE permission");
-    }
-
-    private static Exception getUnknwnException() {
-        return new Exception("Unknown error");
-    }
-
-    private static final Map<Class, Map<Integer, Exception>> ERROR_MAP = Map.of(
-            ILockUnlockDeviceCallback.class, Map.of(
-                    ILockUnlockDeviceCallback.ERROR_UNKNOWN, getUnknwnException(),
-                    ILockUnlockDeviceCallback.ERROR_SECURITY, getSecurityException()
-            ),
-            IIsDeviceLockedCallback.class, Map.of(
-                    IIsDeviceLockedCallback.ERROR_UNKNOWN, getUnknwnException(),
-                    IIsDeviceLockedCallback.ERROR_SECURITY, getSecurityException()
-            ),
-            IGetDeviceIdCallback.class, Map.of(
-                    IGetDeviceIdCallback.ERROR_UNKNOWN, getUnknwnException(),
-                    IGetDeviceIdCallback.ERROR_SECURITY, getSecurityException(),
-                    IGetDeviceIdCallback.ERROR_INVALID_DEVICE_ID_TYPE_BITMAP,
-                        new Exception("Invalid device type"),
-                    IGetDeviceIdCallback.ERROR_CANNOT_GET_DEVICE_ID,
-                        new Exception("Unable to get device id")
-            ),
-            IGetKioskAppsCallback.class, Map.of(
-                    IGetKioskAppsCallback.ERROR_UNKNOWN, getUnknwnException()
-            )
-    );
-
-    private static Exception getException(Class clazz, int error) {
-        final Map<Integer, Exception> map = ERROR_MAP.get(clazz);
-        if (map == null) {
-            Log.e(TAG, "Cannot find error map for: " + clazz.getSimpleName());
-
-            return new Exception();
-        }
-
-        final Exception ex = map.get(error);
-        if (ex == null) {
-            return new Exception();
-        }
-
-        return ex;
-    }
-
     /**
      * @hide
      */
@@ -155,9 +108,8 @@
                         }
 
                         @Override
-                        public void onError(int error) {
-                            callback.onError(getException(ILockUnlockDeviceCallback.class,
-                                    error));
+                        public void onError(ParcelableException parcelableException) {
+                            callback.onError(parcelableException.getException());
                         }
                     });
         } catch (RemoteException e) {
@@ -186,9 +138,8 @@
                         }
 
                         @Override
-                        public void onError(int error) {
-                            callback.onError(getException(ILockUnlockDeviceCallback.class,
-                                    error));
+                        public void onError(ParcelableException parcelableException) {
+                            callback.onError(parcelableException.getException());
                         }
                     });
         } catch (RemoteException e) {
@@ -217,10 +168,9 @@
                         }
 
                         @Override
-                        public void onError(int error) {
+                        public void onError(ParcelableException parcelableException) {
                             executor.execute(() ->
-                                    callback.onError(getException(IIsDeviceLockedCallback.class,
-                                            error)));
+                                    callback.onError(parcelableException.getException()));
                         }
                     });
         } catch (RemoteException e) {
@@ -257,9 +207,8 @@
                         }
 
                         @Override
-                        public void onError(int error) {
-                            callback.onError(getException(IGetDeviceIdCallback.class,
-                                    error));
+                        public void onError(ParcelableException parcelableException) {
+                            callback.onError(parcelableException.getException());
                         }
                     }
             );
@@ -293,9 +242,8 @@
                         }
 
                         @Override
-                        public void onError(int error) {
-                            callback.onError(getException(IGetKioskAppsCallback.class,
-                                    error));
+                        public void onError(ParcelableException parcelableException) {
+                            callback.onError(parcelableException.getException());
                         }
                     }
             );
diff --git a/framework/java/android/devicelock/IDeviceLockService.aidl b/framework/java/android/devicelock/IDeviceLockService.aidl
index 95667b0..0e19fb9 100644
--- a/framework/java/android/devicelock/IDeviceLockService.aidl
+++ b/framework/java/android/devicelock/IDeviceLockService.aidl
@@ -75,15 +75,51 @@
     void removeFinancedDeviceKioskRole(in String packageName, in RemoteCallback remoteCallback);
 
     /**
-     * Set the Device Lock Controller exempt from starting an activity from the background
-     * for the calling user.
+     * Set the exempt from activity background restrction app op mode for the calling uid.
      */
-    void setExemptFromActivityBackgroundStartRestriction(in boolean exempt,
-        in RemoteCallback remoteCallback);
+    void setCallerExemptFromActivityBgStartRestrictionState(in boolean exempt,
+     in RemoteCallback remoteCallback);
 
     /**
-     * Exampt kiosk app from hibernation.
+     * Set whether the caller should be allowed to send undismissible notifications.
      */
-    void setExemptFromHibernation(in String packageName, in boolean exempt,
-        in RemoteCallback remoteCallback);
+    void setCallerAllowedToSendUndismissibleNotifications(in boolean allowed,
+     in RemoteCallback remoteCallback);
+
+    /**
+     * Set the exempt from hibernation, battery usage, data usage restrictions state for the
+     * given uid.
+     */
+    void setUidExemptFromRestrictionsState(in int uid, in boolean exempt,
+     in RemoteCallback remoteCallback);
+
+    /**
+     * Enable kiosk keepalive.
+     */
+     void enableKioskKeepalive(in String packageName, in RemoteCallback remoteCallback);
+
+    /**
+     * Disable kiosk keepalive.
+     */
+     void disableKioskKeepalive(in RemoteCallback remoteCallback);
+
+    /**
+     * Enable controller keepalive.
+     */
+     void enableControllerKeepalive(in RemoteCallback remoteCallback);
+
+    /**
+     * Disable controller keepalive.
+     */
+     void disableControllerKeepalive(in RemoteCallback remoteCallback);
+
+    /**
+     * Set device finalized.
+     */
+     void setDeviceFinalized(in boolean finalized, in RemoteCallback remoteCallback);
+
+     /**
+      * Set/clear controller POST_NOTIFICATIONS FLAG_PERMISSION_SYSTEM_FIXED flag.
+      */
+     void setPostNotificationsSystemFixed(in boolean systemFixed, in RemoteCallback remoteCallback);
 }
diff --git a/framework/java/android/devicelock/IGetDeviceIdCallback.aidl b/framework/java/android/devicelock/IGetDeviceIdCallback.aidl
index ecfee98..718ea49 100644
--- a/framework/java/android/devicelock/IGetDeviceIdCallback.aidl
+++ b/framework/java/android/devicelock/IGetDeviceIdCallback.aidl
@@ -16,6 +16,8 @@
 
 package android.devicelock;
 
+import android.devicelock.ParcelableException;
+
 /**
   * Callback for a getDeviceId() request.
   * {@hide}
@@ -23,10 +25,5 @@
 oneway interface IGetDeviceIdCallback {
     void onDeviceIdReceived(int type, in String id);
 
-    const int ERROR_UNKNOWN = 0;
-    const int ERROR_SECURITY = 1;
-    const int ERROR_INVALID_DEVICE_ID_TYPE_BITMAP = 2;
-    const int ERROR_CANNOT_GET_DEVICE_ID = 3;
-
-    void onError(int error);
+    void onError(in ParcelableException parcelableException);
 }
diff --git a/framework/java/android/devicelock/IGetKioskAppsCallback.aidl b/framework/java/android/devicelock/IGetKioskAppsCallback.aidl
index 7f7ed8c..124ad23 100644
--- a/framework/java/android/devicelock/IGetKioskAppsCallback.aidl
+++ b/framework/java/android/devicelock/IGetKioskAppsCallback.aidl
@@ -16,6 +16,8 @@
 
 package android.devicelock;
 
+import android.devicelock.ParcelableException;
+
 /**
   * Callback for a getActiveKioskAppPackagesAndRoles() request.
   * {@hide}
@@ -23,7 +25,5 @@
 oneway interface IGetKioskAppsCallback {
     void onKioskAppsReceived(in Map roleToPackage);
 
-    const int ERROR_UNKNOWN = 0;
-
-    void onError(int error);
+    void onError(in ParcelableException parcelableException);
 }
diff --git a/framework/java/android/devicelock/IIsDeviceLockedCallback.aidl b/framework/java/android/devicelock/IIsDeviceLockedCallback.aidl
index abb1462..4ace8e0 100644
--- a/framework/java/android/devicelock/IIsDeviceLockedCallback.aidl
+++ b/framework/java/android/devicelock/IIsDeviceLockedCallback.aidl
@@ -16,16 +16,15 @@
 
 package android.devicelock;
 
+import android.devicelock.ParcelableException;
+
 /**
   * Callback for a isDeviceLocked() request.
   * {@hide}
   */
 oneway interface IIsDeviceLockedCallback {
 
-    void onIsDeviceLocked(boolean locked);
+    void onIsDeviceLocked(in boolean locked);
 
-    const int ERROR_UNKNOWN = 0;
-    const int ERROR_SECURITY = 1;
-
-    void onError(int error);
+    void onError(in ParcelableException parcelableException);
 }
diff --git a/framework/java/android/devicelock/ILockUnlockDeviceCallback.aidl b/framework/java/android/devicelock/ILockUnlockDeviceCallback.aidl
index 7e65ee7..6664ecb 100644
--- a/framework/java/android/devicelock/ILockUnlockDeviceCallback.aidl
+++ b/framework/java/android/devicelock/ILockUnlockDeviceCallback.aidl
@@ -16,6 +16,8 @@
 
 package android.devicelock;
 
+import android.devicelock.ParcelableException;
+
 /**
   * Callback for a lockDevice()/unlockDevice() request.
   * {@hide}
@@ -23,8 +25,5 @@
 oneway interface ILockUnlockDeviceCallback {
     void onDeviceLockedUnlocked();
 
-    const int ERROR_UNKNOWN = 0;
-    const int ERROR_SECURITY = 1;
-
-    void onError(int error);
+    void onError(in ParcelableException parcelableException);
 }
diff --git a/framework/java/android/devicelock/ParcelableException.aidl b/framework/java/android/devicelock/ParcelableException.aidl
new file mode 100644
index 0000000..c6fc752
--- /dev/null
+++ b/framework/java/android/devicelock/ParcelableException.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.devicelock;
+
+/** {@hide} */
+parcelable ParcelableException;
diff --git a/framework/java/android/devicelock/ParcelableException.java b/framework/java/android/devicelock/ParcelableException.java
new file mode 100644
index 0000000..750138c
--- /dev/null
+++ b/framework/java/android/devicelock/ParcelableException.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.devicelock;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Wrapper class for transporting exceptions, similar to android.os.ParcelableException that is
+ * hidden and cannot be used by device lock.
+ *
+ * @hide
+ */
+public final class ParcelableException extends Exception implements Parcelable {
+    public ParcelableException(Exception t) {
+        super(t);
+    }
+
+    public ParcelableException(String message) {
+        super(message);
+    }
+
+    private static Exception readFromParcel(Parcel in) {
+        final String name = in.readString();
+        final String msg = in.readString();
+        try {
+            final Class<?> clazz = Class.forName(name, true, Parcelable.class.getClassLoader());
+            if (Exception.class.isAssignableFrom(clazz)) {
+                return (Exception) clazz.getConstructor(String.class).newInstance(msg);
+            }
+        } catch (ReflectiveOperationException e) {
+            // return the below exception in this case.
+        }
+        return new Exception(name + ": " + msg);
+    }
+
+    private static void writeToParcel(Parcel out, Throwable t) {
+        out.writeString(t.getClass().getName());
+        out.writeString(t.getMessage());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        writeToParcel(dest, getCause());
+    }
+
+    /**
+     * Required per Parcelable documentation.
+     */
+    public static final Creator<ParcelableException> CREATOR = new Creator<>() {
+        @Override
+        public ParcelableException createFromParcel(Parcel source) {
+            return new ParcelableException(readFromParcel(source));
+        }
+
+        @Override
+        public ParcelableException[] newArray(int size) {
+            return new ParcelableException[size];
+        }
+    };
+
+    /**
+     * Get the encapsulated exception.
+     */
+    public Exception getException() {
+        return (Exception) getCause();
+    }
+}
diff --git a/permissions/com.android.devicelockcontroller.xml b/permissions/com.android.devicelockcontroller.xml
index d4df1eb..1dbefe5 100644
--- a/permissions/com.android.devicelockcontroller.xml
+++ b/permissions/com.android.devicelockcontroller.xml
@@ -20,9 +20,7 @@
     <!-- Permission allowlist for device lock controller -->
     <privapp-permissions package="com.android.devicelockcontroller">
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
-        <permission name="android.permission.INSTALL_PACKAGES"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.MASTER_CLEAR"/>
-        <permission name="com.android.permission.INSTALL_EXISTING_PACKAGES"/>
     </privapp-permissions>
 </permissions>
diff --git a/service/Android.bp b/service/Android.bp
index ff7eb5c..93a2705 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -38,6 +38,7 @@
     ],
     static_libs: [
         "devicelockcontroller-interface",
+        "devicelockcontroller-thread-asserts-lib",
     ],
     apex_available: [
         "com.android.devicelock",
diff --git a/service/java/com/android/server/devicelock/DeviceLockControllerConnector.java b/service/java/com/android/server/devicelock/DeviceLockControllerConnector.java
index 4c282e1..8de87fe 100644
--- a/service/java/com/android/server/devicelock/DeviceLockControllerConnector.java
+++ b/service/java/com/android/server/devicelock/DeviceLockControllerConnector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -16,371 +16,60 @@
 
 package com.android.server.devicelock;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
 import android.os.OutcomeReceiver;
-import android.os.RemoteCallback;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.ArraySet;
-import android.util.Slog;
-
-import com.android.devicelockcontroller.IDeviceLockControllerService;
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeoutException;
 
 /**
- * This class is used to establish a connection (bind) to the Device Lock Controller APK.
+ * Connector class that acts as the interface between the system service and the DLC service.
  */
-final class DeviceLockControllerConnector {
-    private final Object mLock = new Object();
-
-    private static final String TAG = "DeviceLockControllerConnector";
-
-    @GuardedBy("mLock")
-    private IDeviceLockControllerService mDeviceLockControllerService;
-
-    @GuardedBy("mLock")
-    private ServiceConnection mServiceConnection;
-
-    private final Context mContext;
-    private final ComponentName mComponentName;
-    private final Handler mHandler;
-
-    private static final UserHandle USER_HANDLE_SYSTEM = UserHandle.of(0);
-
-    private final ExecutorService mExecutorService = Executors.newCachedThreadPool();
-
-    private static final long INACTIVITY_TIMEOUT_MILLIS = 1_000 * 60 * 1; // One minute.
-    private static final long API_CALL_TIMEOUT_MILLIS = 1_000 * 10;       // Ten seconds.
-
-    // The following hash set is used for API timeout detection. We do oneway calls into the
-    // device lock controller service, and the service is supposed to reply with another one way
-    // call. Once we call into the device lock controller service, we add the callback to this
-    // hash map and remove it once the remote invocation from the controller is received by
-    // the system service or a timeout occurred. In this way, we guarantee that the callback
-    // will be always invoked (and it's only invoked once).
-    @GuardedBy("mPendingCallbacks")
-    private final ArraySet<OutcomeReceiver> mPendingCallbacks = new ArraySet<>();
-
-    private final Runnable mUnbindDeviceLockControllerService = () -> {
-        Slog.i(TAG, "Unbinding DeviceLockControllerService");
-        unbind();
-    };
-
-    private <Result> void callControllerApi(Callable<Void> body,
-            OutcomeReceiver<Result, Exception> callback) {
-        Runnable r = () -> {
-            Exception exception = null;
-
-            mHandler.removeCallbacks(mUnbindDeviceLockControllerService);
-            mHandler.postDelayed(mUnbindDeviceLockControllerService, INACTIVITY_TIMEOUT_MILLIS);
-
-            synchronized (mLock) {
-                // First, bind if not already bound.
-                if (bindLocked()) {
-                    while (mDeviceLockControllerService == null) {
-                        try {
-                            mLock.wait();
-                        } catch (InterruptedException e) {
-                            // Nothing to do, wait again if mService is still null.
-                        }
-                    }
-
-                    try {
-                        synchronized (mPendingCallbacks) {
-                            mPendingCallbacks.add(callback);
-                        }
-                        body.call();
-                        // Start timeout for this call.
-                        mHandler.postDelayed(() -> {
-                            boolean removed;
-                            synchronized (mPendingCallbacks) {
-                                removed = mPendingCallbacks.remove(callback);
-                            }
-                            if (removed) {
-                                // We hit a timeout, execute the callback.
-                                mHandler.post(() -> callback.onError(new TimeoutException()));
-                            }
-                        }, API_CALL_TIMEOUT_MILLIS);
-                    } catch (Exception e) {
-                        synchronized (mPendingCallbacks) {
-                            mPendingCallbacks.remove(callback);
-                        }
-                        exception = e;
-                    }
-                } else {
-                    exception = new Exception("Failed to bind to service");
-                }
-            }
-
-            if (exception != null) {
-                final Exception finalException = exception;
-                mHandler.post(() -> callback.onError(finalException));
-                return;
-            }
-        };
-
-        mExecutorService.execute(r);
-    }
-
-    private boolean hasApiCallTimedOut(OutcomeReceiver callback) {
-        boolean removed;
-        synchronized (mPendingCallbacks) {
-            removed = mPendingCallbacks.remove(callback);
-        }
-        // if this callback was already been removed by the timeout and somehow this callback
-        // arrived late. We already replied with a timeout error, ignore the result.
-
-        return !removed;
-    }
-
-    private RemoteCallback.OnResultListener checkTimeout(OutcomeReceiver callback,
-            RemoteCallback.OnResultListener listener) {
-        return (@Nullable Bundle bundle) -> {
-            if (hasApiCallTimedOut(callback)) {
-                return;
-            }
-            listener.onResult(bundle);
-        };
-    }
-
-    private class DeviceLockControllerServiceConnection implements ServiceConnection {
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            synchronized (mLock) {
-                if (mServiceConnection == null) {
-                    Slog.w(TAG, "Connected: " + mComponentName.flattenToShortString()
-                            + " but not bound, ignore.");
-                    return;
-                }
-
-                Slog.i(TAG, "Connected to " + mComponentName.flattenToShortString());
-
-                mDeviceLockControllerService =
-                        IDeviceLockControllerService.Stub.asInterface(service);
-
-                mLock.notifyAll();
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            Slog.i(TAG, "Disconnected from " + mComponentName.flattenToShortString());
-            // Service has crashed or been killed. The binding is still valid, however
-            // we unbind here so we can bind again an restart the service when needed.
-            // Otherwise, Activity Manager would restart it after some back-off, and trying
-            // to use the service in this timeframe would result in a DeadObjectException.
-            unbind();
-        }
-
-        @Override
-        public void onBindingDied(ComponentName name) {
-            // Activity Manager gave up.
-            synchronized (mLock) {
-                if (mServiceConnection == null) {
-                    // Callback came in late
-                    Slog.w(TAG, "Binding died: " + mComponentName.flattenToShortString()
-                            + " but not bound, ignore.");
-                    return;
-                }
-
-                Slog.w(TAG, "Binding died " + mComponentName.flattenToShortString());
-
-                // We just unbind here; any API calls would cause the binding to be recreated
-                // when needed.
-                unbindLocked();
-            }
-        }
-    };
+public interface DeviceLockControllerConnector {
 
     /**
-     * Create a new connector to the Device Lock Controller service.
-     *
-     * @param context the context for this call.
-     * @param componentName Device Lock Controller service component name.
+     * Unbinds the Device Lock Controller service.
      */
-    DeviceLockControllerConnector(@NonNull Context context,
-            @NonNull ComponentName componentName) {
-        mContext = context;
-        mComponentName = componentName;
-
-        HandlerThread handlerThread =
-                new HandlerThread("DeviceLockControllerConnectorHandlerThread");
-        handlerThread.start();
-        mHandler = new Handler(handlerThread.getLooper());
-    }
-
-    @GuardedBy("mLock")
-    private boolean bindLocked() {
-        if (mServiceConnection != null) {
-            // Already bound, ignore and return success.
-            return true;
-        }
-
-        mServiceConnection = new DeviceLockControllerServiceConnection();
-
-        final Intent service = new Intent().setComponent(mComponentName);
-        final boolean bound = mContext.bindServiceAsUser(service, mServiceConnection,
-                Context.BIND_AUTO_CREATE, USER_HANDLE_SYSTEM);
-
-        if (bound) {
-            Slog.i(TAG, "Binding " + mComponentName.flattenToShortString());
-        } else {
-            // As per bindService() documentation, we still need to call unbindService()
-            // if binding fails.
-            mContext.unbindService(mServiceConnection);
-            mServiceConnection = null;
-            Slog.e(TAG, "Binding " + mComponentName.flattenToShortString() + " failed.");
-        }
-
-        return bound;
-    }
-
-    @GuardedBy("mLock")
-    private void unbindLocked() {
-        if (mServiceConnection == null) {
-            return;
-        }
-
-        Slog.i(TAG, "Unbinding " + mComponentName.flattenToShortString());
-
-        mContext.unbindService(mServiceConnection);
-
-        mDeviceLockControllerService = null;
-        mServiceConnection = null;
-    }
+    void unbind();
 
     /**
-     * Bind to the Device Lock Controller service.
+     * Locks the device.
      */
-    public boolean bind() {
-        synchronized (mLock) {
-            return bindLocked();
-        }
-    }
+    void lockDevice(OutcomeReceiver<Void, Exception> callback);
 
     /**
-     * Unbind the Device Lock Controller service.
+     * Unlocks the device.
      */
-    public void unbind() {
-        synchronized (mLock) {
-            unbindLocked();
-        }
-    }
+    void unlockDevice(OutcomeReceiver<Void, Exception> callback);
 
-    public void lockDevice(OutcomeReceiver<Void, Exception> callback) {
-        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
-            final boolean success =
-                    result.getBoolean(IDeviceLockControllerService.KEY_LOCK_DEVICE_RESULT);
-            if (success) {
-                mHandler.post(() -> callback.onResult(null));
-            } else {
-                mHandler.post(() -> callback.onError(new Exception("Failed to lock device")));
-            }
-        }));
+    /**
+     * Returns whether the device is currently locked.
+     */
+    void isDeviceLocked(OutcomeReceiver<Boolean, Exception> callback);
 
-        callControllerApi(new Callable<Void>() {
-            @Override
-            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
-            public Void call() throws Exception {
-                mDeviceLockControllerService.lockDevice(remoteCallback);
-                return null;
-            }
-        } , callback);
+    /**
+     * Gets the device id.
+     */
+    void getDeviceId(OutcomeReceiver<String, Exception> callback);
 
-    }
+    /**
+     * Clears the device restrictions
+     */
+    void clearDeviceRestrictions(OutcomeReceiver<Void, Exception> callback);
 
-    public void unlockDevice(OutcomeReceiver<Void, Exception> callback) {
-        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
-            final boolean success =
-                    result.getBoolean(IDeviceLockControllerService.KEY_UNLOCK_DEVICE_RESULT);
-            if (success) {
-                mHandler.post(() -> callback.onResult(null));
-            } else {
-                mHandler.post(() -> callback.onError(new Exception("Failed to unlock device")));
-            }
-        }));
+    /**
+     * Called when the user has switched.
+     */
+    void onUserSwitching(OutcomeReceiver<Void, Exception> callback);
 
-        callControllerApi(new Callable<Void>() {
-            @Override
-            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
-            public Void call() throws Exception {
-                mDeviceLockControllerService.unlockDevice(remoteCallback);
-                return null;
-            }
-        }, callback);
-    }
+    /**
+     * Called when the user is unlocked.
+     */
+    void onUserUnlocked(OutcomeReceiver<Void, Exception> callback);
 
-    public void isDeviceLocked(OutcomeReceiver<Boolean, Exception> callback) {
-        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
-            final boolean isLocked =
-                    result.getBoolean(IDeviceLockControllerService.KEY_IS_DEVICE_LOCKED_RESULT);
-            mHandler.post(() -> callback.onResult(isLocked));
-        }));
+    /**
+     * Called when the user has completed setup.
+     */
+    void onUserSetupCompleted(OutcomeReceiver<Void, Exception> callback);
 
-        callControllerApi(new Callable<Void>() {
-            @Override
-            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
-            public Void call() throws Exception {
-                mDeviceLockControllerService.isDeviceLocked(remoteCallback);
-                return null;
-            }
-        }, callback);
-    }
-
-    public void getDeviceId(OutcomeReceiver<String, Exception> callback) {
-        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
-            final String deviceId =
-                    result.getString(IDeviceLockControllerService.KEY_HARDWARE_ID_RESULT);
-            if (TextUtils.isEmpty(deviceId)) { // If the deviceId is null or empty
-                mHandler.post(() -> callback.onError(new IllegalStateException(
-                        "No registered Device ID found")));
-            } else {
-                mHandler.post(() -> callback.onResult(deviceId));
-            }
-        }));
-
-        callControllerApi(new Callable<Void>() {
-            @Override
-            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
-            public Void call() throws Exception {
-                mDeviceLockControllerService.getDeviceIdentifier(remoteCallback);
-                return null;
-            }
-        }, callback);
-    }
-
-    public void clearDeviceRestrictions(OutcomeReceiver<Void, Exception> callback) {
-        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
-            final boolean success =
-                    result.getBoolean(IDeviceLockControllerService.KEY_CLEAR_DEVICE_RESULT);
-            if (success) {
-                mHandler.post(() -> callback.onResult(null));
-            } else {
-                mHandler.post(() -> callback.onError(new Exception("Failed to clear device")));
-            }
-        }));
-
-        callControllerApi(new Callable<Void>() {
-            @Override
-            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
-            public Void call() throws Exception {
-                mDeviceLockControllerService.clearDeviceRestrictions(remoteCallback);
-                return null;
-            }
-        }, callback);
-    }
+    /**
+     * Called when the controller or kiosk app has crashed.
+     */
+    void onAppCrashed(boolean isKiosk, OutcomeReceiver<Void, Exception> callback);
 }
diff --git a/service/java/com/android/server/devicelock/DeviceLockControllerConnectorImpl.java b/service/java/com/android/server/devicelock/DeviceLockControllerConnectorImpl.java
new file mode 100644
index 0000000..4e7dfe6
--- /dev/null
+++ b/service/java/com/android/server/devicelock/DeviceLockControllerConnectorImpl.java
@@ -0,0 +1,484 @@
+/*
+ * 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 com.android.server.devicelock;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.devicelock.ParcelableException;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.OutcomeReceiver;
+import android.os.RemoteCallback;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.devicelockcontroller.IDeviceLockControllerService;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * This class is used to establish a connection (bind) to the Device Lock Controller APK.
+ */
+final class DeviceLockControllerConnectorImpl implements DeviceLockControllerConnector {
+    private final Object mLock = new Object();
+
+    private static final String TAG = "DeviceLockControllerConnectorImpl";
+
+    @GuardedBy("mLock")
+    private IDeviceLockControllerService mDeviceLockControllerService;
+
+    @GuardedBy("mLock")
+    private ServiceConnection mServiceConnection;
+
+    private final Context mContext;
+    private final ComponentName mComponentName;
+    private final UserHandle mUserHandle;
+    private final Handler mHandler;
+
+    private final ExecutorService mExecutorService = Executors.newCachedThreadPool();
+
+    private static final long INACTIVITY_TIMEOUT_MILLIS = 1_000 * 60 * 1; // One minute.
+    private static final long API_CALL_TIMEOUT_MILLIS = 1_000 * 10;       // Ten seconds.
+
+    // The following hash set is used for API timeout detection. We do oneway calls into the
+    // device lock controller service, and the service is supposed to reply with another one way
+    // call. Once we call into the device lock controller service, we add the callback to this
+    // hash map and remove it once the remote invocation from the controller is received by
+    // the system service or a timeout occurred. In this way, we guarantee that the callback
+    // will be always invoked (and it's only invoked once).
+    @GuardedBy("mPendingCallbacks")
+    private final ArraySet<OutcomeReceiver> mPendingCallbacks = new ArraySet<>();
+
+    private final Runnable mUnbindDeviceLockControllerService = () -> {
+        Slog.i(TAG, "Unbinding DeviceLockControllerService");
+        unbind();
+    };
+
+    private <Result> void callControllerApi(Callable<Void> body,
+            OutcomeReceiver<Result, Exception> callback) {
+        Runnable r = () -> {
+            Exception exception = null;
+
+            mHandler.removeCallbacks(mUnbindDeviceLockControllerService);
+            mHandler.postDelayed(mUnbindDeviceLockControllerService, INACTIVITY_TIMEOUT_MILLIS);
+
+            synchronized (mLock) {
+                // First, bind if not already bound.
+                if (bindLocked()) {
+                    while (mDeviceLockControllerService == null) {
+                        try {
+                            mLock.wait();
+                        } catch (InterruptedException e) {
+                            // Nothing to do, wait again if mService is still null.
+                        }
+                    }
+
+                    try {
+                        synchronized (mPendingCallbacks) {
+                            mPendingCallbacks.add(callback);
+                        }
+                        body.call();
+                        // Start timeout for this call.
+                        mHandler.postDelayed(() -> {
+                            boolean removed;
+                            synchronized (mPendingCallbacks) {
+                                removed = mPendingCallbacks.remove(callback);
+                            }
+                            if (removed) {
+                                // We hit a timeout, execute the callback.
+                                mHandler.post(() -> callback.onError(new TimeoutException()));
+                            }
+                        }, API_CALL_TIMEOUT_MILLIS);
+                    } catch (Exception e) {
+                        synchronized (mPendingCallbacks) {
+                            mPendingCallbacks.remove(callback);
+                        }
+                        exception = e;
+                    }
+                } else {
+                    exception = new Exception("Failed to bind to service");
+                }
+            }
+
+            if (exception != null) {
+                final Exception finalException = exception;
+                mHandler.post(() -> callback.onError(finalException));
+                return;
+            }
+        };
+
+        mExecutorService.execute(r);
+    }
+
+    private boolean hasApiCallTimedOut(OutcomeReceiver callback) {
+        boolean removed;
+        synchronized (mPendingCallbacks) {
+            removed = mPendingCallbacks.remove(callback);
+        }
+        // if this callback was already been removed by the timeout and somehow this callback
+        // arrived late. We already replied with a timeout error, ignore the result.
+
+        return !removed;
+    }
+
+    private RemoteCallback.OnResultListener checkTimeout(OutcomeReceiver callback,
+            RemoteCallback.OnResultListener listener) {
+        return (@Nullable Bundle bundle) -> {
+            if (hasApiCallTimedOut(callback)) {
+                return;
+            }
+            listener.onResult(bundle);
+        };
+    }
+
+    private class DeviceLockControllerServiceConnection implements ServiceConnection {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            synchronized (mLock) {
+                if (mServiceConnection == null) {
+                    Slog.w(TAG, "Connected: " + mComponentName.flattenToShortString()
+                            + " but not bound, ignore.");
+                    return;
+                }
+
+                Slog.i(TAG, "Connected to " + mComponentName.flattenToShortString());
+
+                mDeviceLockControllerService =
+                        IDeviceLockControllerService.Stub.asInterface(service);
+
+                mLock.notifyAll();
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            Slog.i(TAG, "Disconnected from " + mComponentName.flattenToShortString());
+            // Service has crashed or been killed. The binding is still valid, however
+            // we unbind here so we can bind again an restart the service when needed.
+            // Otherwise, Activity Manager would restart it after some back-off, and trying
+            // to use the service in this timeframe would result in a DeadObjectException.
+            unbind();
+        }
+
+        @Override
+        public void onBindingDied(ComponentName name) {
+            // Activity Manager gave up.
+            synchronized (mLock) {
+                if (mServiceConnection == null) {
+                    // Callback came in late
+                    Slog.w(TAG, "Binding died: " + mComponentName.flattenToShortString()
+                            + " but not bound, ignore.");
+                    return;
+                }
+
+                Slog.w(TAG, "Binding died " + mComponentName.flattenToShortString());
+
+                // We just unbind here; any API calls would cause the binding to be recreated
+                // when needed.
+                unbindLocked();
+            }
+        }
+    }
+
+    /**
+     * Create a new connector to the Device Lock Controller service.
+     *
+     * @param context       the context for this call.
+     * @param componentName Device Lock Controller service component name.
+     */
+    DeviceLockControllerConnectorImpl(@NonNull Context context,
+            @NonNull ComponentName componentName, @NonNull UserHandle userHandle) {
+        mContext = context;
+        mComponentName = componentName;
+        mUserHandle = userHandle;
+
+        HandlerThread handlerThread =
+                new HandlerThread("DeviceLockControllerConnectorHandlerThread");
+        handlerThread.start();
+        mHandler = new Handler(handlerThread.getLooper());
+    }
+
+    @GuardedBy("mLock")
+    private boolean bindLocked() {
+        if (mServiceConnection != null) {
+            // Already bound, ignore and return success.
+            return true;
+        }
+
+        mServiceConnection = new DeviceLockControllerServiceConnection();
+
+        final Intent service = new Intent().setComponent(mComponentName);
+        final boolean bound = mContext.bindServiceAsUser(service, mServiceConnection,
+                Context.BIND_AUTO_CREATE, mUserHandle);
+
+        if (bound) {
+            Slog.i(TAG, "Binding " + mComponentName.flattenToShortString());
+        } else {
+            // As per bindService() documentation, we still need to call unbindService()
+            // if binding fails.
+            mContext.unbindService(mServiceConnection);
+            mServiceConnection = null;
+            Slog.e(TAG, "Binding " + mComponentName.flattenToShortString() + " failed.");
+        }
+
+        return bound;
+    }
+
+    @GuardedBy("mLock")
+    private void unbindLocked() {
+        if (mServiceConnection == null) {
+            return;
+        }
+
+        Slog.i(TAG, "Unbinding " + mComponentName.flattenToShortString());
+
+        mContext.unbindService(mServiceConnection);
+
+        mDeviceLockControllerService = null;
+        mServiceConnection = null;
+    }
+
+    @Override
+    public void unbind() {
+        synchronized (mLock) {
+            unbindLocked();
+        }
+    }
+
+    /**
+     * Report an exception (if any) using the callback.
+     *
+     * @param callback Callback used to report the exception.
+     * @param bundle Bundle where to look for a parcelable exception.
+     *
+     * @return true if an exception was reported.
+     */
+    private boolean maybeReportException(@NonNull OutcomeReceiver<?, Exception> callback,
+            @NonNull Bundle bundle) {
+        bundle.setClassLoader(this.getClass().getClassLoader());
+        final ParcelableException parcelableException =
+                bundle.getSerializable(IDeviceLockControllerService.KEY_PARCELABLE_EXCEPTION,
+                        ParcelableException.class);
+        if (parcelableException != null) {
+            mHandler.post(() -> callback.onError(parcelableException));
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public void lockDevice(OutcomeReceiver<Void, Exception> callback) {
+        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
+            if (maybeReportException(callback, result)) {
+                return;
+            }
+
+            mHandler.post(() -> callback.onResult(null));
+        }));
+
+        callControllerApi(new Callable<Void>() {
+            @Override
+            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
+            public Void call() throws Exception {
+                mDeviceLockControllerService.lockDevice(remoteCallback);
+                return null;
+            }
+        }, callback);
+    }
+
+    @Override
+    public void unlockDevice(OutcomeReceiver<Void, Exception> callback) {
+        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
+            if (maybeReportException(callback, result)) {
+                return;
+            }
+
+            mHandler.post(() -> callback.onResult(null));
+        }));
+
+        callControllerApi(new Callable<Void>() {
+            @Override
+            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
+            public Void call() throws Exception {
+                mDeviceLockControllerService.unlockDevice(remoteCallback);
+                return null;
+            }
+        }, callback);
+    }
+
+    @Override
+    public void isDeviceLocked(OutcomeReceiver<Boolean, Exception> callback) {
+        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
+            if (maybeReportException(callback, result)) {
+                return;
+            }
+
+            final boolean isLocked =
+                    result.getBoolean(IDeviceLockControllerService.KEY_RESULT);
+            mHandler.post(() -> callback.onResult(isLocked));
+        }));
+
+        callControllerApi(new Callable<Void>() {
+            @Override
+            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
+            public Void call() throws Exception {
+                mDeviceLockControllerService.isDeviceLocked(remoteCallback);
+                return null;
+            }
+        }, callback);
+    }
+
+    @Override
+    public void getDeviceId(OutcomeReceiver<String, Exception> callback) {
+        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
+            if (maybeReportException(callback, result)) {
+                return;
+            }
+
+            final String deviceId =
+                    result.getString(IDeviceLockControllerService.KEY_RESULT);
+            if (TextUtils.isEmpty(deviceId)) { // If the deviceId is null or empty
+                mHandler.post(() -> callback.onError(new IllegalStateException(
+                        "No registered Device ID found")));
+            } else {
+                mHandler.post(() -> callback.onResult(deviceId));
+            }
+        }));
+
+        callControllerApi(new Callable<Void>() {
+            @Override
+            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
+            public Void call() throws Exception {
+                mDeviceLockControllerService.getDeviceIdentifier(remoteCallback);
+                return null;
+            }
+        }, callback);
+    }
+
+    @Override
+    public void clearDeviceRestrictions(OutcomeReceiver<Void, Exception> callback) {
+        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
+            if (maybeReportException(callback, result)) {
+                return;
+            }
+
+            mHandler.post(() -> callback.onResult(null));
+        }));
+
+        callControllerApi(new Callable<Void>() {
+            @Override
+            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
+            public Void call() throws Exception {
+                mDeviceLockControllerService.clearDeviceRestrictions(remoteCallback);
+                return null;
+            }
+        }, callback);
+    }
+
+    @Override
+    public void onUserSwitching(OutcomeReceiver<Void, Exception> callback) {
+        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
+            if (maybeReportException(callback, result)) {
+                return;
+            }
+
+            mHandler.post(() -> callback.onResult(null));
+        }));
+
+        callControllerApi(new Callable<Void>() {
+            @Override
+            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
+            public Void call() throws Exception {
+                mDeviceLockControllerService.onUserSwitching(remoteCallback);
+                return null;
+            }
+        }, callback);
+    }
+
+    @Override
+    public void onUserUnlocked(OutcomeReceiver<Void, Exception> callback) {
+        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
+            if (maybeReportException(callback, result)) {
+                return;
+            }
+
+            mHandler.post(() -> callback.onResult(null));
+        }));
+
+        callControllerApi(new Callable<Void>() {
+            @Override
+            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
+            public Void call() throws Exception {
+                mDeviceLockControllerService.onUserUnlocked(remoteCallback);
+                return null;
+            }
+        }, callback);
+    }
+
+    @Override
+    public void onUserSetupCompleted(OutcomeReceiver<Void, Exception> callback) {
+        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
+            if (maybeReportException(callback, result)) {
+                return;
+            }
+
+            mHandler.post(() -> callback.onResult(null));
+        }));
+
+        callControllerApi(new Callable<Void>() {
+            @Override
+            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
+            public Void call() throws Exception {
+                mDeviceLockControllerService.onUserSetupCompleted(remoteCallback);
+                return null;
+            }
+        }, callback);
+    }
+
+    @Override
+    public void onAppCrashed(boolean isKiosk, OutcomeReceiver<Void, Exception> callback) {
+        RemoteCallback remoteCallback = new RemoteCallback(checkTimeout(callback, result -> {
+            if (maybeReportException(callback, result)) {
+                return;
+            }
+
+            mHandler.post(() -> callback.onResult(null));
+        }));
+
+        callControllerApi(new Callable<Void>() {
+            @Override
+            @SuppressWarnings("GuardedBy") // mLock already held in callControllerApi (error prone).
+            public Void call() throws Exception {
+                mDeviceLockControllerService.onAppCrashed(isKiosk, remoteCallback);
+                return null;
+            }
+        }, callback);
+    }
+}
diff --git a/service/java/com/android/server/devicelock/DeviceLockControllerConnectorStub.java b/service/java/com/android/server/devicelock/DeviceLockControllerConnectorStub.java
new file mode 100644
index 0000000..94c5936
--- /dev/null
+++ b/service/java/com/android/server/devicelock/DeviceLockControllerConnectorStub.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.devicelock;
+
+import android.os.OutcomeReceiver;
+
+/**
+ * Stub implementation of the connector that is used when the device has had its restrictions
+ * cleared so that we don't try to bind to a disabled package.
+ */
+public class DeviceLockControllerConnectorStub implements DeviceLockControllerConnector {
+
+    @Override
+    public void unbind() {}
+
+    @Override
+    public void lockDevice(OutcomeReceiver<Void, Exception> callback) {
+        setException(callback);
+    }
+
+    @Override
+    public void unlockDevice(OutcomeReceiver<Void, Exception> callback) {
+        setException(callback);
+    }
+
+    @Override
+    public void isDeviceLocked(OutcomeReceiver<Boolean, Exception> callback) {
+        setException(callback);
+    }
+
+    @Override
+    public void getDeviceId(OutcomeReceiver<String, Exception> callback) {
+        setException(callback);
+    }
+
+    @Override
+    public void clearDeviceRestrictions(OutcomeReceiver<Void, Exception> callback) {
+        setException(callback);
+    }
+
+    @Override
+    public void onUserSwitching(OutcomeReceiver<Void, Exception> callback) {
+        // Do not throw exception as we expect this to be called
+        callback.onResult(null);
+    }
+
+    @Override
+    public void onUserUnlocked(OutcomeReceiver<Void, Exception> callback) {
+        // Do not throw exception as we expect this to be called
+        callback.onResult(null);
+    }
+
+    @Override
+    public void onUserSetupCompleted(OutcomeReceiver<Void, Exception> callback) {
+        // Do not throw exception as we expect this to be called
+        callback.onResult(null);
+    }
+
+    @Override
+    public void onAppCrashed(boolean isKiosk, OutcomeReceiver<Void, Exception> callback) {
+        setException(callback);
+    }
+
+    private static void setException(OutcomeReceiver<?, Exception> callback) {
+        callback.onError(new IllegalStateException("Device lock controller package is disabled."));
+    }
+}
diff --git a/service/java/com/android/server/devicelock/DeviceLockControllerPackageUtils.java b/service/java/com/android/server/devicelock/DeviceLockControllerPackageUtils.java
index a2bea0b..1fc421f 100644
--- a/service/java/com/android/server/devicelock/DeviceLockControllerPackageUtils.java
+++ b/service/java/com/android/server/devicelock/DeviceLockControllerPackageUtils.java
@@ -39,7 +39,8 @@
 public final class DeviceLockControllerPackageUtils {
     private final Context mContext;
 
-    private static final String SERVICE_ACTION =
+    @VisibleForTesting
+    static final String SERVICE_ACTION =
             "android.app.action.DEVICE_LOCK_CONTROLLER_SERVICE";
 
     public DeviceLockControllerPackageUtils(Context context) {
diff --git a/service/java/com/android/server/devicelock/DeviceLockPersistentStore.java b/service/java/com/android/server/devicelock/DeviceLockPersistentStore.java
new file mode 100644
index 0000000..ef23b3c
--- /dev/null
+++ b/service/java/com/android/server/devicelock/DeviceLockPersistentStore.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.devicelock;
+
+import android.annotation.WorkerThread;
+import android.os.Environment;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.devicelockcontroller.util.ThreadAsserts;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * Class that manages persisting device state data for the system service.
+ */
+public final class DeviceLockPersistentStore {
+    private static final String TAG = DeviceLockPersistentStore.class.getSimpleName();
+    private static final String SYSTEM_DIR = "system";
+    private static final String DEVICE_LOCK_DIR = "device_lock";
+    private static final String DEVICE_STATE_FILE = "device_state.xml";
+    private static final String TAG_DEVICE_STATE = "device_state";
+    private static final String ATTR_IS_DEVICE_FINALIZED = "is_device_finalized";
+
+    private final Executor mBgExecutor = Executors.newSingleThreadExecutor();
+    private final File mFile;
+
+    DeviceLockPersistentStore() {
+        final File systemDir = new File(Environment.getDataDirectory(), SYSTEM_DIR);
+        final File deviceLockDir = new File(systemDir, DEVICE_LOCK_DIR);
+        if (!deviceLockDir.exists()) {
+            final boolean madeDirs = deviceLockDir.mkdirs();
+            if (!madeDirs) {
+                Slog.e(TAG, "Failed to make directory " + deviceLockDir.getAbsolutePath());
+            }
+        }
+        mFile = new File(deviceLockDir, DEVICE_STATE_FILE);
+    }
+
+    /**
+     * Schedule a write of the finalized state.
+     *
+     * @param finalized true if device is fully finalized
+     */
+    public void scheduleWrite(boolean finalized) {
+        mBgExecutor.execute(() -> writeState(finalized));
+    }
+
+    /**
+     * Read the finalized state from disk
+     *
+     * @param callback callback for when state is read
+     * @param callbackExecutor executor to run callback on
+     */
+    public void readFinalizedState(DeviceStateCallback callback, Executor callbackExecutor) {
+        mBgExecutor.execute(() -> {
+            final boolean isFinalized = readState();
+            callbackExecutor.execute(() -> callback.onDeviceStateRead(isFinalized));
+        });
+    }
+
+    @WorkerThread
+    private void writeState(boolean finalized) {
+        ThreadAsserts.assertWorkerThread("writeState");
+        synchronized (this) {
+            AtomicFile atomicFile = new AtomicFile(mFile);
+
+            try (FileOutputStream fileOutputStream = atomicFile.startWrite()) {
+                try {
+                    XmlSerializer serializer = Xml.newSerializer();
+                    serializer.setOutput(fileOutputStream, Xml.Encoding.UTF_8.name());
+                    serializer.startDocument(Xml.Encoding.UTF_8.name(), true /* standalone */);
+                    writeToXml(serializer, finalized);
+                    serializer.endDocument();
+                    fileOutputStream.flush();
+                    atomicFile.finishWrite(fileOutputStream);
+                } catch (IOException e) {
+                    Slog.e(TAG, "Failed to write to XML", e);
+                    atomicFile.failWrite(fileOutputStream);
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to start write", e);
+            }
+        }
+    }
+
+    private void writeToXml(XmlSerializer serializer, boolean finalized) throws IOException {
+        serializer.startTag(null /* namespace */, TAG_DEVICE_STATE);
+        serializer.attribute(null /* namespace */,
+                ATTR_IS_DEVICE_FINALIZED, Boolean.toString(finalized));
+        serializer.endTag(null /* namespace */, TAG_DEVICE_STATE);
+    }
+
+    @WorkerThread
+    private boolean readState() {
+        ThreadAsserts.assertWorkerThread("readState");
+        synchronized (this) {
+            if (!mFile.exists()) {
+                return false;
+            }
+            AtomicFile atomicFile = new AtomicFile(mFile);
+
+            try (FileInputStream inputStream = atomicFile.openRead()) {
+                XmlPullParser parser = Xml.newPullParser();
+                parser.setInput(inputStream, Xml.Encoding.UTF_8.name());
+                return getStateFromXml(parser);
+            } catch (XmlPullParserException | IOException e) {
+                Slog.e(TAG, "Failed to read XML", e);
+                return false;
+            }
+        }
+    }
+
+    private boolean getStateFromXml(XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        while (parser.getEventType() != XmlPullParser.START_TAG
+                || !TAG_DEVICE_STATE.equals(parser.getName())) {
+            if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
+                throw new XmlPullParserException("Malformed XML. Unable to find start of tag.");
+            }
+            parser.next();
+        }
+        return Boolean.parseBoolean(
+                parser.getAttributeValue(null /* namespace */, ATTR_IS_DEVICE_FINALIZED));
+    }
+
+    /**
+     * Callback for when state is read from disk.
+     */
+    interface DeviceStateCallback {
+        /**
+         * Callback for when state is finished reading from disk.
+         *
+         * @param isFinalized whether device is finalized
+         */
+        void onDeviceStateRead(boolean isFinalized);
+    }
+}
diff --git a/service/java/com/android/server/devicelock/DeviceLockService.java b/service/java/com/android/server/devicelock/DeviceLockService.java
index 4c34092..2de5408 100644
--- a/service/java/com/android/server/devicelock/DeviceLockService.java
+++ b/service/java/com/android/server/devicelock/DeviceLockService.java
@@ -16,7 +16,18 @@
 
 package com.android.server.devicelock;
 
+import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
 import android.util.Slog;
 
 import com.android.server.SystemService;
@@ -50,20 +61,65 @@
         Slog.d(TAG, "onBootPhase: " + phase);
     }
 
+    @NonNull
+    private static Context getUserContext(@NonNull Context context, @NonNull UserHandle user) {
+        if (Process.myUserHandle().equals(user)) {
+            return context;
+        } else {
+            return context.createContextAsUser(user, 0 /* flags */);
+        }
+    }
+
     @Override
-    public void onUserSwitching(TargetUser from, TargetUser to) {
+    public boolean isUserSupported(@NonNull TargetUser user) {
+        final UserManager userManager =
+                getUserContext(getContext(),
+                        user.getUserHandle()).getSystemService(UserManager.class);
+        return !userManager.isProfile();
+    }
+
+    @Override
+    public void onUserSwitching(@NonNull TargetUser from, @NonNull TargetUser to) {
         Objects.requireNonNull(to);
-        Slog.d(TAG, "onUserSwitching");
-        mImpl.setDeviceLockControllerPackageDefaultEnabledState(to.getUserHandle());
+        Slog.d(TAG, "onUserSwitching from: " + from + " to: " + to);
+        final UserHandle userHandle = to.getUserHandle();
+        mImpl.enforceDeviceLockControllerPackageEnabledState(userHandle);
+        mImpl.onUserSwitching(userHandle);
     }
 
     @Override
-    public void onUserUnlocking(TargetUser user) {
-        Slog.d(TAG, "onUserUnlocking");
+    public void onUserUnlocking(@NonNull TargetUser user) {
+        Slog.d(TAG, "onUserUnlocking: " + user);
     }
 
     @Override
-    public void onUserStopping(TargetUser user) {
-        Slog.d(TAG, "onUserStopping");
+    public void onUserUnlocked(@NonNull TargetUser user) {
+        Slog.d(TAG, "onUserUnlocked: " + user);
+        final UserHandle userHandle = user.getUserHandle();
+        mImpl.onUserUnlocked(userHandle);
+        // TODO(b/312521897): Add unit tests for this flow
+        registerUserSetupCompleteListener(userHandle);
+    }
+
+    @Override
+    public void onUserStopping(@NonNull TargetUser user) {
+        Slog.d(TAG, "onUserStopping: " + user);
+    }
+
+    private void registerUserSetupCompleteListener(UserHandle userHandle) {
+        final ContentResolver contentResolver = getUserContext(getContext(), userHandle)
+                .getContentResolver();
+        Uri setupCompleteUri = Settings.Secure.getUriFor(USER_SETUP_COMPLETE);
+        contentResolver.registerContentObserver(setupCompleteUri,
+                false /* notifyForDescendants */, new ContentObserver(null /* handler */) {
+                    @Override
+                    public void onChange(boolean selfChange, @Nullable Uri uri) {
+                        if (setupCompleteUri.equals(uri)
+                                && Settings.Secure.getInt(
+                                        contentResolver, USER_SETUP_COMPLETE, 0) != 0) {
+                            mImpl.onUserSetupCompleted(userHandle);
+                        }
+                    }
+                });
     }
 }
diff --git a/service/java/com/android/server/devicelock/DeviceLockServiceImpl.java b/service/java/com/android/server/devicelock/DeviceLockServiceImpl.java
index 494683b..b68505a 100644
--- a/service/java/com/android/server/devicelock/DeviceLockServiceImpl.java
+++ b/service/java/com/android/server/devicelock/DeviceLockServiceImpl.java
@@ -20,13 +20,16 @@
 import static android.app.role.RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP;
 import static android.content.IntentFilter.SYSTEM_HIGH_PRIORITY;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.DONT_KILL_APP;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.devicelock.DeviceId.DEVICE_ID_TYPE_IMEI;
 import static android.devicelock.DeviceId.DEVICE_ID_TYPE_MEID;
 
 import android.Manifest;
+import android.Manifest.permission;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.app.role.RoleManager;
 import android.content.BroadcastReceiver;
@@ -34,9 +37,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageManager.PackageInfoFlags;
 import android.content.pm.ServiceInfo;
 import android.devicelock.DeviceId.DeviceIdType;
 import android.devicelock.DeviceLockManager;
@@ -45,9 +48,13 @@
 import android.devicelock.IGetKioskAppsCallback;
 import android.devicelock.IIsDeviceLockedCallback;
 import android.devicelock.ILockUnlockDeviceCallback;
+import android.devicelock.ParcelableException;
+import android.net.NetworkPolicyManager;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.OutcomeReceiver;
+import android.os.PowerExemptionManager;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -56,8 +63,10 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -67,17 +76,54 @@
 final class DeviceLockServiceImpl extends IDeviceLockService.Stub {
     private static final String TAG = "DeviceLockServiceImpl";
 
+    // Keep this in sync with NetworkPolicyManager#POLICY_NONE.
+    private static final int POLICY_NONE = 0x0;
+    //Keep this in sync with NetworkPolicyManager#POLICY_ALLOW_METERED_BACKGROUND.
+    private static final int POLICY_ALLOW_METERED_BACKGROUND = 0x4;
+    private static final String ACTION_DEVICE_LOCK_KEEPALIVE =
+            "com.android.devicelock.action.KEEPALIVE";
+
+    // Workaround for timeout while adding the kiosk app as role holder for financing.
+    private static final int MAX_ADD_ROLE_HOLDER_TRIES = 4;
+
     private final Context mContext;
 
-    private final DeviceLockControllerConnector mDeviceLockControllerConnector;
+    private final RoleManager mRoleManager;
+    private final TelephonyManager mTelephonyManager;
+    private final AppOpsManager mAppOpsManager;
+
+    // Map user id -> DeviceLockControllerConnector
+    @GuardedBy("this")
+    private final ArrayMap<Integer, DeviceLockControllerConnector> mDeviceLockControllerConnectors;
+
+    private final DeviceLockControllerConnectorStub mDeviceLockControllerConnectorStub =
+            new DeviceLockControllerConnectorStub();
 
     private final DeviceLockControllerPackageUtils mPackageUtils;
 
     private final ServiceInfo mServiceInfo;
 
-    // The following should be a SystemApi on AppOpsManager.
-    private static final String OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION =
+    // Map user id -> ServiceConnection for kiosk keepalive.
+    private final ArrayMap<Integer, KeepaliveServiceConnection> mKioskKeepaliveServiceConnections;
+
+    // Map user id -> ServiceConnection for controller keepalive.
+    private final ArrayMap<Integer, KeepaliveServiceConnection>
+            mControllerKeepaliveServiceConnections;
+
+    private final DeviceLockPersistentStore mPersistentStore;
+
+    private boolean mUseStubConnector = false;
+
+    // The following string constants should be a SystemApi on AppOpsManager.
+    @VisibleForTesting
+    static final String OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION =
             "android:system_exempt_from_activity_bg_start_restriction";
+    @VisibleForTesting
+    static final String OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS =
+            "android:system_exempt_from_dismissible_notifications";
+    @VisibleForTesting
+    static final String OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS =
+            "android:system_exempt_from_power_restrictions";
 
     // Stopgap: this receiver should be replaced by an API on DeviceLockManager.
     private final class DeviceLockClearReceiver extends BroadcastReceiver {
@@ -93,74 +139,118 @@
             // The result will still be sent to the 'resultReceiver' of 'sendOrderedBroadcast'.
             abortBroadcast();
 
+            final UserHandle userHandle = getSendingUser();
+
             final PendingResult pendingResult = goAsync();
 
-            mDeviceLockControllerConnector.clearDeviceRestrictions(new OutcomeReceiver<>() {
+            getDeviceLockControllerConnector(userHandle).clearDeviceRestrictions(
+                    new OutcomeReceiver<>() {
 
-                private void setResult(int resultCode) {
-                    pendingResult.setResultCode(resultCode);
+                        private void setResult(int resultCode) {
+                            pendingResult.setResultCode(resultCode);
 
-                    pendingResult.finish();
-                }
+                            pendingResult.finish();
+                        }
 
-                @Override
-                public void onResult(Void ignored) {
-                    Slog.i(TAG, "Device cleared ");
+                        @Override
+                        public void onResult(Void ignored) {
+                            Slog.i(TAG, "Device cleared ");
 
-                    setResult(DeviceLockClearReceiver.CLEAR_SUCCEEDED);
-                }
+                            setResult(DeviceLockClearReceiver.CLEAR_SUCCEEDED);
+                        }
 
-                @Override
-                public void onError(Exception ex) {
-                    Slog.e(TAG, "Exception clearing device: ", ex);
+                        @Override
+                        public void onError(Exception ex) {
+                            Slog.e(TAG, "Exception clearing device: ", ex);
 
-                    setResult(DeviceLockClearReceiver.CLEAR_FAILED);
-                }
-            });
+                            setResult(DeviceLockClearReceiver.CLEAR_FAILED);
+                        }
+                    });
         }
     }
 
     // Last supported device id type
     private static final @DeviceIdType int LAST_DEVICE_ID_TYPE = DEVICE_ID_TYPE_MEID;
 
-    private static final String MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER =
+    @VisibleForTesting
+    static final String MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER =
             "com.android.devicelockcontroller.permission."
                     + "MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER";
 
+    @NonNull
+    private DeviceLockControllerConnector getDeviceLockControllerConnector(UserHandle userHandle) {
+        synchronized (this) {
+            if (mUseStubConnector) {
+                return mDeviceLockControllerConnectorStub;
+            } else {
+                final int userId = userHandle.getIdentifier();
+                DeviceLockControllerConnector deviceLockControllerConnector =
+                        mDeviceLockControllerConnectors.get(userId);
+                if (deviceLockControllerConnector == null) {
+                    final ComponentName componentName = new ComponentName(mServiceInfo.packageName,
+                            mServiceInfo.name);
+                    deviceLockControllerConnector = new DeviceLockControllerConnectorImpl(mContext,
+                            componentName, userHandle);
+                    mDeviceLockControllerConnectors.put(userId, deviceLockControllerConnector);
+                }
+
+                return deviceLockControllerConnector;
+            }
+        }
+    }
+
+    @NonNull
+    private DeviceLockControllerConnector getDeviceLockControllerConnector() {
+        final UserHandle userHandle = Binder.getCallingUserHandle();
+        return getDeviceLockControllerConnector(userHandle);
+    }
+
     DeviceLockServiceImpl(@NonNull Context context) {
+        this(context, context.getSystemService(TelephonyManager.class));
+    }
+
+    @VisibleForTesting
+    DeviceLockServiceImpl(@NonNull Context context, TelephonyManager telephonyManager) {
         mContext = context;
+        mTelephonyManager = telephonyManager;
+
+        mRoleManager = context.getSystemService(RoleManager.class);
+        mAppOpsManager = context.getSystemService(AppOpsManager.class);
+
+        mDeviceLockControllerConnectors = new ArrayMap<>();
+
+        mKioskKeepaliveServiceConnections = new ArrayMap<>();
+        mControllerKeepaliveServiceConnections = new ArrayMap<>();
 
         mPackageUtils = new DeviceLockControllerPackageUtils(context);
 
+        mPersistentStore = new DeviceLockPersistentStore();
+
         final StringBuilder errorMessage = new StringBuilder();
         mServiceInfo = mPackageUtils.findService(errorMessage);
 
         if (mServiceInfo == null) {
-            mDeviceLockControllerConnector = null;
-
             throw new RuntimeException(errorMessage.toString());
         }
 
-        if (!mServiceInfo.applicationInfo.enabled) {
-            Slog.w(TAG, "Device Lock Controller is disabled");
-            setDeviceLockControllerPackageDefaultEnabledState(UserHandle.SYSTEM);
-        }
-
-        final ComponentName componentName = new ComponentName(mServiceInfo.packageName,
-                mServiceInfo.name);
-
-        mDeviceLockControllerConnector = new DeviceLockControllerConnector(context, componentName);
+        enforceDeviceLockControllerPackageEnabledState(UserHandle.SYSTEM);
 
         final IntentFilter intentFilter = new IntentFilter(DeviceLockClearReceiver.ACTION_CLEAR);
         // Run before any eventual app receiver (there should be none).
         intentFilter.setPriority(SYSTEM_HIGH_PRIORITY);
-        context.registerReceiver(new DeviceLockClearReceiver(),
-                intentFilter,
+        context.registerReceiverForAllUsers(new DeviceLockClearReceiver(), intentFilter,
                 Manifest.permission.MANAGE_DEVICE_LOCK_STATE, null /* scheduler */,
                 Context.RECEIVER_EXPORTED);
     }
 
-    void setDeviceLockControllerPackageDefaultEnabledState(@NonNull UserHandle userHandle) {
+    void enforceDeviceLockControllerPackageEnabledState(@NonNull UserHandle userHandle) {
+        mPersistentStore.readFinalizedState(
+                isFinalized -> setDeviceLockControllerPackageEnabledState(userHandle, !isFinalized),
+                mContext.getMainExecutor());
+    }
+
+    private void setDeviceLockControllerPackageEnabledState(UserHandle userHandle,
+            boolean enabled) {
         final String controllerPackageName = mServiceInfo.packageName;
 
         Context controllerContext;
@@ -175,8 +265,70 @@
 
         final PackageManager controllerPackageManager = controllerContext.getPackageManager();
 
-        controllerPackageManager.setApplicationEnabledSetting(controllerPackageName,
-                COMPONENT_ENABLED_STATE_DEFAULT, DONT_KILL_APP);
+        final int enableState =
+                enabled ? COMPONENT_ENABLED_STATE_DEFAULT : COMPONENT_ENABLED_STATE_DISABLED;
+        // We cannot check if user control is disabled since
+        // DevicePolicyManager.getUserControlDisabledPackages() acts on the calling user.
+        // Additionally, we would have to catch SecurityException anyways to avoid TOCTOU bugs
+        // since checking and setting is not atomic.
+        try {
+            controllerPackageManager.setApplicationEnabledSetting(controllerPackageName,
+                    enableState, enabled ? DONT_KILL_APP : 0);
+        } catch (SecurityException ex) {
+            // This exception is thrown when Device Lock Controller has already enabled
+            // package protection for itself. This is an expected behaviour.
+            // Note: the exception description thrown by
+            // PackageManager.setApplicationEnabledSetting() is somehow misleading because it says
+            // that a protected package cannot be disabled (but we're actually trying to enable it).
+        }
+        if (!enabled) {
+            synchronized (this) {
+                mUseStubConnector = true;
+                mDeviceLockControllerConnectors.clear();
+            }
+        }
+    }
+
+    void onUserSwitching(@NonNull UserHandle userHandle) {
+        getDeviceLockControllerConnector(userHandle).onUserSwitching(new OutcomeReceiver<>() {
+            @Override
+            public void onResult(Void ignored) {
+                Slog.i(TAG, "User switching reported for: " + userHandle);
+            }
+
+            @Override
+            public void onError(Exception ex) {
+                Slog.e(TAG, "Exception reporting user switching for: " + userHandle, ex);
+            }
+        });
+    }
+
+    void onUserUnlocked(@NonNull UserHandle userHandle) {
+        getDeviceLockControllerConnector(userHandle).onUserUnlocked(new OutcomeReceiver<>() {
+            @Override
+            public void onResult(Void ignored) {
+                Slog.i(TAG, "User unlocked reported for: " + userHandle);
+            }
+
+            @Override
+            public void onError(Exception ex) {
+                Slog.e(TAG, "Exception reporting user unlocked for: " + userHandle, ex);
+            }
+        });
+    }
+
+    void onUserSetupCompleted(UserHandle userHandle) {
+        getDeviceLockControllerConnector(userHandle).onUserSetupCompleted(new OutcomeReceiver<>() {
+            @Override
+            public void onResult(Void ignored) {
+                Slog.i(TAG, "User set up complete reported for: " + userHandle);
+            }
+
+            @Override
+            public void onError(Exception ex) {
+                Slog.e(TAG, "Exception reporting user setup complete for: " + userHandle, ex);
+            }
+        });
     }
 
     private boolean checkCallerPermission() {
@@ -185,48 +337,52 @@
     }
 
     private void reportDeviceLockedUnlocked(@NonNull ILockUnlockDeviceCallback callback,
-            boolean success) {
+            @Nullable Exception exception) {
         try {
-            if (success) {
+            if (exception == null) {
                 callback.onDeviceLockedUnlocked();
             } else {
-                callback.onError(ILockUnlockDeviceCallback.ERROR_UNKNOWN);
+                callback.onError(getParcelableException(exception));
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "Unable to send result to the callback", e);
         }
     }
 
-    private OutcomeReceiver<Void, Exception>
-            getLockUnlockOutcomeReceiver(@NonNull ILockUnlockDeviceCallback callback,
-                @NonNull String successMessage) {
+    private OutcomeReceiver<Void, Exception> getLockUnlockOutcomeReceiver(
+            @NonNull ILockUnlockDeviceCallback callback, @NonNull String successMessage) {
         return new OutcomeReceiver<>() {
             @Override
             public void onResult(Void ignored) {
                 Slog.i(TAG, successMessage);
-                reportDeviceLockedUnlocked(callback, true /* success */);
+                reportDeviceLockedUnlocked(callback, /* exception= */ null);
             }
 
             @Override
             public void onError(Exception ex) {
                 Slog.e(TAG, "Exception: ", ex);
-                reportDeviceLockedUnlocked(callback, false /* success */);
+                reportDeviceLockedUnlocked(callback, ex);
             }
         };
     }
 
+    private ParcelableException getParcelableException(Exception exception) {
+        return exception instanceof ParcelableException ? (ParcelableException) exception
+                : new ParcelableException(exception);
+    }
+
     @Override
     public void lockDevice(@NonNull ILockUnlockDeviceCallback callback) {
         if (!checkCallerPermission()) {
             try {
-                callback.onError(ILockUnlockDeviceCallback.ERROR_SECURITY);
+                callback.onError(new ParcelableException(new SecurityException()));
             } catch (RemoteException e) {
                 Slog.e(TAG, "lockDevice() - Unable to send error to the callback", e);
             }
             return;
         }
 
-        mDeviceLockControllerConnector.lockDevice(
+        getDeviceLockControllerConnector().lockDevice(
                 getLockUnlockOutcomeReceiver(callback, "Device locked"));
     }
 
@@ -234,14 +390,14 @@
     public void unlockDevice(@NonNull ILockUnlockDeviceCallback callback) {
         if (!checkCallerPermission()) {
             try {
-                callback.onError(ILockUnlockDeviceCallback.ERROR_SECURITY);
+                callback.onError(new ParcelableException(new SecurityException()));
             } catch (RemoteException e) {
                 Slog.e(TAG, "unlockDevice() - Unable to send error to the callback", e);
             }
             return;
         }
 
-        mDeviceLockControllerConnector.unlockDevice(
+        getDeviceLockControllerConnector().unlockDevice(
                 getLockUnlockOutcomeReceiver(callback, "Device unlocked"));
     }
 
@@ -249,59 +405,54 @@
     public void isDeviceLocked(@NonNull IIsDeviceLockedCallback callback) {
         if (!checkCallerPermission()) {
             try {
-                callback.onError(IIsDeviceLockedCallback.ERROR_SECURITY);
+                callback.onError(new ParcelableException(new SecurityException()));
             } catch (RemoteException e) {
                 Slog.e(TAG, "isDeviceLocked() - Unable to send error to the callback", e);
             }
             return;
         }
 
-        mDeviceLockControllerConnector.isDeviceLocked(
-                new OutcomeReceiver<>() {
-                    @Override
-                    public void onResult(Boolean isLocked) {
-                        Slog.i(TAG, isLocked ? "Device is locked" : "Device is not locked");
-                        try {
-                            callback.onIsDeviceLocked(isLocked);
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "isDeviceLocked() - Unable to send result to the "
-                                    + "callback", e);
-                        }
-                    }
+        getDeviceLockControllerConnector().isDeviceLocked(new OutcomeReceiver<>() {
+            @Override
+            public void onResult(Boolean isLocked) {
+                Slog.i(TAG, isLocked ? "Device is locked" : "Device is not locked");
+                try {
+                    callback.onIsDeviceLocked(isLocked);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "isDeviceLocked() - Unable to send result to the " + "callback", e);
+                }
+            }
 
-                    @Override
-                    public void onError(Exception ex) {
-                            Slog.e(TAG, "Exception: ", ex);
-                            try {
-                                callback.onError(ILockUnlockDeviceCallback.ERROR_UNKNOWN);
-                            } catch (RemoteException e) {
-                                Slog.e(TAG, "isDeviceLocked() - Unable to send error to the "
-                                        + "callback", e);
-                            }
-                        }
-                });
+            @Override
+            public void onError(Exception ex) {
+                Slog.e(TAG, "isDeviceLocked exception: ", ex);
+                try {
+                    callback.onError(getParcelableException(ex));
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "isDeviceLocked() - Unable to send error to the " + "callback", e);
+                }
+            }
+        });
     }
 
     @VisibleForTesting
     void getDeviceId(@NonNull IGetDeviceIdCallback callback, int deviceIdTypeBitmap) {
         try {
             if (deviceIdTypeBitmap < 0 || deviceIdTypeBitmap >= (1 << (LAST_DEVICE_ID_TYPE + 1))) {
-                callback.onError(IGetDeviceIdCallback.ERROR_INVALID_DEVICE_ID_TYPE_BITMAP);
+                callback.onError(new ParcelableException("Invalid device type"));
                 return;
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "getDeviceId() - Unable to send result to the callback", e);
         }
 
-        final TelephonyManager telephonyManager =
-                mContext.getSystemService(TelephonyManager.class);
-        int activeModemCount = telephonyManager.getActiveModemCount();
+        int activeModemCount = mTelephonyManager.getActiveModemCount();
         List<String> imeiList = new ArrayList<String>();
         List<String> meidList = new ArrayList<String>();
 
         if ((deviceIdTypeBitmap & (1 << DEVICE_ID_TYPE_IMEI)) != 0) {
             for (int i = 0; i < activeModemCount; i++) {
-                String imei = telephonyManager.getImei(i);
+                String imei = mTelephonyManager.getImei(i);
                 if (!TextUtils.isEmpty(imei)) {
                     imeiList.add(imei);
                 }
@@ -310,57 +461,56 @@
 
         if ((deviceIdTypeBitmap & (1 << DEVICE_ID_TYPE_MEID)) != 0) {
             for (int i = 0; i < activeModemCount; i++) {
-                String meid = telephonyManager.getMeid(i);
+                String meid = mTelephonyManager.getMeid(i);
                 if (!TextUtils.isEmpty(meid)) {
                     meidList.add(meid);
                 }
             }
         }
 
-        mDeviceLockControllerConnector.getDeviceId(new OutcomeReceiver<>() {
-                @Override
-                public void onResult(String deviceId) {
-                    Slog.i(TAG, "Get Device ID ");
-                    try {
-                        if (meidList.contains(deviceId)) {
-                            callback.onDeviceIdReceived(DEVICE_ID_TYPE_MEID, deviceId);
-                            return;
-                        }
-                        if (imeiList.contains(deviceId)) {
-                            callback.onDeviceIdReceived(DEVICE_ID_TYPE_IMEI, deviceId);
-                            return;
-                        }
-                        // When a device ID is returned from DLC App, but none of the IDs
-                        // got from TelephonyManager matches that device ID.
-                        //
-                        // TODO(b/270392813): Send the device ID back to the callback
-                        // with UNSPECIFIED device ID type.
-                        callback.onError(IGetDeviceIdCallback.ERROR_CANNOT_GET_DEVICE_ID);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "getDeviceId() - Unable to send result to the "
-                                + "callback", e);
+        getDeviceLockControllerConnector().getDeviceId(new OutcomeReceiver<>() {
+            @Override
+            public void onResult(String deviceId) {
+                Slog.i(TAG, "Get Device ID ");
+                try {
+                    if (meidList.contains(deviceId)) {
+                        callback.onDeviceIdReceived(DEVICE_ID_TYPE_MEID, deviceId);
+                        return;
                     }
-                }
-
-                @Override
-                public void onError(Exception ex) {
-                    Slog.e(TAG, "Exception: ", ex);
-                    try {
-                        callback.onError(IGetDeviceIdCallback.ERROR_CANNOT_GET_DEVICE_ID);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "getDeviceId() - Unable to send error to the "
-                                + "callback", e);
+                    if (imeiList.contains(deviceId)) {
+                        callback.onDeviceIdReceived(DEVICE_ID_TYPE_IMEI, deviceId);
+                        return;
                     }
+                    // When a device ID is returned from DLC App, but none of the IDs got from
+                    // TelephonyManager matches that device ID.
+                    //
+                    // TODO(b/270392813): Send the device ID back to the callback with
+                    //  UNSPECIFIED device ID type.
+                    callback.onError(new ParcelableException("Unable to get device id"));
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "getDeviceId() - Unable to send result to the callback", e);
                 }
             }
-        );
+
+            @Override
+            public void onError(Exception ex) {
+                Slog.e(TAG, "Exception: ", ex);
+                try {
+                    callback.onError(getParcelableException(ex));
+                } catch (RemoteException e) {
+                    Slog.e(TAG,
+                            "getDeviceId() - " + "Unable to send error to" + " the " + "callback",
+                            e);
+                }
+            }
+        });
     }
 
     @Override
     public void getDeviceId(@NonNull IGetDeviceIdCallback callback) {
         if (!checkCallerPermission()) {
             try {
-                callback.onError(IGetDeviceIdCallback.ERROR_SECURITY);
+                callback.onError(new ParcelableException(new SecurityException()));
             } catch (RemoteException e) {
                 Slog.e(TAG, "getDeviceId() - Unable to send error to the callback", e);
             }
@@ -387,10 +537,9 @@
         final ArrayMap kioskApps = new ArrayMap<Integer, String>();
 
         final UserHandle userHandle = Binder.getCallingUserHandle();
-        final RoleManager roleManager = mContext.getSystemService(RoleManager.class);
         final long identity = Binder.clearCallingIdentity();
         try {
-            List<String> roleHolders = roleManager.getRoleHoldersAsUser(
+            List<String> roleHolders = mRoleManager.getRoleHoldersAsUser(
                     RoleManager.ROLE_FINANCED_DEVICE_KIOSK, userHandle);
 
             if (!roleHolders.isEmpty()) {
@@ -432,6 +581,24 @@
         remoteCallback.sendResult(result);
     }
 
+    private void addFinancedDeviceKioskRoleInternal(@NonNull String packageName,
+            @NonNull RemoteCallback remoteCallback, @NonNull UserHandle userHandle, long identity,
+            int remainingTries) {
+        mRoleManager.addRoleHolderAsUser(RoleManager.ROLE_FINANCED_DEVICE_KIOSK, packageName,
+                MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, mContext.getMainExecutor(),
+                accepted -> {
+                    if (accepted || remainingTries == 1) {
+                        reportResult(accepted, identity, remoteCallback);
+                    } else {
+                        final int retryNumber = MAX_ADD_ROLE_HOLDER_TRIES - remainingTries + 1;
+                        Slog.w(TAG, "Retrying adding financed device role to kiosk app (retry "
+                                + retryNumber + ")");
+                        addFinancedDeviceKioskRoleInternal(packageName, remoteCallback, userHandle,
+                                identity, remainingTries - 1);
+                    }
+                });
+    }
+
     @Override
     public void addFinancedDeviceKioskRole(@NonNull String packageName,
             @NonNull RemoteCallback remoteCallback) {
@@ -440,12 +607,10 @@
         }
 
         final UserHandle userHandle = Binder.getCallingUserHandle();
-        final RoleManager roleManager = mContext.getSystemService(RoleManager.class);
         final long identity = Binder.clearCallingIdentity();
 
-        roleManager.addRoleHolderAsUser(RoleManager.ROLE_FINANCED_DEVICE_KIOSK, packageName,
-                MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, mContext.getMainExecutor(),
-                accepted -> reportResult(accepted, identity, remoteCallback));
+        addFinancedDeviceKioskRoleInternal(packageName, remoteCallback, userHandle, identity,
+                MAX_ADD_ROLE_HOLDER_TRIES);
 
         Binder.restoreCallingIdentity(identity);
     }
@@ -458,26 +623,320 @@
         }
 
         final UserHandle userHandle = Binder.getCallingUserHandle();
-        final RoleManager roleManager = mContext.getSystemService(RoleManager.class);
         final long identity = Binder.clearCallingIdentity();
 
-        roleManager.removeRoleHolderAsUser(RoleManager.ROLE_FINANCED_DEVICE_KIOSK, packageName,
+        // Clear the FLAG_PERMISSION_GRANTED_BY_ROLE flag from POST_NOTIFICATIONS for the kiosk app
+        // before removing the ROLE_FINANCED_DEVICE_KIOSK role, to prevent the app from being
+        // killed.
+        final PackageManager packageManager = mContext.getPackageManager();
+        packageManager.updatePermissionFlags(permission.POST_NOTIFICATIONS, packageName,
+                PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, /* flagValues= */ 0, userHandle);
+
+        mRoleManager.removeRoleHolderAsUser(RoleManager.ROLE_FINANCED_DEVICE_KIOSK, packageName,
                 MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, mContext.getMainExecutor(),
                 accepted -> reportResult(accepted, identity, remoteCallback));
 
         Binder.restoreCallingIdentity(identity);
     }
 
-    private void setExemption(String packageName, int uid, String appOp, boolean exempt,
-            @NonNull RemoteCallback remoteCallback) {
-        final AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
-        final long identity = Binder.clearCallingIdentity();
+    /**
+     * @param uid         The uid whose AppOps mode needs to change.
+     * @param packageName The name of the package whose AppOp mode needs to change.
+     * @param appOps      A list of appOps to change
+     * @param allowed     If true, the mode would be set to {@link AppOpsManager#MODE_ALLOWED};
+     *                    false,
+     *                    the mode would be set to {@link AppOpsManager#MODE_DEFAULT}.
+     * @return a boolean value indicates whether the app ops modes have been changed to the
+     * requested value.
+     */
+    private boolean setAppOpsModes(int uid, String packageName, String[] appOps, boolean allowed) {
+        final int mode = allowed ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_DEFAULT;
 
-        final int mode = exempt ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_DEFAULT;
-
-        appOpsManager.setMode(appOp, uid, packageName, mode);
-
+        long identity = Binder.clearCallingIdentity();
+        for (String appOp : appOps) {
+            mAppOpsManager.setMode(appOp, uid, packageName, mode);
+        }
         Binder.restoreCallingIdentity(identity);
+        return true;
+    }
+
+    /**
+     * Set the exemption state for activity background start restriction for the calling uid.
+     * Caller must hold the {@link MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER} permission.
+     *
+     * @param exempt if true, the calling uid will be set to exempt from activity background start
+     *               restriction; false, the exemption state will be set to default.
+     */
+    @Override
+    public void setCallerExemptFromActivityBgStartRestrictionState(boolean exempt,
+            @NonNull RemoteCallback remoteCallback) {
+        if (!checkDeviceLockControllerPermission(remoteCallback)) {
+            return;
+        }
+        Bundle result = new Bundle();
+        result.putBoolean(KEY_REMOTE_CALLBACK_RESULT,
+                setAppOpsModes(Binder.getCallingUid(), mServiceInfo.packageName,
+                        new String[]{OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION},
+                        exempt));
+        remoteCallback.sendResult(result);
+    }
+
+    /**
+     * Set whether the caller is allowed to send undismissible notifications.
+     *
+     * @param allowed true if the caller can send undismissible notifications, false otherwise
+     */
+    @Override
+    public void setCallerAllowedToSendUndismissibleNotifications(boolean allowed,
+            @NonNull RemoteCallback remoteCallback) {
+        if (!checkDeviceLockControllerPermission(remoteCallback)) {
+            return;
+        }
+        Bundle result = new Bundle();
+        result.putBoolean(KEY_REMOTE_CALLBACK_RESULT,
+                setAppOpsModes(Binder.getCallingUid(), mServiceInfo.packageName,
+                        new String[]{OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS}, allowed));
+        remoteCallback.sendResult(result);
+    }
+
+    /**
+     * @param uid   The uid whose network policy needs to change.
+     * @param allow whether to allow background data usage in metered data mode.
+     * @return a boolean value indicates whether the policy change is a success.
+     */
+    private boolean setNetworkPolicyForUid(int uid, boolean allow) {
+        boolean result;
+        long caller = Binder.clearCallingIdentity();
+        try {
+            // TODO(b/319266027): Figure out a long term solution instead of using reflection here.
+            NetworkPolicyManager networkPolicyManager = mContext.getSystemService(
+                    NetworkPolicyManager.class);
+            NetworkPolicyManager.class.getDeclaredMethod("setUidPolicy", Integer.TYPE,
+                    Integer.TYPE).invoke(networkPolicyManager, uid,
+                    allow ? POLICY_ALLOW_METERED_BACKGROUND : POLICY_NONE);
+            result = true;
+        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
+            Slog.e(TAG, "Failed to exempt data usage for given uid: " + uid, e);
+            result = false;
+        }
+        Binder.restoreCallingIdentity(caller);
+        return result;
+    }
+
+    private boolean setPowerExemptionForPackage(String packageName, boolean allow) {
+        boolean result;
+        long caller = Binder.clearCallingIdentity();
+        try {
+            // TODO(b/321539640): Figure out a long term solution instead of using reflection here.
+            PowerExemptionManager powerExemptionManager = mContext.getSystemService(
+                    PowerExemptionManager.class);
+            String methodName = allow ? "addToPermanentAllowList" : "removeFromPermanentAllowList";
+            PowerExemptionManager.class.getDeclaredMethod(methodName, String.class).invoke(
+                    powerExemptionManager, packageName);
+            result = true;
+        } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
+            Slog.e(TAG, "Failed to exempt power usage for given package: " + packageName, e);
+            result = false;
+        }
+        Binder.restoreCallingIdentity(caller);
+        return result;
+    }
+
+    /**
+     * Set the exemption state for app restrictions(e.g. hibernation, battery and data usage
+     * restriction) for the given uid
+     * Caller must hold the {@link MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER} permission.
+     *
+     * @param exempt if true, the given uid will be set to exempt from hibernation, battery and data
+     *               usage restriction; false, the exemption state will be set to default.
+     */
+    @Override
+    public void setUidExemptFromRestrictionsState(int uid, boolean exempt,
+            @NonNull RemoteCallback remoteCallback) {
+        if (!checkDeviceLockControllerPermission(remoteCallback)) {
+            return;
+        }
+        boolean setAppOpsResult = false;
+        boolean setPowerExemptionResult = false;
+
+        String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+        if (packageNames == null || packageNames.length < 1) {
+            Slog.e(TAG, "Can not find package name for given uid: " + uid);
+        } else {
+            setAppOpsResult = setAppOpsModes(uid, packageNames[0],
+                    new String[]{OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION,
+                            OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS}, exempt);
+            setPowerExemptionResult = setPowerExemptionForPackage(packageNames[0], exempt);
+        }
+        boolean setNetworkPolicyResult = setNetworkPolicyForUid(uid, exempt);
+        Bundle result = new Bundle();
+        result.putBoolean(KEY_REMOTE_CALLBACK_RESULT,
+                setAppOpsResult && setPowerExemptionResult && setNetworkPolicyResult);
+        remoteCallback.sendResult(result);
+    }
+
+    private class KeepaliveServiceConnection implements ServiceConnection {
+        final boolean mIsKiosk;
+        final String mPackageName;
+        final UserHandle mUserHandle;
+
+        final Intent mService;
+
+        KeepaliveServiceConnection(boolean isKiosk, String packageName, UserHandle userHandle) {
+            super();
+            mIsKiosk = isKiosk;
+            mPackageName = packageName;
+            mUserHandle = userHandle;
+            mService = new Intent(ACTION_DEVICE_LOCK_KEEPALIVE).setPackage(packageName);
+        }
+
+        private boolean bind() {
+            return mContext.bindServiceAsUser(mService, this, Context.BIND_AUTO_CREATE,
+                    mUserHandle);
+        }
+
+        private boolean rebind() {
+            mContext.unbindService(this);
+            boolean bound = bind();
+
+            if (bound) {
+                getDeviceLockControllerConnector(mUserHandle).onAppCrashed(mIsKiosk,
+                        new OutcomeReceiver<>() {
+                            @Override
+                            public void onResult(Void result) {
+                                Slog.i(TAG,
+                                        "Notified controller about " + mPackageName + " crash");
+                            }
+
+                            @Override
+                            public void onError(Exception ex) {
+                                Slog.e(TAG, "On " + mPackageName + " crashed error: ", ex);
+                            }
+                        });
+            }
+
+            return bound;
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            Slog.i(TAG, mPackageName + " keepalive successful for user " + mUserHandle);
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            if (rebind()) {
+                Slog.i(TAG,
+                        "onServiceDisconnected rebind successful for " + mPackageName + " user "
+                                + mUserHandle);
+            } else {
+                Slog.e(TAG, "onServiceDisconnected rebind failed for " + mPackageName + " user "
+                        + mUserHandle);
+            }
+        }
+
+        @Override
+        public void onBindingDied(ComponentName name) {
+            ServiceConnection.super.onBindingDied(name);
+            if (rebind()) {
+                Slog.i(TAG, "onBindingDied rebind successful for " + mPackageName + " user "
+                        + mUserHandle);
+            } else {
+                Slog.e(TAG,
+                        "onBindingDied rebind failed for " + mPackageName + " user "
+                                + mUserHandle);
+            }
+        }
+    }
+
+    @Override
+    public void enableKioskKeepalive(String packageName, @NonNull RemoteCallback remoteCallback) {
+        enableKeepalive(true /* forKiosk */, packageName, remoteCallback);
+    }
+
+    @Override
+    public void disableKioskKeepalive(@NonNull RemoteCallback remoteCallback) {
+        disableKeepalive(true /* forKiosk */, remoteCallback);
+    }
+
+    @Override
+    public void enableControllerKeepalive(@NonNull RemoteCallback remoteCallback) {
+        enableKeepalive(false /* forKiosk */, mServiceInfo.packageName, remoteCallback);
+    }
+
+    @Override
+    public void disableControllerKeepalive(@NonNull RemoteCallback remoteCallback) {
+        disableKeepalive(false /* forKiosk */, remoteCallback);
+    }
+
+    private void enableKeepalive(boolean forKiosk, String packageName,
+            @NonNull RemoteCallback remoteCallback) {
+        final UserHandle controllerUserHandle = Binder.getCallingUserHandle();
+        final int controllerUserId = controllerUserHandle.getIdentifier();
+        boolean keepaliveEnabled = false;
+        final ArrayMap<Integer, KeepaliveServiceConnection> keepaliveServiceConnections =
+                forKiosk ? mKioskKeepaliveServiceConnections
+                        : mControllerKeepaliveServiceConnections;
+
+        synchronized (this) {
+            if (keepaliveServiceConnections.get(controllerUserId) == null) {
+                final KeepaliveServiceConnection serviceConnection =
+                        new KeepaliveServiceConnection(
+                                forKiosk, packageName, controllerUserHandle);
+                final long identity = Binder.clearCallingIdentity();
+                if (serviceConnection.bind()) {
+                    keepaliveServiceConnections.put(controllerUserId, serviceConnection);
+                    keepaliveEnabled = true;
+                } else {
+                    Slog.w(TAG, "enableKeepalive: failed to bind to keepalive service "
+                            + " for package: " + packageName + " user:" + controllerUserHandle);
+                    mContext.unbindService(serviceConnection);
+                }
+                Binder.restoreCallingIdentity(identity);
+            } else {
+                // Consider success if we already have an entry for this user id.
+                keepaliveEnabled = true;
+            }
+        }
+
+        final Bundle result = new Bundle();
+        result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, keepaliveEnabled);
+        remoteCallback.sendResult(result);
+    }
+
+    private void disableKeepalive(boolean isKiosk, @NonNull RemoteCallback remoteCallback) {
+        final UserHandle controllerUserHandle = Binder.getCallingUserHandle();
+        final int controllerUserId = controllerUserHandle.getIdentifier();
+        final KeepaliveServiceConnection serviceConnection;
+        final ArrayMap<Integer, KeepaliveServiceConnection> keepaliveServiceConnections =
+                isKiosk ? mKioskKeepaliveServiceConnections
+                        : mControllerKeepaliveServiceConnections;
+
+        synchronized (this) {
+            serviceConnection = keepaliveServiceConnections.remove(controllerUserId);
+        }
+
+        if (serviceConnection != null) {
+            final long identity = Binder.clearCallingIdentity();
+            mContext.unbindService(serviceConnection);
+            Binder.restoreCallingIdentity(identity);
+        } else {
+            final String target = isKiosk ? "kiosk" : "controller";
+            Slog.e(TAG,
+                    "disableKeepalive: Service connection to " + target
+                            + " not found for user: "
+                            + controllerUserHandle);
+        }
+
+        final Bundle result = new Bundle();
+        result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, serviceConnection != null);
+        remoteCallback.sendResult(result);
+    }
+
+    @Override
+    public void setDeviceFinalized(boolean finalized, @NonNull RemoteCallback remoteCallback) {
+        mPersistentStore.scheduleWrite(finalized);
+        setDeviceLockControllerPackageEnabledState(getCallingUserHandle(), false /* enabled */);
 
         final Bundle result = new Bundle();
         result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, true);
@@ -485,40 +944,23 @@
     }
 
     @Override
-    public void setExemptFromActivityBackgroundStartRestriction(boolean exempt,
+    public void setPostNotificationsSystemFixed(boolean systemFixed,
             @NonNull RemoteCallback remoteCallback) {
-        if (!checkDeviceLockControllerPermission(remoteCallback)) {
-            return;
-        }
-
-        setExemption(mServiceInfo.packageName, Binder.getCallingUid(),
-                OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION, exempt, remoteCallback);
-    }
-
-    @Override
-    public void setExemptFromHibernation(String packageName, boolean exempt,
-            @NonNull RemoteCallback remoteCallback) {
-        if (!checkDeviceLockControllerPermission(remoteCallback)) {
-            return;
-        }
-
-        final UserHandle controllerUserHandle = Binder.getCallingUserHandle();
-        final int controllerUserId = controllerUserHandle.getIdentifier();
+        final UserHandle userHandle = Binder.getCallingUserHandle();
         final PackageManager packageManager = mContext.getPackageManager();
-        int kioskUid;
+        final int permissionFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+        final int newFlagValues = systemFixed ? permissionFlags : 0;
         final long identity = Binder.clearCallingIdentity();
-        try {
-            kioskUid = packageManager.getPackageUidAsUser(packageName, PackageInfoFlags.of(0),
-                    controllerUserId);
-        } catch (NameNotFoundException e) {
-            Binder.restoreCallingIdentity(identity);
-            Slog.e(TAG, "Failed to set hibernation appop", e);
-            reportErrorToCaller(remoteCallback);
-            return;
-        }
+        // Make sure permission hasn't been revoked.
+        packageManager.grantRuntimePermission(mServiceInfo.packageName,
+                permission.POST_NOTIFICATIONS, userHandle);
+        packageManager.updatePermissionFlags(permission.POST_NOTIFICATIONS,
+                mServiceInfo.packageName, permissionFlags, newFlagValues,
+                userHandle);
         Binder.restoreCallingIdentity(identity);
 
-        setExemption(packageName, kioskUid, OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION, exempt,
-                remoteCallback);
+        final Bundle result = new Bundle();
+        result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, true);
+        remoteCallback.sendResult(result);
     }
 }
diff --git a/tests/cts/Android.bp b/tests/cts/Android.bp
index 1d099df..f0a1723 100644
--- a/tests/cts/Android.bp
+++ b/tests/cts/Android.bp
@@ -26,7 +26,7 @@
     ],
     static_libs: [
         "androidx.test.rules",
-        "truth-prebuilt",
+        "truth",
         "androidx.test.core",
         "compatibility-device-util-axt",
     ],
diff --git a/tests/cts/TEST_MAPPING b/tests/cts/TEST_MAPPING
index 7f6b129..be2f725 100644
--- a/tests/cts/TEST_MAPPING
+++ b/tests/cts/TEST_MAPPING
@@ -3,10 +3,5 @@
     {
       "name": "CtsDeviceLockTestCases"
     }
-  ],
-  "postsubmit": [
-    {
-      "name": "DeviceLockUnitTests"
-    }
   ]
 }
diff --git a/tests/cts/src/com/android/cts/devicelock/DeviceLockManagerTest.java b/tests/cts/src/com/android/cts/devicelock/DeviceLockManagerTest.java
index 6aab946..d6bbb08 100644
--- a/tests/cts/src/com/android/cts/devicelock/DeviceLockManagerTest.java
+++ b/tests/cts/src/com/android/cts/devicelock/DeviceLockManagerTest.java
@@ -81,11 +81,11 @@
         SystemUtil.runShellCommandOrThrow(cmd);
     }
 
-    public ListenableFuture<Boolean> getIsDeviceLockedFuture() {
+    private ListenableFuture<Boolean> getIsDeviceLockedFuture() {
         return CallbackToFutureAdapter.getFuture(
                 completer -> {
                     mDeviceLockManager.isDeviceLocked(mExecutorService,
-                            new OutcomeReceiver<Boolean, Exception>() {
+                            new OutcomeReceiver<>() {
                                 @Override
                                 public void onResult(Boolean locked) {
                                     completer.set(locked);
@@ -101,11 +101,11 @@
                 });
     }
 
-    public ListenableFuture<Void> getLockDeviceFuture() {
+    private ListenableFuture<Void> getLockDeviceFuture() {
         return CallbackToFutureAdapter.getFuture(
                 completer -> {
                     mDeviceLockManager.lockDevice(mExecutorService,
-                            new OutcomeReceiver<Void, Exception>() {
+                            new OutcomeReceiver<>() {
                                 @Override
                                 public void onResult(Void result) {
                                     completer.set(null);
@@ -121,11 +121,11 @@
                 });
     }
 
-    public ListenableFuture<Void> getUnlockDeviceFuture() {
+    private ListenableFuture<Void> getUnlockDeviceFuture() {
         return CallbackToFutureAdapter.getFuture(
                 completer -> {
                     mDeviceLockManager.unlockDevice(mExecutorService,
-                            new OutcomeReceiver<Void, Exception>() {
+                            new OutcomeReceiver<>() {
                                 @Override
                                 public void onResult(Void result) {
                                     completer.set(null);
@@ -141,11 +141,11 @@
                 });
     }
 
-    public ListenableFuture<DeviceId> getDeviceIdFuture() {
+    private ListenableFuture<DeviceId> getDeviceIdFuture() {
         return CallbackToFutureAdapter.getFuture(
                 completer -> {
                     mDeviceLockManager.getDeviceId(mExecutorService,
-                            new OutcomeReceiver<DeviceId, Exception>() {
+                            new OutcomeReceiver<>() {
                                 @Override
                                 public void onResult(DeviceId deviceId) {
                                     completer.set(deviceId);
@@ -161,11 +161,11 @@
                 });
     }
 
-    public ListenableFuture<Map<Integer, String>> getKioskAppsFuture() {
+    private ListenableFuture<Map<Integer, String>> getKioskAppsFuture() {
         return CallbackToFutureAdapter.getFuture(
                 completer -> {
                     mDeviceLockManager.getKioskApps(mExecutorService,
-                            new OutcomeReceiver<Map<Integer, String>, Exception>() {
+                            new OutcomeReceiver<>() {
                                 @Override
                                 public void onResult(Map<Integer, String> result) {
                                     completer.set(result);
@@ -189,10 +189,8 @@
         Exception lockDeviceResponseException =
                 assertThrows(
                         ExecutionException.class,
-                        () -> {
-                            lockDeviceFuture.get(TIMEOUT, TimeUnit.SECONDS);
-                        });
-        assertThat(lockDeviceResponseException.getCause())
+                        () -> lockDeviceFuture.get(TIMEOUT, TimeUnit.SECONDS));
+        assertThat(lockDeviceResponseException).hasCauseThat()
                 .isInstanceOf(SecurityException.class);
     }
 
@@ -204,10 +202,8 @@
         Exception lockDeviceResponseException =
                 assertThrows(
                         ExecutionException.class,
-                        () -> {
-                            unlockDeviceFuture.get(TIMEOUT, TimeUnit.SECONDS);
-                        });
-        assertThat(lockDeviceResponseException.getCause())
+                        () -> unlockDeviceFuture.get(TIMEOUT, TimeUnit.SECONDS));
+        assertThat(lockDeviceResponseException).hasCauseThat()
                 .isInstanceOf(SecurityException.class);
     }
 
@@ -219,10 +215,8 @@
         Exception isDeviceLockedResponseException =
                 assertThrows(
                         ExecutionException.class,
-                        () -> {
-                            isDeviceLockedFuture.get(TIMEOUT, TimeUnit.SECONDS);
-                        });
-        assertThat(isDeviceLockedResponseException.getCause())
+                        () -> isDeviceLockedFuture.get(TIMEOUT, TimeUnit.SECONDS));
+        assertThat(isDeviceLockedResponseException).hasCauseThat()
                 .isInstanceOf(SecurityException.class);
     }
 
@@ -234,32 +228,26 @@
         Exception isDeviceLockedResponseException =
                 assertThrows(
                         ExecutionException.class,
-                        () -> {
-                            deviceIdFuture.get(TIMEOUT, TimeUnit.SECONDS);
-                        });
-        assertThat(isDeviceLockedResponseException.getCause())
+                        () -> deviceIdFuture.get(TIMEOUT, TimeUnit.SECONDS));
+        assertThat(isDeviceLockedResponseException).hasCauseThat()
                 .isInstanceOf(SecurityException.class);
     }
 
     @Test
     @ApiTest(
             apis = {
-                "android.devicelock.DeviceLockManager#isDeviceLocked",
-                "android.devicelock.DeviceLockManager#lockDevice",
-                "android.devicelock.DeviceLockManager#unlockDevice"
+                    "android.devicelock.DeviceLockManager#isDeviceLocked",
+                    "android.devicelock.DeviceLockManager#lockDevice",
+                    "android.devicelock.DeviceLockManager#unlockDevice"
             })
-    public void deviceShouldLockAndUnlock() throws InterruptedException, ExecutionException,
-            TimeoutException {
-
+    public void deviceShouldLockAndUnlock()
+            throws ExecutionException, InterruptedException, TimeoutException {
         try {
             addFinancedDeviceKioskRole();
 
-            boolean locked = getIsDeviceLockedFuture().get(TIMEOUT, TimeUnit.SECONDS);
-            assertThat(locked).isFalse();
-
             getLockDeviceFuture().get(TIMEOUT, TimeUnit.SECONDS);
 
-            locked = getIsDeviceLockedFuture().get(TIMEOUT, TimeUnit.SECONDS);
+            boolean locked = getIsDeviceLockedFuture().get(TIMEOUT, TimeUnit.SECONDS);
             assertThat(locked).isTrue();
 
             getUnlockDeviceFuture().get(TIMEOUT, TimeUnit.SECONDS);
@@ -273,8 +261,7 @@
 
     @Test
     @ApiTest(apis = {"android.devicelock.DeviceLockManager#getDeviceId"})
-    public void getDeviceIdShouldReturnAnId()
-            throws ExecutionException, InterruptedException, TimeoutException {
+    public void getDeviceIdShouldReturnAnId() {
         try {
             addFinancedDeviceKioskRole();
 
@@ -295,7 +282,7 @@
     @ApiTest(apis = {"android.devicelock.DeviceLockManager#getKioskApps"})
     public void getKioskApp_financedRoleHolderExists_returnsMapping()
             throws ExecutionException, InterruptedException, TimeoutException {
-        final ArrayMap expectedKioskApps = new ArrayMap<Integer, String>();
+        final ArrayMap<Integer, String> expectedKioskApps = new ArrayMap<>();
         expectedKioskApps.put(
                 DeviceLockManager.DEVICE_LOCK_ROLE_FINANCING, mContext.getPackageName());
 
@@ -317,14 +304,4 @@
         Map<Integer, String> kioskAppsMap = getKioskAppsFuture().get(TIMEOUT, TimeUnit.SECONDS);
         assertThat(kioskAppsMap).isEmpty();
     }
-
-    private static void adoptShellPermissions() {
-        InstrumentationRegistry
-                .getInstrumentation().getUiAutomation().adoptShellPermissionIdentity();
-    }
-
-    private static void dropShellPermissions() {
-        InstrumentationRegistry
-                .getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
-    }
 }
diff --git a/tests/unittests/Android.bp b/tests/unittests/Android.bp
index a5768ec..4e08acc 100644
--- a/tests/unittests/Android.bp
+++ b/tests/unittests/Android.bp
@@ -15,31 +15,29 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-android_test {
+android_app {
+    name: "DeviceLockTestApp",
+    platform_apis: true,
+    srcs: [],
+}
+
+android_robolectric_test {
     name: "DeviceLockUnitTests",
     srcs: [
         "src/**/*.java",
         ":framework-devicelock-sources",
     ],
+    java_resource_dirs: ["config"],
     static_libs: [
         "service-devicelock",
-        "services.core",
+        "androidx.test.core",
         "androidx.test.runner",
-        "mockito-target-extended-minus-junit4",
-        "truth-prebuilt",
+        "mockito-robolectric-prebuilt",
+        "truth",
     ],
     libs: [
-        "android.test.mock",
-        "android.test.base",
-        "android.test.runner",
         "framework-annotations-lib",
     ],
-    jni_libs: [
-        // Required for ExtendedMockito
-        "libdexmakerjvmtiagent",
-        "libstaticjvmtiagent",
-    ],
-    compile_multilib: "both",
-    sdk_version: "module_current",
-    test_suites: ["general-tests"],
+    instrumentation_for: "DeviceLockTestApp",
+    upstream: true,
 }
diff --git a/tests/unittests/AndroidManifest.xml b/tests/unittests/AndroidManifest.xml
index fae165e..a414e38 100644
--- a/tests/unittests/AndroidManifest.xml
+++ b/tests/unittests/AndroidManifest.xml
@@ -15,14 +15,6 @@
   ~ limitations under the License.
   -->
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.server.devicelock.tests" >
-
-    <application android:debuggable="true">
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.server.devicelock.tests"
-                     android:label="Device Lock unit tests"/>
+<manifest package="com.android.server.devicelock.tests" >
+    <application/>
 </manifest>
diff --git a/tests/unittests/config/robolectric.properties b/tests/unittests/config/robolectric.properties
new file mode 100644
index 0000000..f814535
--- /dev/null
+++ b/tests/unittests/config/robolectric.properties
@@ -0,0 +1,16 @@
+#
+# Copyright (C) 2023 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.
+#
+sdk=NEWEST_SDK
diff --git a/tests/unittests/src/com/android/server/devicelock/DeviceLockServiceImplTest.java b/tests/unittests/src/com/android/server/devicelock/DeviceLockServiceImplTest.java
new file mode 100644
index 0000000..7f7b0ac
--- /dev/null
+++ b/tests/unittests/src/com/android/server/devicelock/DeviceLockServiceImplTest.java
@@ -0,0 +1,329 @@
+/*
+ * 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 com.android.server.devicelock;
+
+import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION;
+import static android.devicelock.DeviceId.DEVICE_ID_TYPE_IMEI;
+import static android.devicelock.DeviceId.DEVICE_ID_TYPE_MEID;
+import static android.devicelock.IDeviceLockService.KEY_REMOTE_CALLBACK_RESULT;
+
+import static com.android.server.devicelock.DeviceLockControllerPackageUtils.SERVICE_ACTION;
+import static com.android.server.devicelock.DeviceLockServiceImpl.MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER;
+import static com.android.server.devicelock.DeviceLockServiceImpl.OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION;
+import static com.android.server.devicelock.DeviceLockServiceImpl.OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS;
+import static com.android.server.devicelock.DeviceLockServiceImpl.OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS;
+import static com.android.server.devicelock.TestUtils.eventually;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.AppOpsManager;
+import android.app.Application;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.devicelock.IGetDeviceIdCallback;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.PowerExemptionManager;
+import android.os.Process;
+import android.os.RemoteCallback;
+import android.telephony.TelephonyManager;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.devicelockcontroller.IDeviceLockControllerService;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowAppOpsManager;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowPackageManager;
+import org.robolectric.shadows.ShadowTelephonyManager;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Tests for {@link com.android.server.devicelock.DeviceLockServiceImpl}.
+ */
+@RunWith(RobolectricTestRunner.class)
+public final class DeviceLockServiceImplTest {
+    private static final String DLC_PACKAGE_NAME = "test.package";
+
+    private static final String DLC_SERVICE_NAME = "test.service";
+
+    private static final long ONE_SEC_MILLIS = 1000;
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    private Context mContext;
+    private ShadowTelephonyManager mShadowTelephonyManager;
+    private ShadowAppOpsManager mShadowAppOpsManager;
+
+    @Mock
+    private IDeviceLockControllerService mDeviceLockControllerService;
+    @Mock
+    private PowerExemptionManager mPowerExemptionManager;
+
+    private ShadowApplication mShadowApplication;
+
+    private DeviceLockServiceImpl mService;
+
+    @Before
+    public void setup() {
+        mContext = ApplicationProvider.getApplicationContext();
+        mShadowApplication = shadowOf((Application) mContext);
+        mShadowApplication.grantPermissions(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER);
+        mShadowApplication.setSystemService(
+                mContext.getSystemServiceName(PowerExemptionManager.class),
+                mPowerExemptionManager);
+
+        PackageManager packageManager = mContext.getPackageManager();
+        ShadowPackageManager shadowPackageManager = shadowOf(packageManager);
+        shadowPackageManager.setPackagesForUid(Process.myUid(),
+                new String[]{mContext.getPackageName()});
+
+        PackageInfo dlcPackageInfo = new PackageInfo();
+        dlcPackageInfo.packageName = DLC_PACKAGE_NAME;
+        shadowPackageManager.installPackage(dlcPackageInfo);
+
+        Intent intent = new Intent(SERVICE_ACTION);
+        ResolveInfo resolveInfo = makeDlcResolveInfo();
+        shadowPackageManager.addResolveInfoForIntent(intent, resolveInfo);
+
+        TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+        mShadowTelephonyManager = shadowOf(telephonyManager);
+
+        mShadowAppOpsManager = shadowOf(mContext.getSystemService(AppOpsManager.class));
+
+        mService = new DeviceLockServiceImpl(mContext, telephonyManager);
+    }
+
+    @Test
+    public void getDeviceId_withIMEIType_shouldReturnIMEI() throws Exception {
+        // GIVEN an IMEI registered in telephony manager
+        final String testImei = "983402979622353";
+        mShadowTelephonyManager.setActiveModemCount(1);
+        mShadowTelephonyManager.setImei(/* slotIndex= */ 0, testImei);
+
+        // GIVEN a successful service call to DLC app
+        doAnswer((Answer<Void>) invocation -> {
+            RemoteCallback callback = invocation.getArgument(0);
+            Bundle bundle = new Bundle();
+            bundle.putString(IDeviceLockControllerService.KEY_RESULT, testImei);
+            callback.sendResult(bundle);
+            return null;
+        }).when(mDeviceLockControllerService).getDeviceIdentifier(any(RemoteCallback.class));
+
+        IGetDeviceIdCallback mockCallback = mock(IGetDeviceIdCallback.class);
+
+        // WHEN the device id is requested with the IMEI device type
+        mService.getDeviceId(mockCallback, 1 << DEVICE_ID_TYPE_IMEI);
+        waitUntilConnected();
+
+        // THEN the IMEI id is received
+        verify(mockCallback, timeout(ONE_SEC_MILLIS)).onDeviceIdReceived(
+                eq(DEVICE_ID_TYPE_IMEI), eq(testImei));
+    }
+
+    @Test
+    public void getDeviceId_withMEIDType_shouldReturnMEID() throws Exception {
+        // GIVEN an MEID registered in telephony manager
+        final String testMeid = "354403064522046";
+        mShadowTelephonyManager.setActiveModemCount(1);
+        mShadowTelephonyManager.setMeid(/* slotIndex= */ 0, testMeid);
+
+        // GIVEN a successful service call to DLC app
+        doAnswer((Answer<Void>) invocation -> {
+            RemoteCallback callback = invocation.getArgument(0);
+            Bundle bundle = new Bundle();
+            bundle.putString(IDeviceLockControllerService.KEY_RESULT, testMeid);
+            callback.sendResult(bundle);
+            return null;
+        }).when(mDeviceLockControllerService).getDeviceIdentifier(any(RemoteCallback.class));
+
+        IGetDeviceIdCallback mockCallback = mock(IGetDeviceIdCallback.class);
+
+        // WHEN the device id is requested with the MEID device type
+        mService.getDeviceId(mockCallback, 1 << DEVICE_ID_TYPE_MEID);
+        waitUntilConnected();
+
+        // THEN the MEID id is received
+        verify(mockCallback, timeout(ONE_SEC_MILLIS)).onDeviceIdReceived(
+                eq(DEVICE_ID_TYPE_MEID), eq(testMeid));
+    }
+
+    @Test
+    public void setCallerAllowedToSendUndismissibleNotifications_trueAllowsAppOp() {
+        final AtomicBoolean succeeded = new AtomicBoolean(false);
+        RemoteCallback callback = new RemoteCallback(result -> {
+            succeeded.set(result.getBoolean(KEY_REMOTE_CALLBACK_RESULT));
+        });
+        mService.setCallerAllowedToSendUndismissibleNotifications(true, callback);
+
+        assertThat(succeeded.get()).isTrue();
+        final int opMode = mShadowAppOpsManager.unsafeCheckOpNoThrow(
+                OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS,
+                Process.myUid(),
+                DLC_PACKAGE_NAME);
+        assertThat(opMode).isEqualTo(AppOpsManager.MODE_ALLOWED);
+    }
+
+    @Test
+    public void setCallerAllowedToSendUndismissibleNotifications_falseDisallowsAppOp() {
+        final AtomicBoolean succeeded = new AtomicBoolean(false);
+        RemoteCallback callback = new RemoteCallback(result -> {
+            succeeded.set(result.getBoolean(KEY_REMOTE_CALLBACK_RESULT));
+        });
+        mService.setCallerAllowedToSendUndismissibleNotifications(false, callback);
+
+        assertThat(succeeded.get()).isTrue();
+        final int opMode = mShadowAppOpsManager.unsafeCheckOpNoThrow(
+                OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS,
+                Process.myUid(),
+                DLC_PACKAGE_NAME);
+        assertThat(opMode).isEqualTo(AppOpsManager.MODE_DEFAULT);
+    }
+
+    @Test
+    public void setCallerExemptFromActivityBgStartRestrictionState_trueAllowsAppOp() {
+        final AtomicBoolean succeeded = new AtomicBoolean(false);
+        RemoteCallback callback = new RemoteCallback(result -> {
+            succeeded.set(result.getBoolean(KEY_REMOTE_CALLBACK_RESULT));
+        });
+        mService.setCallerExemptFromActivityBgStartRestrictionState(true, callback);
+
+        assertThat(succeeded.get()).isTrue();
+        final int opMode = mShadowAppOpsManager.unsafeCheckOpNoThrow(
+                OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
+                Process.myUid(),
+                DLC_PACKAGE_NAME);
+        assertThat(opMode).isEqualTo(AppOpsManager.MODE_ALLOWED);
+    }
+
+    @Test
+    public void setCallerExemptFromActivityBgStartRestrictionState_falseDisallowsAppOp() {
+        final AtomicBoolean succeeded = new AtomicBoolean(false);
+        RemoteCallback callback = new RemoteCallback(result -> {
+            succeeded.set(result.getBoolean(KEY_REMOTE_CALLBACK_RESULT));
+        });
+        mService.setCallerExemptFromActivityBgStartRestrictionState(false, callback);
+
+        assertThat(succeeded.get()).isTrue();
+        final int opMode = mShadowAppOpsManager.unsafeCheckOpNoThrow(
+                OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
+                Process.myUid(),
+                DLC_PACKAGE_NAME);
+        assertThat(opMode).isEqualTo(AppOpsManager.MODE_DEFAULT);
+    }
+
+    @Test
+    public void setUidExemptFromRestrictionsState_trueAllowsAppOps() {
+        final AtomicBoolean succeeded = new AtomicBoolean(false);
+        RemoteCallback callback = new RemoteCallback(result -> {
+            succeeded.set(result.getBoolean(KEY_REMOTE_CALLBACK_RESULT));
+        });
+        mService.setUidExemptFromRestrictionsState(Process.myUid(), true, callback);
+
+        assertThat(succeeded.get()).isTrue();
+        final int hibernationOpMode = mShadowAppOpsManager.unsafeCheckOpNoThrow(
+                OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION,
+                Process.myUid(),
+                mContext.getPackageName());
+        assertThat(hibernationOpMode).isEqualTo(AppOpsManager.MODE_ALLOWED);
+        final int powerOpMode = mShadowAppOpsManager.unsafeCheckOpNoThrow(
+                OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
+                Process.myUid(),
+                mContext.getPackageName());
+        assertThat(powerOpMode).isEqualTo(AppOpsManager.MODE_ALLOWED);
+    }
+
+    @Test
+    public void setUidExemptFromRestrictionsState_falseDisallowsAppOps() {
+        final AtomicBoolean succeeded = new AtomicBoolean(false);
+        RemoteCallback callback = new RemoteCallback(result -> {
+            succeeded.set(result.getBoolean(KEY_REMOTE_CALLBACK_RESULT));
+        });
+        mService.setUidExemptFromRestrictionsState(Process.myUid(), false, callback);
+
+        assertThat(succeeded.get()).isTrue();
+        final int hibernationOpMode = mShadowAppOpsManager.unsafeCheckOpNoThrow(
+                OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION,
+                Process.myUid(),
+                mContext.getPackageName());
+        assertThat(hibernationOpMode).isEqualTo(AppOpsManager.MODE_DEFAULT);
+        final int powerOpMode = mShadowAppOpsManager.unsafeCheckOpNoThrow(
+                OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
+                Process.myUid(),
+                mContext.getPackageName());
+        assertThat(powerOpMode).isEqualTo(AppOpsManager.MODE_DEFAULT);
+    }
+
+    /**
+     * Make the resolve info for the DLC package.
+     */
+    private ResolveInfo makeDlcResolveInfo() {
+        ApplicationInfo appInfo = new ApplicationInfo();
+        appInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+        appInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.name = DLC_SERVICE_NAME;
+        serviceInfo.packageName = DLC_PACKAGE_NAME;
+        serviceInfo.applicationInfo = appInfo;
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.serviceInfo = serviceInfo;
+
+        return resolveInfo;
+    }
+
+    /**
+     * Set-up calls to mock the service being connected.
+     */
+    private void waitUntilConnected() {
+        eventually(() -> {
+            shadowOf(Looper.getMainLooper()).idle();
+            ServiceConnection connection = mShadowApplication.getBoundServiceConnections().get(0);
+            Binder binder = new Binder();
+            binder.attachInterface(mDeviceLockControllerService,
+                    IDeviceLockControllerService.class.getName());
+            connection.onServiceConnected(new ComponentName(DLC_PACKAGE_NAME, DLC_SERVICE_NAME),
+                    binder);
+        }, ONE_SEC_MILLIS);
+    }
+}
diff --git a/tests/unittests/src/com/android/server/devicelock/DeviceLockUnitTest.java b/tests/unittests/src/com/android/server/devicelock/DeviceLockUnitTest.java
deleted file mode 100644
index 1bf0558..0000000
--- a/tests/unittests/src/com/android/server/devicelock/DeviceLockUnitTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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 com.android.server.devicelock;
-
-import static android.devicelock.DeviceId.DEVICE_ID_TYPE_IMEI;
-import static android.devicelock.DeviceId.DEVICE_ID_TYPE_MEID;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.timeout;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.devicelock.IGetDeviceIdCallback;
-import android.telephony.TelephonyManager;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-
-/**
- * Tests for {@link com.android.server.devicelock.DeviceLockService}.
- */
-public class DeviceLockUnitTest {
-
-    private Context mMockContext;
-
-    @Mock
-    private PackageManager mPackageManager;
-
-    @Mock
-    private TelephonyManager mTelephonyManager;
-
-    private MockitoSession mSession;
-
-    private DeviceLockServiceImpl mService;
-
-    private static final long ONE_SEC_MILLIS = 1000;
-
-    @Before
-    public void setup() {
-        mSession = ExtendedMockito.mockitoSession().initMocks(this)
-                .strictness(Strictness.LENIENT)
-                .startMocking();
-        mMockContext = spy(InstrumentationRegistry.getInstrumentation().getContext());
-
-        doNothing().when(mMockContext).enforceCallingPermission(anyString(), anyString());
-
-        when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
-        when(mMockContext.getSystemService(TelephonyManager.class))
-                .thenReturn(mTelephonyManager);
-    }
-
-    @After
-    public void teardown() {
-        mSession.finishMocking();
-    }
-
-    /**
-     * Test IMEI for {@link com.android.server.devicelock.DeviceLockServiceImpl#getDeviceId}
-     */
-    @Test
-    public void getDeviceIdShouldReturnIMEI() {
-        final String testImei = "983402979622353";
-
-        mService = new DeviceLockServiceImpl(mMockContext);
-
-        when(mTelephonyManager.getImei()).thenReturn(testImei);
-
-        IGetDeviceIdCallback mockCallback = mock(IGetDeviceIdCallback.class);
-
-        mService.getDeviceId(mockCallback, 1 << DEVICE_ID_TYPE_IMEI);
-
-        try {
-            verify(mockCallback, timeout(ONE_SEC_MILLIS))
-                    .onDeviceIdReceived(eq(DEVICE_ID_TYPE_IMEI), eq(testImei));
-        } catch (Exception ex) {
-            // Should not happen.
-        }
-    }
-
-    /**
-     * Test MEID for {@link com.android.server.devicelock.DeviceLockServiceImpl#getDeviceId}
-     */
-    @Test
-    public void getDeviceIdShouldReturnMEID() {
-        final String testMeid = "354403064522046";
-
-        mService = new DeviceLockServiceImpl(mMockContext);
-
-        when(mTelephonyManager.getMeid()).thenReturn(testMeid);
-
-        IGetDeviceIdCallback mockCallback = mock(IGetDeviceIdCallback.class);
-
-        mService.getDeviceId(mockCallback, 1 << DEVICE_ID_TYPE_MEID);
-
-        try {
-            verify(mockCallback, timeout(1000))
-                    .onDeviceIdReceived(eq(DEVICE_ID_TYPE_MEID), eq(testMeid));
-        } catch (Exception ex) {
-            // Should not happen.
-        }
-    }
-}
diff --git a/tests/unittests/src/com/android/server/devicelock/TestUtils.java b/tests/unittests/src/com/android/server/devicelock/TestUtils.java
new file mode 100644
index 0000000..0c596e9
--- /dev/null
+++ b/tests/unittests/src/com/android/server/devicelock/TestUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.devicelock;
+
+import org.junit.function.ThrowingRunnable;
+import org.junit.runners.model.TestTimedOutException;
+
+/**
+ * Utils useful for testing
+ */
+final class TestUtils {
+    private TestUtils() {}
+
+    /**
+     * Make sure that a runnable eventually finishes without throwing an exception.
+     */
+    static void eventually(ThrowingRunnable r, long timeoutMillis) {
+        long start = System.currentTimeMillis();
+
+        while (true) {
+            try {
+                r.run();
+                return;
+            } catch (TestTimedOutException e) {
+                throw new RuntimeException(e);
+            } catch (Throwable e) {
+                if (System.currentTimeMillis() - start < timeoutMillis) {
+                    try {
+                        Thread.sleep(100);
+                    } catch (InterruptedException ignored) {
+                        throw new RuntimeException(e);
+                    }
+                } else {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+}