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

Commit ceffeb0d authored by Rubin Xu's avatar Rubin Xu Committed by Android (Google) Code Review
Browse files

Merge "DevicePolicy API to set default dialer and SMS app"

parents b186a092 c6507df7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7920,6 +7920,7 @@ package android.app.admin {
    method @Deprecated public void setCrossProfileCallerIdDisabled(@NonNull android.content.ComponentName, boolean);
    method @Deprecated public void setCrossProfileContactsSearchDisabled(@NonNull android.content.ComponentName, boolean);
    method public void setCrossProfilePackages(@NonNull android.content.ComponentName, @NonNull java.util.Set<java.lang.String>);
    method public void setDefaultDialerApplication(@NonNull String);
    method public void setDefaultSmsApplication(@NonNull android.content.ComponentName, @NonNull String);
    method public void setDelegatedScopes(@NonNull android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.lang.String>);
    method public void setDeviceOwnerLockScreenInfo(@NonNull android.content.ComponentName, CharSequence);
+35 −0
Original line number Diff line number Diff line
@@ -9816,6 +9816,11 @@ public class DevicePolicyManager {
     * of an organization-owned managed profile and the package must be a pre-installed system
     * package. If called on the parent instance, then the default SMS application is set on the
     * personal profile.
     * <p>
     * Starting from Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the profile
     * owner of an organization-owned managed profile can also call this method directly (not on the
     * parent profile instance) to set the default SMS application in the work profile. This is only
     * meaningful when work profile telephony is enabled by {@link #setManagedSubscriptionsPolicy}.
     *
     * @param admin       Which {@link DeviceAdminReceiver} this request is associated with.
     * @param packageName The name of the package to set as the default SMS application.
@@ -9836,6 +9841,36 @@ public class DevicePolicyManager {
        }
    }
    /**
     * Must be called by a device owner or a profile owner of an organization-owned managed profile
     * to set the default dialer application for the calling user.
     * <p>
     * When the profile owner of an organization-owned managed profile calls this method, it sets
     * the default dialer application in the work profile. This is only meaningful when work profile
     * telephony is enabled by {@link #setManagedSubscriptionsPolicy}.
     * <p>
     * If the device does not support telephony ({@link PackageManager#FEATURE_TELEPHONY}), calling
     * this method will do nothing.
     *
     * @param packageName The name of the package to set as the default dialer application.
     * @throws SecurityException        if {@code admin} is not a device or profile owner or a
     *                                  profile owner of an organization-owned managed profile.
     * @throws IllegalArgumentException if the package cannot be set as the default dialer, for
     *                                  example if the package is not installed or does not expose
     *                                  the expected activities or services that a dialer app is
     *                                  required to have.
     */
    public void setDefaultDialerApplication(@NonNull String packageName) {
        throwIfParentInstance("setDefaultDialerApplication");
        if (mService != null) {
            try {
                mService.setDefaultDialerApplication(packageName);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
    /**
     * Called by a profile owner or device owner to grant permission to a package to manage
     * application restrictions for the calling user via {@link #setApplicationRestrictions} and
+1 −0
Original line number Diff line number Diff line
@@ -239,6 +239,7 @@ interface IDevicePolicyManager {
    void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);

    void setDefaultSmsApplication(in ComponentName admin, String packageName, boolean parent);
    void setDefaultDialerApplication(String packageName);

    void setApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName, in Bundle settings);
    Bundle getApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName);
+19 −0
Original line number Diff line number Diff line
@@ -175,6 +175,8 @@ class ActiveAdmin {
    private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
    private static final String ATTR_PACKAGE_POLICY_MODE = "package-policy-type";
    private static final String TAG_CREDENTIAL_MANAGER_POLICY = "credential-manager-policy";
    private static final String TAG_DIALER_PACKAGE = "dialer_package";
    private static final String TAG_SMS_PACKAGE = "sms_package";

    // If the ActiveAdmin is a permission-based admin, then info will be null because the
    // permission-based admin is not mapped to a device administrator component.
@@ -350,6 +352,8 @@ class ActiveAdmin {
    boolean mUsbDataSignalingEnabled = USB_DATA_SIGNALING_ENABLED_DEFAULT;

    int mWifiMinimumSecurityLevel = DevicePolicyManager.WIFI_SECURITY_OPEN;
    String mDialerPackage;
    String mSmsPackage;

    ActiveAdmin(DeviceAdminInfo info, boolean isParent) {
        this.info = info;
@@ -661,6 +665,12 @@ class ActiveAdmin {
            mManagedSubscriptionsPolicy.saveToXml(out);
            out.endTag(null, TAG_MANAGED_SUBSCRIPTIONS_POLICY);
        }
        if (!TextUtils.isEmpty(mDialerPackage)) {
            writeAttributeValueToXml(out, TAG_DIALER_PACKAGE, mDialerPackage);
        }
        if (!TextUtils.isEmpty(mSmsPackage)) {
            writeAttributeValueToXml(out, TAG_SMS_PACKAGE, mSmsPackage);
        }
    }

    private void writePackagePolicy(TypedXmlSerializer out, String tag,
@@ -969,6 +979,10 @@ class ActiveAdmin {
                mManagedSubscriptionsPolicy = ManagedSubscriptionsPolicy.readFromXml(parser);
            } else if (TAG_CREDENTIAL_MANAGER_POLICY.equals(tag)) {
                mCredentialManagerPolicy = readPackagePolicy(parser);
            } else if (TAG_DIALER_PACKAGE.equals(tag)) {
                mDialerPackage = parser.getAttributeValue(null, ATTR_VALUE);
            } else if (TAG_SMS_PACKAGE.equals(tag)) {
                mSmsPackage = parser.getAttributeValue(null, ATTR_VALUE);
            } else {
                Slogf.w(LOG_TAG, "Unknown admin tag: %s", tag);
                XmlUtils.skipCurrentTag(parser);
@@ -1449,5 +1463,10 @@ class ActiveAdmin {
            pw.println(mManagedSubscriptionsPolicy);
            pw.decreaseIndent();
        }

        pw.print("mDialerPackage=");
        pw.println(mDialerPackage);
        pw.print("mSmsPackage=");
        pw.println(mSmsPackage);
    }
}
+73 −3
Original line number Diff line number Diff line
@@ -341,6 +341,7 @@ import android.net.Uri;
import android.net.VpnManager;
import android.net.metrics.IpConnectivityLog;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -481,8 +482,12 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -839,6 +844,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    final UserManagerInternal mUserManagerInternal;
    final UsageStatsManagerInternal mUsageStatsManagerInternal;
    final TelephonyManager mTelephonyManager;
    final RoleManager mRoleManager;
    private final LockPatternUtils mLockPatternUtils;
    private final LockSettingsInternal mLockSettingsInternal;
    private final DeviceAdminServiceController mDeviceAdminServiceController;
@@ -1626,6 +1632,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return mContext.getSystemService(TelephonyManager.class);
        }
        RoleManager getRoleManager() {
            return mContext.getSystemService(RoleManager.class);
        }
        TrustManager getTrustManager() {
            return (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
        }
@@ -1968,6 +1978,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        mIPackageManager = Objects.requireNonNull(injector.getIPackageManager());
        mIPermissionManager = Objects.requireNonNull(injector.getIPermissionManager());
        mTelephonyManager = Objects.requireNonNull(injector.getTelephonyManager());
        mRoleManager = Objects.requireNonNull(injector.getRoleManager());
        mLocalService = new LocalService();
        mLockPatternUtils = injector.newLockPatternUtils();
@@ -10842,14 +10853,73 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        final CallerIdentity caller = getCallerIdentity(admin);
        Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
                || (parent && isProfileOwnerOfOrganizationOwnedDevice(caller)));
                || isProfileOwnerOfOrganizationOwnedDevice(caller));
        final int userId;
        if (parent) {
            userId = getProfileParentId(mInjector.userHandleGetCallingUserId());
            mInjector.binderWithCleanCallingIdentity(() -> enforcePackageIsSystemPackage(
                    packageName, getProfileParentId(mInjector.userHandleGetCallingUserId())));
                    packageName, userId));
        } else {
            userId = mInjector.userHandleGetCallingUserId();
        }
        mInjector.binderWithCleanCallingIdentity(() ->
                SmsApplication.setDefaultApplication(packageName, mContext));
                SmsApplication.setDefaultApplicationAsUser(packageName, mContext, userId));
        synchronized (getLockObject()) {
            final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
                    getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent);
            if (!Objects.equals(activeAdmin.mSmsPackage, packageName)) {
                activeAdmin.mSmsPackage = packageName;
                saveSettingsLocked(caller.getUserId());
            }
        }
    }
    @Override
    public void setDefaultDialerApplication(String packageName) {
        if (!mHasFeature || !mHasTelephonyFeature) {
            return;
        }
        final CallerIdentity caller = getCallerIdentity();
        final int callerUserId = caller.getUserId();
        Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
                || isProfileOwnerOfOrganizationOwnedDevice(caller));
        mInjector.binderWithCleanCallingIdentity(() -> {
            CompletableFuture<Void> future = new CompletableFuture<>();
            Consumer<Boolean> callback = successful -> {
                if (successful) {
                    future.complete(null);
                } else {
                    future.completeExceptionally(new IllegalArgumentException(
                            packageName +  " cannot be set as the dialer"));
                }
            };
            mRoleManager.addRoleHolderAsUser(
                    RoleManager.ROLE_DIALER, packageName, 0, UserHandle.of(callerUserId),
                    AsyncTask.THREAD_POOL_EXECUTOR, callback);
            try {
                future.get(5, TimeUnit.SECONDS);
            } catch (TimeoutException e) {
                throw new IllegalArgumentException("Timeout when setting the app as the dialer", e);
            } catch (ExecutionException e) {
                Throwable cause = e.getCause();
                if (cause instanceof IllegalArgumentException) {
                    throw (IllegalArgumentException) cause;
                } else {
                    throw new IllegalStateException(cause);
                }
            }
        });
        // Only save the package when the setting the role succeeded without exception.
        synchronized (getLockObject()) {
            final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(callerUserId);
            if (!Objects.equals(admin.mDialerPackage, packageName)) {
                admin.mDialerPackage = packageName;
                saveSettingsLocked(callerUserId);
            }
        }
    }
    @Override