/* * Copyright 2017, 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.preprovisioning.terms; import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DISCLAIMER_CONTENT; import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DISCLAIMER_HEADER; import static android.content.pm.PackageManager.GET_META_DATA; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import android.annotation.IntDef; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import com.android.managedprovisioning.R; import com.android.managedprovisioning.common.ProvisionLogger; import com.android.managedprovisioning.common.StoreUtils; import com.android.managedprovisioning.common.Utils; import com.android.managedprovisioning.model.DisclaimersParam; import com.android.managedprovisioning.model.ProvisioningParams; import java.io.File; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** * Sources all available {@link TermsDocument}s: * */ public class TermsProvider { private final Context mContext; private final StoreUtils.TextFileReader mTextFileReader; private final Utils mUtils; /** * Sources all available {@link TermsDocument}s: * */ public TermsProvider(Context context, StoreUtils.TextFileReader textFileReader, Utils utils) { mContext = context; mTextFileReader = textFileReader; mUtils = utils; } /** * Sources all available {@link TermsDocument}s: * */ public List getTerms(ProvisioningParams params, @Flags int flags) { List result = new ArrayList<>(); int provisioningCase = determineProvisioningCase(params); if ((flags & Flags.SKIP_GENERAL_DISCLAIMER) == 0) { result.add(getGeneralDisclaimer(provisioningCase)); } if (provisioningCase == ProvisioningCase.DEVICE_OWNER) { result.addAll(getSystemAppTerms()); } result.addAll(getExtraDisclaimers(params)); return result.stream().filter(Objects::nonNull).collect(Collectors.toList()); } private int determineProvisioningCase(ProvisioningParams params) { if (mUtils.isDeviceOwnerAction(params.provisioningAction)) { return ProvisioningCase.DEVICE_OWNER; } // TODO: move somewhere more general boolean isComp = ((DevicePolicyManager) mContext .getSystemService(Context.DEVICE_POLICY_SERVICE)).isDeviceManaged(); return isComp ? ProvisioningCase.COMP : ProvisioningCase.PROFILE_OWNER; } private TermsDocument getGeneralDisclaimer(@ProvisioningCase int provisioningCase) { String heading = mContext.getString(provisioningCase == ProvisioningCase.PROFILE_OWNER ? R.string.work_profile_info : R.string.managed_device_info); String content = mContext.getString(provisioningCase == ProvisioningCase.PROFILE_OWNER ? R.string.admin_has_ability_to_monitor_profile : R.string.admin_has_ability_to_monitor_device); return TermsDocument.createInstance(heading, content); } private List getSystemAppTerms() { List terms = new ArrayList<>(); List appInfos = mContext.getPackageManager().getInstalledApplications( MATCH_SYSTEM_ONLY | GET_META_DATA); for (ApplicationInfo appInfo : appInfos) { String header = getStringMetaData(appInfo, EXTRA_PROVISIONING_DISCLAIMER_HEADER); String content = getStringMetaData(appInfo, EXTRA_PROVISIONING_DISCLAIMER_CONTENT); if (header != null && content != null) { terms.add(TermsDocument.createInstance(header, content)); } } return terms; } private List getExtraDisclaimers(ProvisioningParams params) { List result = new ArrayList<>(); DisclaimersParam.Disclaimer[] disclaimers = params.disclaimersParam == null ? null : params.disclaimersParam.mDisclaimers; if (disclaimers != null) { for (DisclaimersParam.Disclaimer disclaimer : disclaimers) { try { String htmlContent = mTextFileReader.read( new File(disclaimer.mContentFilePath)); result.add(TermsDocument.createInstance(disclaimer.mHeader, htmlContent)); } catch (IOException e) { ProvisionLogger.loge("Failed to read disclaimer", e); } } } return result; } private String getStringMetaData(ApplicationInfo appInfo, String key) { if (appInfo.metaData != null) { int resId = appInfo.metaData.getInt(key); if (resId != 0) { try { return mContext.getPackageManager().getResourcesForApplication( appInfo).getString(resId); } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { ProvisionLogger.loge("NameNotFoundException", e); } } } return null; } // TODO: move somewhere more general @IntDef(value = { ProvisioningCase.PROFILE_OWNER, ProvisioningCase.DEVICE_OWNER, ProvisioningCase.COMP, }) @Retention(RetentionPolicy.SOURCE) private @interface ProvisioningCase { int PROFILE_OWNER = 1; int DEVICE_OWNER = 2; int COMP = 4; } @IntDef(flag = true, value = { Flags.SKIP_GENERAL_DISCLAIMER, }) @Retention(RetentionPolicy.SOURCE) public @interface Flags { int SKIP_GENERAL_DISCLAIMER = 1; } }