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

Commit 64896541 authored by Hongming Jin's avatar Hongming Jin Committed by Android (Google) Code Review
Browse files

Merge "Add shell command handler for account manager to allow enabling service...

Merge "Add shell command handler for account manager to allow enabling service binding for instant app. Test: cts-tradefed run cts -m CtsAccountManagerTestCases cts-instant-tradefed run cts-instant -m CtsAccountManagerTestCases Bug: 79367659" into pi-dev
parents 15ebbeb9 8e2bfc11
Loading
Loading
Loading
Loading
+47 −9
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.content.pm;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -40,9 +41,12 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;

import com.google.android.collect.Lists;
import com.google.android.collect.Maps;

import libcore.io.IoUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -61,8 +65,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;

import libcore.io.IoUtils;

/**
 * Cache of registered services. This cache is lazily built by interrogating
 * {@link PackageManager} on a per-user basis. It's updated as packages are
@@ -98,6 +100,8 @@ public abstract class RegisteredServicesCache<V> {
        Map<V, ServiceInfo<V>> services = null;
        @GuardedBy("mServicesLock")
        boolean mPersistentServicesFileDidNotExist = true;
        @GuardedBy("mServicesLock")
        boolean mBindInstantServiceAllowed = false;
    }

    @GuardedBy("mServicesLock")
@@ -387,6 +391,34 @@ public abstract class RegisteredServicesCache<V> {
        }
    }

    /**
     * @return whether the binding to service is allowed for instant apps.
     */
    public boolean getBindInstantServiceAllowed(int userId) {
        mContext.enforceCallingOrSelfPermission(
                Manifest.permission.MANAGE_BIND_INSTANT_SERVICE,
                "getBindInstantServiceAllowed");

        synchronized (mServicesLock) {
            final UserServices<V> user = findOrCreateUserLocked(userId);
            return user.mBindInstantServiceAllowed;
        }
    }

    /**
     * Set whether the binding to service is allowed or not for instant apps.
     */
    public void setBindInstantServiceAllowed(int userId, boolean allowed) {
        mContext.enforceCallingOrSelfPermission(
                Manifest.permission.MANAGE_BIND_INSTANT_SERVICE,
                "setBindInstantServiceAllowed");

        synchronized (mServicesLock) {
            final UserServices<V> user = findOrCreateUserLocked(userId);
            user.mBindInstantServiceAllowed = allowed;
        }
    }

    @VisibleForTesting
    protected boolean inSystemImage(int callerUid) {
        String[] packages = mContext.getPackageManager().getPackagesForUid(callerUid);
@@ -409,10 +441,16 @@ public abstract class RegisteredServicesCache<V> {
    @VisibleForTesting
    protected List<ResolveInfo> queryIntentServices(int userId) {
        final PackageManager pm = mContext.getPackageManager();
        return pm.queryIntentServicesAsUser(new Intent(mInterfaceName),
                PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE
                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                userId);
        int flags = PackageManager.GET_META_DATA
                | PackageManager.MATCH_DIRECT_BOOT_AWARE
                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
        synchronized (mServicesLock) {
            final UserServices<V> user = findOrCreateUserLocked(userId);
            if (user.mBindInstantServiceAllowed) {
                flags |= PackageManager.MATCH_INSTANT;
            }
        }
        return pm.queryIntentServicesAsUser(new Intent(mInterfaceName), flags, userId);
    }

    /**
+24 −2
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@ import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -408,6 +410,15 @@ public class AccountManagerService
        });
    }


    boolean getBindInstantServiceAllowed(int userId) {
        return  mAuthenticatorCache.getBindInstantServiceAllowed(userId);
    }

    void setBindInstantServiceAllowed(int userId, boolean allowed) {
        mAuthenticatorCache.setBindInstantServiceAllowed(userId, allowed);
    }

    private void cancelAccountAccessRequestNotificationIfNeeded(int uid,
            boolean checkAccess) {
        Account[] accounts = getAccountsAsUser(null, UserHandle.getUserId(uid), "android");
@@ -4647,6 +4658,14 @@ public class AccountManagerService
        }
    }

    @Override
    public void onShellCommand(FileDescriptor in, FileDescriptor out,
            FileDescriptor err, String[] args, ShellCallback callback,
            ResultReceiver resultReceiver) {
        new AccountManagerServiceShellCommand(this).exec(this, in, out, err, args,
                callback, resultReceiver);
    }

    private abstract class Session extends IAccountAuthenticatorResponse.Stub
            implements IBinder.DeathRecipient, ServiceConnection {
        IAccountManagerResponse mResponse;
@@ -5018,8 +5037,11 @@ public class AccountManagerService
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName);
            }
            if (!mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
                    UserHandle.of(mAccounts.userId))) {
            int flags = Context.BIND_AUTO_CREATE;
            if (mAuthenticatorCache.getBindInstantServiceAllowed(mAccounts.userId)) {
                flags |= Context.BIND_ALLOW_INSTANT;
            }
            if (!mContext.bindServiceAsUser(intent, this, flags, UserHandle.of(mAccounts.userId))) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
                }
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.accounts;

import android.annotation.NonNull;
import android.os.ShellCommand;
import android.os.UserHandle;

import java.io.PrintWriter;

/**
 * Shell command implementation for the account manager service
 */
final class AccountManagerServiceShellCommand extends ShellCommand {
    final @NonNull AccountManagerService mService;

    AccountManagerServiceShellCommand(@NonNull AccountManagerService service) {
        mService = service;
    }

    @Override
    public int onCommand(String cmd) {
        if (cmd == null) {
            return handleDefaultCommands(cmd);
        }
        switch (cmd) {
            case "get-bind-instant-service-allowed": {
                return runGetBindInstantServiceAllowed();
            }
            case "set-bind-instant-service-allowed": {
                return runSetBindInstantServiceAllowed();
            }
        }
        return -1;
    }

    private int runGetBindInstantServiceAllowed() {
        final Integer userId = parseUserId();
        if (userId == null) {
            return -1;
        }
        getOutPrintWriter().println(Boolean.toString(
                mService.getBindInstantServiceAllowed(userId)));
        return 0;
    }

    private int runSetBindInstantServiceAllowed() {
        final Integer userId = parseUserId();
        if (userId == null) {
            return -1;
        }
        final String allowed = getNextArgRequired();
        if (allowed == null) {
            getErrPrintWriter().println("Error: no true/false specified");
            return -1;
        }
        mService.setBindInstantServiceAllowed(userId,
                Boolean.parseBoolean(allowed));
        return 0;
    }

    private Integer parseUserId() {
        final String option = getNextOption();
        if (option != null) {
            if (option.equals("--user")) {
                return UserHandle.parseUserArg(getNextArgRequired());
            } else {
                getErrPrintWriter().println("Unknown option: " + option);
                return null;
            }
        }
        return UserHandle.USER_SYSTEM;
    }

    @Override
    public void onHelp() {
        PrintWriter pw = getOutPrintWriter();
        pw.println("Account manager service commands:");
        pw.println("  help");
        pw.println("    Print this help text.");
        pw.println("  set-bind-instant-service-allowed [--user <USER_ID>] true|false ");
        pw.println("    Set whether binding to services provided by instant apps is allowed.");
        pw.println("  get-bind-instant-service-allowed [--user <USER_ID>]");
        pw.println("    Get whether binding to services provided by instant apps is allowed.");
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -70,4 +70,7 @@ public interface IAccountAuthenticatorCache {
     * picked up by the cache.
     */
    void updateServices(int userId);

    boolean getBindInstantServiceAllowed(int userId);
    void setBindInstantServiceAllowed(int userId, boolean allowed);
}