Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73de23bc authored by Kholoud Mohamed's avatar Kholoud Mohamed
Browse files

Add lockTask policy definition

Bug: 232918480
Test: manual
Change-Id: Ifbaf0f19d018fa9aadcbab3dd6c8eefe8d79f492
parent 61b9bf9c
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -3936,6 +3936,12 @@ public class DevicePolicyManager {
        return PERMISSION_GRANT_POLICY_KEY + "_" + packageName + "_" + permission;
    }
    // TODO: Expose this as SystemAPI once we add the query API
    /**
     * @hide
     */
    public static final String LOCK_TASK_POLICY = "lockTask";
    /**
     * This object is a single place to tack on invalidation and disable calls.  All
     * binder caches in this class derive from this Config, so all can be invalidated or
+53 −52
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ import android.util.DebugUtils;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
import android.view.IWindowManager;
@@ -2878,32 +2879,34 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        policy.validatePasswordOwner();
        updateMaximumTimeToLockLocked(userHandle);
        updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
        updateLockTaskPackagesLocked(mContext, policy.mLockTaskPackages, userHandle);
        updateLockTaskFeaturesLocked(policy.mLockTaskFeatures, userHandle);
        if (policy.mStatusBarDisabled) {
            setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle);
        }
    }
    private void updateLockTaskPackagesLocked(List<String> packages, int userId) {
        String[] packagesArray = null;
    static void updateLockTaskPackagesLocked(Context context, List<String> packages, int userId) {
        Binder.withCleanCallingIdentity(() -> {
            String[] packagesArray = null;
            if (!packages.isEmpty()) {
                // When adding packages, we need to include the exempt apps so they can still be
            // launched (ideally we should use a different AM API as these apps don't need to use
            // lock-task mode).
            // They're not added when the packages is empty though, as in that case we're disabling
            // lock-task mode.
            List<String> exemptApps = listPolicyExemptAppsUnchecked();
                // launched (ideally we should use a different AM API as these apps don't need to
                // use lock-task mode).
                // They're not added when the packages is empty though, as in that case we're
                // disabling lock-task mode.
                List<String> exemptApps = listPolicyExemptAppsUnchecked(context);
                if (!exemptApps.isEmpty()) {
                // TODO(b/175377361): add unit test to verify it (cannot be CTS because the policy-
                // -exempt apps are provided by OEM and the test would have no control over it) once
                // tests are migrated to the new infra-structure
                    // TODO(b/175377361): add unit test to verify it (cannot be CTS because the
                    //  policy-exempt apps are provided by OEM and the test would have no control
                    //  over it) once tests are migrated to the new infra-structure
                    HashSet<String> updatedPackages = new HashSet<>(packages);
                    updatedPackages.addAll(exemptApps);
                    if (VERBOSE_LOG) {
                    Slogf.v(LOG_TAG, "added %d policy-exempt apps to %d lock task packages. Final "
                            + "list: %s", exemptApps.size(), packages.size(), updatedPackages);
                        Slogf.v(LOG_TAG, "added %d policy-exempt apps to %d lock task "
                                + "packages. Final list: %s",
                                exemptApps.size(), packages.size(), updatedPackages);
                    }
                    packagesArray = updatedPackages.toArray(new String[updatedPackages.size()]);
                }
@@ -2912,26 +2915,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            if (packagesArray == null) {
                packagesArray = packages.toArray(new String[packages.size()]);
            }
        long ident = mInjector.binderClearCallingIdentity();
            try {
            mInjector.getIActivityManager().updateLockTaskPackages(userId, packagesArray);
                ActivityManager.getService().updateLockTaskPackages(userId, packagesArray);
            } catch (RemoteException e) {
            // Not gonna happen.
        } finally {
            mInjector.binderRestoreCallingIdentity(ident);
                // Shouldn't happen.
                Slog.wtf(LOG_TAG, "Remote Exception: ", e);
            }
        });
    }
    private void updateLockTaskFeaturesLocked(int flags, int userId) {
        long ident = mInjector.binderClearCallingIdentity();
    static void updateLockTaskFeaturesLocked(int flags, int userId) {
        Binder.withCleanCallingIdentity(() -> {
            try {
            mInjector.getIActivityTaskManager().updateLockTaskFeatures(userId, flags);
                ActivityTaskManager.getService().updateLockTaskFeatures(userId, flags);
            } catch (RemoteException e) {
            // Not gonna happen.
        } finally {
            mInjector.binderRestoreCallingIdentity(ident);
                // Shouldn't happen.
                Slog.wtf(LOG_TAG, "Remote Exception: ", e);
            }
        });
    }
    static void validateQualityConstant(int quality) {
@@ -8941,7 +8942,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        policy.mUserProvisioningState = DevicePolicyManager.STATE_USER_UNMANAGED;
        policy.mAffiliationIds.clear();
        policy.mLockTaskPackages.clear();
        updateLockTaskPackagesLocked(policy.mLockTaskPackages, userId);
        updateLockTaskPackagesLocked(mContext, policy.mLockTaskPackages, userId);
        policy.mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
        saveSettingsLocked(userId);
@@ -11217,7 +11218,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    private String[] populateNonExemptAndExemptFromPolicyApps(String[] packageNames,
            Set<String> outputExemptApps) {
        Preconditions.checkArgument(outputExemptApps.isEmpty(), "outputExemptApps is not empty");
        List<String> exemptAppsList = listPolicyExemptAppsUnchecked();
        List<String> exemptAppsList = listPolicyExemptAppsUnchecked(mContext);
        if (exemptAppsList.isEmpty()) {
            return packageNames;
        }
@@ -11330,16 +11331,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS)
                        || isDefaultDeviceOwner(caller) || isProfileOwner(caller));
        return listPolicyExemptAppsUnchecked();
        return listPolicyExemptAppsUnchecked(mContext);
    }
    private List<String> listPolicyExemptAppsUnchecked() {
    private static List<String> listPolicyExemptAppsUnchecked(Context context) {
        // TODO(b/181238156): decide whether it should only list the apps set by the resources,
        // or also the "critical" apps defined by PersonalAppsSuspensionHelper (like SMS app).
        // If it's the latter, refactor PersonalAppsSuspensionHelper so it (or a superclass) takes
        // the resources on constructor.
        String[] core = mContext.getResources().getStringArray(R.array.policy_exempt_apps);
        String[] vendor = mContext.getResources().getStringArray(R.array.vendor_policy_exempt_apps);
        String[] core = context.getResources().getStringArray(R.array.policy_exempt_apps);
        String[] vendor = context.getResources().getStringArray(R.array.vendor_policy_exempt_apps);
        int size = core.length + vendor.length;
        Set<String> apps = new ArraySet<>(size);
@@ -11516,7 +11517,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS)));
        List<String> exemptApps = listPolicyExemptAppsUnchecked();
        List<String> exemptApps = listPolicyExemptAppsUnchecked(mContext);
        if (exemptApps.contains(packageName)) {
            Slogf.d(LOG_TAG, "setApplicationHidden(): ignoring %s as it's on policy-exempt list",
                    packageName);
@@ -12191,7 +12192,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        // Store the settings persistently.
        saveSettingsLocked(userHandle);
        updateLockTaskPackagesLocked(packages, userHandle);
        updateLockTaskPackagesLocked(mContext, packages, userHandle);
    }
    @Override
@@ -12210,7 +12211,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    @Override
    public boolean isLockTaskPermitted(String pkg) {
        // Check policy-exempt apps first, as it doesn't require the lock
        if (listPolicyExemptAppsUnchecked().contains(pkg)) {
        if (listPolicyExemptAppsUnchecked(mContext).contains(pkg)) {
            if (VERBOSE_LOG) {
                Slogf.v(LOG_TAG, "isLockTaskPermitted(%s): returning true for policy-exempt app",
                            pkg);
+4 −0
Original line number Diff line number Diff line
@@ -81,6 +81,10 @@ final class EnforcingAdmin {
                componentName.getPackageName(), componentName, Set.of(DEVICE_ADMIN_AUTHORITY));
    }

    static String getRoleAuthorityOf(String roleName) {
        return ROLE_AUTHORITY_PREFIX + roleName;
    }

    private EnforcingAdmin(
            String packageName, ComponentName componentName, Set<String> authorities) {
        Objects.requireNonNull(packageName);
+107 −0
Original line number Diff line number Diff line
/*
 * 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.devicepolicy;

import android.annotation.Nullable;

import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;

import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.Objects;
import java.util.Set;

final class LockTaskPolicy {
    private Set<String> mPackages;
    private int mFlags;

    LockTaskPolicy(@Nullable Set<String> packages, int flags) {
        mPackages = packages;
        mFlags = flags;
    }

    @Nullable
    Set<String> getPackages() {
        return mPackages;
    }

    int getFlags() {
        return mFlags;
    }

    void setPackages(Set<String> packages) {
        mPackages = packages;
    }

    void setFlags(int flags) {
        mFlags = flags;
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        LockTaskPolicy other = (LockTaskPolicy) o;
        return Objects.equals(mPackages, other.mPackages)
                && mFlags == other.mFlags;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mPackages, mFlags);
    }

    static final class LockTaskPolicySerializer extends PolicySerializer<LockTaskPolicy> {

        private static final String ATTR_PACKAGES = ":packages";
        private static final String ATTR_PACKAGES_SEPARATOR = ";";
        private static final String ATTR_FLAGS = ":flags";

        @Override
        void saveToXml(
                TypedXmlSerializer serializer, String attributeNamePrefix, LockTaskPolicy value)
                throws IOException {
            if (value.mPackages != null) {
                serializer.attribute(
                        /* namespace= */ null,
                        attributeNamePrefix + ATTR_PACKAGES,
                        String.join(ATTR_PACKAGES_SEPARATOR, value.mPackages));
            }
            serializer.attributeInt(
                    /* namespace= */ null,
                    attributeNamePrefix + ATTR_FLAGS,
                    value.mFlags);
        }

        @Override
        LockTaskPolicy readFromXml(TypedXmlPullParser parser, String attributeNamePrefix)
                throws XmlPullParserException {
            String packagesStr = parser.getAttributeValue(
                    /* namespace= */ null,
                    attributeNamePrefix + ATTR_PACKAGES);
            Set<String> packages = packagesStr == null
                    ? null
                    : Set.of(packagesStr.split(ATTR_PACKAGES_SEPARATOR));
            int flags = parser.getAttributeInt(
                    /* namespace= */ null,
                    attributeNamePrefix + ATTR_FLAGS);
            return new LockTaskPolicy(packages, flags);
        }
    }
}
+12 −0
Original line number Diff line number Diff line
@@ -82,11 +82,23 @@ final class PolicyDefinition<V> {
                new String[]{packageName, permission});
    }

    static PolicyDefinition<LockTaskPolicy> LOCK_TASK = new PolicyDefinition<>(
            DevicePolicyManager.LOCK_TASK_POLICY,
            new TopPriority<>(List.of(
                    // TODO(b/258166155): add correct device lock role name
                    EnforcingAdmin.getRoleAuthorityOf("DeviceLock"),
                    EnforcingAdmin.DPC_AUTHORITY)),
            POLICY_FLAG_LOCAL_ONLY_POLICY,
            (LockTaskPolicy value, Context context, Integer userId, String[] args) ->
                    PolicyEnforcerCallbacks.setLockTask(value, context, userId),
            new LockTaskPolicy.LockTaskPolicySerializer());

    private static Map<String, PolicyDefinition<?>> sPolicyDefinitions = Map.of(
            DevicePolicyManager.AUTO_TIMEZONE_POLICY, AUTO_TIMEZONE,
            DevicePolicyManager.PERMISSION_GRANT_POLICY_KEY, PERMISSION_GRANT_NO_ARGS
    );


    private final String mPolicyKey;
    private final String mPolicyDefinitionKey;
    private final ResolutionMechanism<V> mResolutionMechanism;
Loading