summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Hongming Jin <hongmingjin@google.com> 2018-05-30 11:01:06 -0700
committer Hongming Jin <hongmingjin@google.com> 2018-06-04 09:41:01 -0700
commit8e2bfc11ce480aaa4791c42bdf1df7111c32db4a (patch)
tree4fdda74d0959fc23e6837bcc6eff8c0581cb547e
parentdea740bdceb20818d49a0f015c620d1d5d9e5adc (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
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java56
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java26
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java100
-rw-r--r--services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java3
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);
}