Merge "Allow Print subsystem to work with services provided by instant app" into pi-dev

This commit is contained in:
Philip P. Moltmann
2018-05-15 04:58:00 +00:00
committed by Android (Google) Code Review
6 changed files with 213 additions and 6 deletions

View File

@@ -143,4 +143,21 @@ interface IPrintManager {
void stopPrinterStateTracking(in PrinterId printerId, int userId); void stopPrinterStateTracking(in PrinterId printerId, int userId);
void destroyPrinterDiscoverySession(in IPrinterDiscoveryObserver observer, void destroyPrinterDiscoverySession(in IPrinterDiscoveryObserver observer,
int userId); int userId);
/**
* Check if the system will bind to print services in intant app.
*
* @param userId the Id of the user the behavior should be checked for
*
* @return {@code true} iff the system will bind to print services in instant apps.
*/
boolean getBindInstantServiceAllowed(int userId);
/**
* Set if the system will bind to print services in intant app.
*
* @param userId the Id of the user the behavior should be changed for
* @param allows iff {@code true} the system will bind to print services in instant apps
*/
void setBindInstantServiceAllowed(int userId, boolean allowed);
} }

View File

@@ -811,6 +811,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
List<ResolveInfo> resolvedActivities = getPackageManager() List<ResolveInfo> resolvedActivities = getPackageManager()
.queryIntentActivities(intent, 0); .queryIntentActivities(intent, 0);
if (resolvedActivities.isEmpty()) { if (resolvedActivities.isEmpty()) {
Log.w(LOG_TAG, "Advanced options activity " + mAdvancedPrintOptionsActivity + " could "
+ "not be found");
return; return;
} }

View File

@@ -18,8 +18,12 @@ package com.android.server.print;
import static android.content.pm.PackageManager.GET_SERVICES; import static android.content.pm.PackageManager.GET_SERVICES;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
import static android.content.pm.PackageManager.MATCH_INSTANT;
import static android.os.Process.ROOT_UID;
import static android.os.Process.SHELL_UID;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName; import android.content.ComponentName;
@@ -36,6 +40,8 @@ import android.os.Bundle;
import android.os.Looper; import android.os.Looper;
import android.os.Process; import android.os.Process;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.print.IPrintDocumentAdapter; import android.print.IPrintDocumentAdapter;
@@ -121,6 +127,13 @@ public final class PrintManagerService extends SystemService {
registerBroadcastReceivers(); registerBroadcastReceivers();
} }
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
new PrintShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
}
@Override @Override
public Bundle print(String printJobName, IPrintDocumentAdapter adapter, public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
PrintAttributes attributes, String packageName, int appId, int userId) { PrintAttributes attributes, String packageName, int appId, int userId) {
@@ -717,6 +730,46 @@ public final class PrintManagerService extends SystemService {
} }
} }
@Override
public boolean getBindInstantServiceAllowed(@UserIdInt int userId) {
int callingUid = Binder.getCallingUid();
if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
throw new SecurityException("Can only be called by uid " + SHELL_UID
+ " or " + ROOT_UID);
}
final UserState userState;
synchronized (mLock) {
userState = getOrCreateUserStateLocked(userId, false);
}
final long identity = Binder.clearCallingIdentity();
try {
return userState.getBindInstantServiceAllowed();
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void setBindInstantServiceAllowed(@UserIdInt int userId, boolean allowed) {
int callingUid = Binder.getCallingUid();
if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
throw new SecurityException("Can only be called by uid " + SHELL_UID
+ " or " + ROOT_UID);
}
final UserState userState;
synchronized (mLock) {
userState = getOrCreateUserStateLocked(userId, false);
}
final long identity = Binder.clearCallingIdentity();
try {
userState.setBindInstantServiceAllowed(allowed);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
private boolean isPrintingEnabled() { private boolean isPrintingEnabled() {
return !mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING, return !mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING,
Binder.getCallingUserHandle()); Binder.getCallingUserHandle());
@@ -773,7 +826,7 @@ public final class PrintManagerService extends SystemService {
List<ResolveInfo> installedServices = mContext.getPackageManager() List<ResolveInfo> installedServices = mContext.getPackageManager()
.queryIntentServicesAsUser(intent, .queryIntentServicesAsUser(intent,
GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING, GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING | MATCH_INSTANT,
getChangingUserId()); getChangingUserId());
return installedServices != null && !installedServices.isEmpty(); return installedServices != null && !installedServices.isEmpty();
@@ -988,7 +1041,7 @@ public final class PrintManagerService extends SystemService {
return appId; return appId;
} }
final int callingAppId = UserHandle.getAppId(callingUid); final int callingAppId = UserHandle.getAppId(callingUid);
if (appId == callingAppId || callingAppId == Process.SHELL_UID if (appId == callingAppId || callingAppId == SHELL_UID
|| callingAppId == Process.SYSTEM_UID) { || callingAppId == Process.SYSTEM_UID) {
return appId; return appId;
} }

View File

@@ -0,0 +1,112 @@
/*
* 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.print;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.print.IPrintManager;
import java.io.PrintWriter;
/**
* Shell command implementation for the print manager service
*/
final class PrintShellCommand extends ShellCommand {
final @NonNull IPrintManager mService;
PrintShellCommand(@NonNull IPrintManager service) {
mService = service;
}
@Override
public int onCommand(@Nullable 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;
}
try {
getOutPrintWriter().println(
Boolean.toString(mService.getBindInstantServiceAllowed(userId)));
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
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;
}
try {
mService.setBindInstantServiceAllowed(userId, Boolean.parseBoolean(allowed));
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
return 0;
}
private @Nullable 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("Print 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 print services provided by instant apps is "
+ "allowed.");
pw.println(" get-bind-instant-service-allowed [--user <USER_ID>]");
pw.println(" Get whether binding to print services provided by instant apps is "
+ "allowed.");
}
}

View File

@@ -571,8 +571,8 @@ final class RemotePrintService implements DeathRecipient {
mBinding = true; mBinding = true;
boolean wasBound = mContext.bindServiceAsUser(mIntent, mServiceConnection, boolean wasBound = mContext.bindServiceAsUser(mIntent, mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
new UserHandle(mUserId)); | Context.BIND_ALLOW_INSTANT, new UserHandle(mUserId));
if (!wasBound) { if (!wasBound) {
if (DEBUG) { if (DEBUG) {

View File

@@ -19,6 +19,7 @@ package com.android.server.print;
import static android.content.pm.PackageManager.GET_META_DATA; import static android.content.pm.PackageManager.GET_META_DATA;
import static android.content.pm.PackageManager.GET_SERVICES; import static android.content.pm.PackageManager.GET_SERVICES;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
import static android.content.pm.PackageManager.MATCH_INSTANT;
import static com.android.internal.print.DumpUtils.writePrintJobInfo; import static com.android.internal.print.DumpUtils.writePrintJobInfo;
import static com.android.internal.print.DumpUtils.writePrinterId; import static com.android.internal.print.DumpUtils.writePrinterId;
@@ -155,6 +156,11 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
*/ */
private RemotePrintServiceRecommendationService mPrintServiceRecommendationsService; private RemotePrintServiceRecommendationService mPrintServiceRecommendationsService;
/**
* Can services from instant apps be bound? (usually disabled, only used by testing)
*/
private boolean mIsInstantServiceAllowed;
public UserState(Context context, int userId, Object lock, boolean lowPriority) { public UserState(Context context, int userId, Object lock, boolean lowPriority) {
mContext = context; mContext = context;
mUserId = userId; mUserId = userId;
@@ -872,9 +878,14 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
private void readInstalledPrintServicesLocked() { private void readInstalledPrintServicesLocked() {
Set<PrintServiceInfo> tempPrintServices = new HashSet<PrintServiceInfo>(); Set<PrintServiceInfo> tempPrintServices = new HashSet<PrintServiceInfo>();
int queryIntentFlags = GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING;
if (mIsInstantServiceAllowed) {
queryIntentFlags |= MATCH_INSTANT;
}
List<ResolveInfo> installedServices = mContext.getPackageManager() List<ResolveInfo> installedServices = mContext.getPackageManager()
.queryIntentServicesAsUser(mQueryIntent, .queryIntentServicesAsUser(mQueryIntent, queryIntentFlags, mUserId);
GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING, mUserId);
final int installedCount = installedServices.size(); final int installedCount = installedServices.size();
for (int i = 0, count = installedCount; i < count; i++) { for (int i = 0, count = installedCount; i < count; i++) {
@@ -1185,6 +1196,18 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
} }
} }
public boolean getBindInstantServiceAllowed() {
return mIsInstantServiceAllowed;
}
public void setBindInstantServiceAllowed(boolean allowed) {
synchronized (mLock) {
mIsInstantServiceAllowed = allowed;
updateIfNeededLocked();
}
}
private abstract class PrintJobStateChangeListenerRecord implements DeathRecipient { private abstract class PrintJobStateChangeListenerRecord implements DeathRecipient {
@NonNull final IPrintJobStateChangeListener listener; @NonNull final IPrintJobStateChangeListener listener;
final int appId; final int appId;