diff options
| author | 2018-05-30 11:01:06 -0700 | |
|---|---|---|
| committer | 2018-06-04 09:41:01 -0700 | |
| commit | 8e2bfc11ce480aaa4791c42bdf1df7111c32db4a (patch) | |
| tree | 4fdda74d0959fc23e6837bcc6eff8c0581cb547e | |
| parent | dea740bdceb20818d49a0f015c620d1d5d9e5adc (diff) | |
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
Change-Id: I3ac968ebc20be68da08293d9b685a01920f11b76
4 files changed, 174 insertions, 11 deletions
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java index 56d61efdcb25..020e8c22b128 100644 --- a/core/java/android/content/pm/RegisteredServicesCache.java +++ b/core/java/android/content/pm/RegisteredServicesCache.java @@ -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 @@ -72,7 +74,7 @@ import libcore.io.IoUtils; * <p> * The services are referred to by type V and are made available via the * {@link #getServiceInfo} method. - * + * * @hide */ public abstract class RegisteredServicesCache<V> { @@ -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") @@ -273,7 +277,7 @@ public abstract class RegisteredServicesCache<V> { Log.d(TAG, "notifyListener: " + type + " is " + (removed ? "removed" : "added")); } RegisteredServicesCacheListener<V> listener; - Handler handler; + Handler handler; synchronized (this) { listener = mListener; handler = mHandler; @@ -281,7 +285,7 @@ public abstract class RegisteredServicesCache<V> { if (listener == null) { return; } - + final RegisteredServicesCacheListener<V> listener2 = listener; handler.post(new Runnable() { public void run() { @@ -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); } /** diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index b2797f9c7a17..426a0c157aec 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -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"); } diff --git a/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java b/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java new file mode 100644 index 000000000000..9e5f7229d382 --- /dev/null +++ b/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java @@ -0,0 +1,100 @@ +/* + * 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."); + } +} diff --git a/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java b/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java index 2c7d921edbcb..b13f66f83381 100644 --- a/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java +++ b/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java @@ -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); } |