1 /* 2 * Copyright 2019, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.managedprovisioning.finalization; 18 19 import static com.android.managedprovisioning.finalization.FinalizationController.PROVISIONING_FINALIZED_RESULT_CHILD_ACTIVITY_LAUNCHED; 20 import static com.android.managedprovisioning.finalization.FinalizationController.PROVISIONING_FINALIZED_RESULT_NO_CHILD_ACTIVITY_LAUNCHED; 21 import static com.android.managedprovisioning.finalization.FinalizationController.ProvisioningFinalizedResult; 22 23 import android.app.Activity; 24 import android.os.Bundle; 25 import android.os.UserHandle; 26 27 import com.android.managedprovisioning.analytics.MetricsWriterFactory; 28 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker; 29 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences; 30 import com.android.managedprovisioning.common.PolicyComplianceUtils; 31 import com.android.managedprovisioning.common.ProvisionLogger; 32 import com.android.managedprovisioning.common.SettingsFacade; 33 import com.android.managedprovisioning.common.StartDpcInsideSuwServiceConnection; 34 import com.android.managedprovisioning.common.TransitionHelper; 35 import com.android.managedprovisioning.common.Utils; 36 import com.android.managedprovisioning.model.ProvisioningParams; 37 38 /** 39 * This controller is used to finalize managed provisioning before the end of Setup Wizard. 40 */ 41 public class FinalizationInsideSuwControllerLogic implements FinalizationControllerLogic { 42 private static final String START_DPC_SERVICE_STATE_KEY = "start_dpc_service_state"; 43 private static final String LAST_REQUEST_CODE_KEY = "last_request_code"; 44 45 private final Activity mActivity; 46 private final Utils mUtils; 47 private final PolicyComplianceUtils mPolicyComplianceUtils; 48 private final ProvisioningAnalyticsTracker mProvisioningAnalyticsTracker; 49 private final TransitionHelper mTransitionHelper; 50 private StartDpcInsideSuwServiceConnection mStartDpcInsideSuwServiceConnection; 51 private int mLastRequestCode = 0; 52 FinalizationInsideSuwControllerLogic(Activity activity)53 public FinalizationInsideSuwControllerLogic(Activity activity) { 54 this(activity, new Utils(), new PolicyComplianceUtils(), 55 new ProvisioningAnalyticsTracker( 56 MetricsWriterFactory.getMetricsWriter(activity, new SettingsFacade()), 57 new ManagedProvisioningSharedPreferences(activity)), 58 new TransitionHelper()); 59 } 60 FinalizationInsideSuwControllerLogic(Activity activity, Utils utils, PolicyComplianceUtils policyComplianceUtils, ProvisioningAnalyticsTracker provisioningAnalyticsTracker, TransitionHelper transitionHelper)61 public FinalizationInsideSuwControllerLogic(Activity activity, Utils utils, 62 PolicyComplianceUtils policyComplianceUtils, 63 ProvisioningAnalyticsTracker provisioningAnalyticsTracker, 64 TransitionHelper transitionHelper) { 65 mActivity = activity; 66 mUtils = utils; 67 mPolicyComplianceUtils = policyComplianceUtils; 68 mProvisioningAnalyticsTracker = provisioningAnalyticsTracker; 69 mTransitionHelper = transitionHelper; 70 } 71 72 @Override notifyDpcManagedProfile( ProvisioningParams params, int requestCode)73 public @ProvisioningFinalizedResult int notifyDpcManagedProfile( 74 ProvisioningParams params, int requestCode) { 75 return startPolicyComplianceActivityForResultIfResolved(params, requestCode); 76 } 77 78 @Override notifyDpcManagedDeviceOrUser( ProvisioningParams params, int requestCode)79 public @ProvisioningFinalizedResult int notifyDpcManagedDeviceOrUser( 80 ProvisioningParams params, int requestCode) { 81 return startPolicyComplianceActivityForResultIfResolved(params, requestCode); 82 } 83 84 @Override shouldFinalizePrimaryProfile(ProvisioningParams params)85 public boolean shouldFinalizePrimaryProfile(ProvisioningParams params) { 86 return true; 87 } 88 89 @Override saveInstanceState(Bundle outState)90 public void saveInstanceState(Bundle outState) { 91 outState.putInt(LAST_REQUEST_CODE_KEY, mLastRequestCode); 92 93 if (mStartDpcInsideSuwServiceConnection != null) { 94 final Bundle startDpcServiceState = new Bundle(); 95 outState.putBundle(START_DPC_SERVICE_STATE_KEY, startDpcServiceState); 96 mStartDpcInsideSuwServiceConnection.saveInstanceState(startDpcServiceState); 97 } 98 } 99 100 @Override restoreInstanceState(Bundle savedInstanceState, ProvisioningParams params)101 public void restoreInstanceState(Bundle savedInstanceState, ProvisioningParams params) { 102 mLastRequestCode = savedInstanceState.getInt(LAST_REQUEST_CODE_KEY); 103 104 final Bundle startDpcServiceState = 105 savedInstanceState.getBundle(START_DPC_SERVICE_STATE_KEY); 106 107 if (startDpcServiceState != null) { 108 mStartDpcInsideSuwServiceConnection = new StartDpcInsideSuwServiceConnection( 109 mActivity, 110 startDpcServiceState, 111 getDpcIntentSender(params, mLastRequestCode)); 112 } 113 } 114 115 @Override activityDestroyed(boolean isFinishing)116 public void activityDestroyed(boolean isFinishing) { 117 if (mStartDpcInsideSuwServiceConnection != null) { 118 if (isFinishing) { 119 mStartDpcInsideSuwServiceConnection.dpcFinished(); 120 } 121 122 mStartDpcInsideSuwServiceConnection.unbind(mActivity); 123 124 if (isFinishing) { 125 mStartDpcInsideSuwServiceConnection = null; 126 } 127 } 128 } 129 startPolicyComplianceActivityForResultIfResolved( ProvisioningParams params, int requestCode)130 private @ProvisioningFinalizedResult int startPolicyComplianceActivityForResultIfResolved( 131 ProvisioningParams params, int requestCode) { 132 if (!mPolicyComplianceUtils.isPolicyComplianceActivityResolvableForManagedUser( 133 mActivity, params, mUtils)) { 134 return PROVISIONING_FINALIZED_RESULT_NO_CHILD_ACTIVITY_LAUNCHED; 135 } 136 137 if (mStartDpcInsideSuwServiceConnection != null) { 138 ProvisionLogger.logw("Attempted to start DPC again before result received - ignoring"); 139 return PROVISIONING_FINALIZED_RESULT_NO_CHILD_ACTIVITY_LAUNCHED; 140 } 141 142 // Connect to a SUW service to disable network intent interception before starting the DPC. 143 mStartDpcInsideSuwServiceConnection = new StartDpcInsideSuwServiceConnection(); 144 mStartDpcInsideSuwServiceConnection.triggerDpcStart(mActivity, 145 getDpcIntentSender(params, requestCode)); 146 147 mLastRequestCode = requestCode; 148 149 return PROVISIONING_FINALIZED_RESULT_CHILD_ACTIVITY_LAUNCHED; 150 } 151 getDpcIntentSender(ProvisioningParams params, int requestCode)152 private Runnable getDpcIntentSender(ProvisioningParams params, int requestCode) { 153 return () -> 154 mPolicyComplianceUtils.startPolicyComplianceActivityForResultIfResolved( 155 mActivity, params, requestCode, mUtils, mProvisioningAnalyticsTracker, 156 mTransitionHelper); 157 } 158 } 159