Merge "Allow Print subsystem to work with services provided by instant app" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
cc64fb9c8f
@@ -143,4 +143,21 @@ interface IPrintManager {
|
||||
void stopPrinterStateTracking(in PrinterId printerId, int userId);
|
||||
void destroyPrinterDiscoverySession(in IPrinterDiscoveryObserver observer,
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -811,6 +811,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
|
||||
List<ResolveInfo> resolvedActivities = getPackageManager()
|
||||
.queryIntentActivities(intent, 0);
|
||||
if (resolvedActivities.isEmpty()) {
|
||||
Log.w(LOG_TAG, "Advanced options activity " + mAdvancedPrintOptionsActivity + " could "
|
||||
+ "not be found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,12 @@ package com.android.server.print;
|
||||
|
||||
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_INSTANT;
|
||||
import static android.os.Process.ROOT_UID;
|
||||
import static android.os.Process.SHELL_UID;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.admin.DevicePolicyManagerInternal;
|
||||
import android.content.ComponentName;
|
||||
@@ -36,6 +40,8 @@ import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ShellCallback;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.print.IPrintDocumentAdapter;
|
||||
@@ -121,6 +127,13 @@ public final class PrintManagerService extends SystemService {
|
||||
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
|
||||
public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
|
||||
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() {
|
||||
return !mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING,
|
||||
Binder.getCallingUserHandle());
|
||||
@@ -773,7 +826,7 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
List<ResolveInfo> installedServices = mContext.getPackageManager()
|
||||
.queryIntentServicesAsUser(intent,
|
||||
GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING,
|
||||
GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING | MATCH_INSTANT,
|
||||
getChangingUserId());
|
||||
|
||||
return installedServices != null && !installedServices.isEmpty();
|
||||
@@ -988,7 +1041,7 @@ public final class PrintManagerService extends SystemService {
|
||||
return appId;
|
||||
}
|
||||
final int callingAppId = UserHandle.getAppId(callingUid);
|
||||
if (appId == callingAppId || callingAppId == Process.SHELL_UID
|
||||
if (appId == callingAppId || callingAppId == SHELL_UID
|
||||
|| callingAppId == Process.SYSTEM_UID) {
|
||||
return appId;
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
@@ -571,8 +571,8 @@ final class RemotePrintService implements DeathRecipient {
|
||||
mBinding = true;
|
||||
|
||||
boolean wasBound = mContext.bindServiceAsUser(mIntent, mServiceConnection,
|
||||
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
|
||||
new UserHandle(mUserId));
|
||||
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
|
||||
| Context.BIND_ALLOW_INSTANT, new UserHandle(mUserId));
|
||||
|
||||
if (!wasBound) {
|
||||
if (DEBUG) {
|
||||
|
||||
@@ -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_SERVICES;
|
||||
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.writePrinterId;
|
||||
@@ -155,6 +156,11 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
*/
|
||||
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) {
|
||||
mContext = context;
|
||||
mUserId = userId;
|
||||
@@ -872,9 +878,14 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
|
||||
private void readInstalledPrintServicesLocked() {
|
||||
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()
|
||||
.queryIntentServicesAsUser(mQueryIntent,
|
||||
GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING, mUserId);
|
||||
.queryIntentServicesAsUser(mQueryIntent, queryIntentFlags, mUserId);
|
||||
|
||||
final int installedCount = installedServices.size();
|
||||
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 {
|
||||
@NonNull final IPrintJobStateChangeListener listener;
|
||||
final int appId;
|
||||
|
||||
Reference in New Issue
Block a user