blob: eaf02cc5d7eb75976495256df6f1d27c380d7b08 [file] [log] [blame]
/*
* Copyright 2019, 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.managedprovisioning.finalization;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
import static com.android.internal.util.Preconditions.checkNotNull;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.UserHandle;
import android.os.UserManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.managedprovisioning.common.ProvisionLogger;
import com.android.managedprovisioning.common.SettingsFacade;
import com.android.managedprovisioning.common.Utils;
import com.android.managedprovisioning.model.ProvisioningParams;
/**
* This controller is invoked, via a call to
* {@link #deviceManagementEstablished(ProvisioningParams)}, immediately after a Device Owner or
* Profile Owner is provisioned. If the user is creating a managed profile on a device post-Setup
* Wizard, then we immediately start the DPC app and set the provisioning state to finalized, so no
* further finalization calls are necessary. On the other hand, if we are still inside of Setup
* Wizard, provisioning needs to be finalized after this using an instance of
* {@link FinalizationController}.
*/
public final class PreFinalizationController {
private final Activity mActivity;
private final Utils mUtils;
private final SettingsFacade mSettingsFacade;
private final UserProvisioningStateHelper mUserProvisioningStateHelper;
private final ProvisioningParamsUtils mProvisioningParamsUtils;
private final SendDpcBroadcastServiceUtils mSendDpcBroadcastServiceUtils;
public PreFinalizationController(Activity activity,
UserProvisioningStateHelper userProvisioningStateHelper) {
this(
activity,
new Utils(),
new SettingsFacade(),
userProvisioningStateHelper,
new ProvisioningParamsUtils(),
new SendDpcBroadcastServiceUtils());
}
public PreFinalizationController(Activity activity) {
this(
activity,
new Utils(),
new SettingsFacade(),
new UserProvisioningStateHelper(activity),
new ProvisioningParamsUtils(),
new SendDpcBroadcastServiceUtils());
}
@VisibleForTesting
PreFinalizationController(Activity activity,
Utils utils,
SettingsFacade settingsFacade,
UserProvisioningStateHelper helper,
ProvisioningParamsUtils provisioningParamsUtils,
SendDpcBroadcastServiceUtils sendDpcBroadcastServiceUtils) {
mActivity = checkNotNull(activity);
mUtils = checkNotNull(utils);
mSettingsFacade = checkNotNull(settingsFacade);
mUserProvisioningStateHelper = checkNotNull(helper);
mProvisioningParamsUtils = provisioningParamsUtils;
mSendDpcBroadcastServiceUtils = sendDpcBroadcastServiceUtils;
}
/**
* This method is invoked after a Device Owner or Profile Owner has been set up.
*
* <p>If provisioning happens as part of SUW, we rely on an instance of
* FinalizationControllerBase to be invoked later on. Otherwise, this method will finalize
* provisioning. If called after SUW, this method notifies the DPC about the completed
* provisioning; otherwise, it stores the provisioning params for later digestion.</p>
*
* <p>Note that fully managed device provisioning is only possible during SUW.
*
* @param params the provisioning params
*/
public final void deviceManagementEstablished(ProvisioningParams params) {
if (!mUserProvisioningStateHelper.isStateUnmanagedOrFinalized()) {
// In any other state than STATE_USER_UNMANAGED and STATE_USER_SETUP_FINALIZED, we've
// already run this method, so don't do anything.
// STATE_USER_SETUP_FINALIZED can occur here if a managed profile is provisioned on a
// device owner device.
ProvisionLogger.logw("deviceManagementEstablished called, but state is not finalized "
+ "or unmanaged");
return;
}
mUserProvisioningStateHelper.markUserProvisioningStateInitiallyDone(params);
if (ACTION_PROVISION_MANAGED_PROFILE.equals(params.provisioningAction)) {
if (params.isOrganizationOwnedProvisioning) {
markIsProfileOwnerOnOrganizationOwnedDevice();
restrictRemovalOfManagedProfile();
}
if (!mSettingsFacade.isDuringSetupWizard(mActivity)) {
// If a managed profile was provisioned after SUW, notify the DPC straight away.
mSendDpcBroadcastServiceUtils.startSendDpcBroadcastService(mActivity, params);
}
}
if (mSettingsFacade.isDuringSetupWizard(mActivity)) {
// Store the information and wait for provisioningFinalized to be called
storeProvisioningParams(params);
}
}
private void restrictRemovalOfManagedProfile() {
final UserManager userManager = UserManager.get(mActivity);
userManager.setUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, true);
}
private void markIsProfileOwnerOnOrganizationOwnedDevice() {
final DevicePolicyManager dpm = mActivity.getSystemService(DevicePolicyManager.class);
final int managedProfileUserId = mUtils.getManagedProfile(mActivity).getIdentifier();
final ComponentName admin = dpm.getProfileOwnerAsUser(managedProfileUserId);
if (admin != null) {
try {
final Context profileContext = mActivity.createPackageContextAsUser(
mActivity.getPackageName(), 0 /* flags */,
UserHandle.of(managedProfileUserId));
final DevicePolicyManager profileDpm =
profileContext.getSystemService(DevicePolicyManager.class);
profileDpm.markProfileOwnerOnOrganizationOwnedDevice(admin);
} catch (NameNotFoundException e) {
ProvisionLogger.logw("Error setting access to Device IDs: " + e.getMessage());
}
}
}
private void storeProvisioningParams(ProvisioningParams params) {
params.save(mProvisioningParamsUtils.getProvisioningParamsFile(mActivity));
}
}