Implement Policy to disable printing.

This adds a new "isPrintingEnabled" policy (true by default)
and hooks it into PrintManagerService.

Bug: 64140119
Test: manual

Change-Id: Ifb0f6772af51e6185135e9dcf5551e9ef0d88af3
This commit is contained in:
Vladislav Kuzkokov
2018-01-15 15:04:05 +01:00
parent e6c2b50229
commit 792d58fbce
7 changed files with 203 additions and 2 deletions

View File

@@ -9197,4 +9197,50 @@ public class DevicePolicyManager {
throw re.rethrowFromSystemServer();
}
}
/**
* Allows/disallows printing.
*
* @param admin which {@link DeviceAdminReceiver} this request is associated with.
* @param enabled whether printing should be allowed or not.
* @throws SecurityException if {@code admin} is neither device, nor profile owner.
* @hide
*/
public void setPrintingEnabled(@NonNull ComponentName admin, boolean enabled) {
try {
mService.setPrintingEnabled(admin, enabled);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Returns whether printing is enabled for current user.
*
* @return {@code true} iff printing is enabled.
* @hide
*/
public boolean isPrintingEnabled() {
try {
return mService.isPrintingEnabled();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Returns error message to be displayed when printing is disabled.
*
* Used only by PrintService.
* @return Localized error message.
* @throws SecurityException if caller is not system.
* @hide
*/
public CharSequence getPrintingDisabledReason() {
try {
return mService.getPrintingDisabledReason();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
}

View File

@@ -396,4 +396,8 @@ interface IDevicePolicyManager {
void setEndUserSessionMessage(in ComponentName admin, in CharSequence endUserSessionMessage);
CharSequence getStartUserSessionMessage(in ComponentName admin);
CharSequence getEndUserSessionMessage(in ComponentName admin);
void setPrintingEnabled(in ComponentName admin, boolean enabled);
boolean isPrintingEnabled();
CharSequence getPrintingDisabledReason();
}

View File

@@ -379,6 +379,9 @@
<string name="factory_reset_message">The admin app can\'t be used. Your device will now be
erased.\n\nIf you have questions, contact your organization's admin.</string>
<!-- A toast message displayed when printing is attempted but disabled by policy. -->
<string name="printing_disabled_by">Printing disabled by <xliff:g id="owner_app">%s</xliff:g>.</string>
<!-- Display name for any time a piece of data refers to the owner of the phone. For example, this could be used in place of the phone's phone number. -->
<string name="me">Me</string>

View File

@@ -878,6 +878,7 @@
<java-symbol type="string" name="preposition_for_time" />
<java-symbol type="string" name="print_service_installed_title" />
<java-symbol type="string" name="print_service_installed_message" />
<java-symbol type="string" name="printing_disabled_by" />
<java-symbol type="string" name="progress_erasing" />
<java-symbol type="string" name="mobile_provisioning_apn" />
<java-symbol type="string" name="mobile_provisioning_url" />

View File

@@ -126,4 +126,19 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
public String getEndUserSessionMessage(ComponentName admin) {
return null;
}
@Override
public void setPrintingEnabled(ComponentName admin, boolean enabled) {
throw new UnsupportedOperationException();
}
@Override
public boolean isPrintingEnabled() {
return true;
}
@Override
public CharSequence getPrintingDisabledReason() {
return null;
}
}

View File

@@ -74,6 +74,7 @@ import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityThread;
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.IActivityManager;
@@ -285,6 +286,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final String TAG_PASSWORD_VALIDITY = "password-validity";
private static final String TAG_PRINTING_ENABLED = "printing-enabled";
private static final int REQUEST_EXPIRE_PASSWORD = 5571;
private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1);
@@ -589,6 +592,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
long mPasswordTokenHandle = 0;
boolean mPrintingEnabled = true;
public DevicePolicyData(int userHandle) {
mUserHandle = userHandle;
}
@@ -2880,6 +2885,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
out.endTag(null, TAG_CURRENT_INPUT_METHOD_SET);
}
if (!policy.mPrintingEnabled) {
out.startTag(null, TAG_PRINTING_ENABLED);
out.attribute(null, ATTR_VALUE, Boolean.toString(policy.mPrintingEnabled));
out.endTag(null, TAG_PRINTING_ENABLED);
}
for (final String cert : policy.mOwnerInstalledCaCerts) {
out.startTag(null, TAG_OWNER_INSTALLED_CA_CERT);
out.attribute(null, ATTR_ALIAS, cert);
@@ -3098,6 +3109,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
policy.mCurrentInputMethodSet = true;
} else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) {
policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS));
} else if (TAG_PRINTING_ENABLED.equals(tag)) {
String enabled = parser.getAttributeValue(null, ATTR_VALUE);
policy.mPrintingEnabled = Boolean.toString(true).equals(enabled);
} else {
Slog.w(LOG_TAG, "Unknown tag: " + tag);
XmlUtils.skipCurrentTag(parser);
@@ -12274,4 +12288,93 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return deviceOwner.endUserSessionMessage;
}
}
private boolean hasPrinting() {
return mInjector.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PRINTING);
}
@Override
public void setPrintingEnabled(ComponentName admin, boolean enabled) {
if (!mHasFeature || !hasPrinting()) {
return;
}
Preconditions.checkNotNull(admin, "Admin cannot be null.");
enforceProfileOrDeviceOwner(admin);
synchronized (this) {
final int userHandle = mInjector.userHandleGetCallingUserId();
DevicePolicyData policy = getUserData(userHandle);
if (policy.mPrintingEnabled != enabled) {
policy.mPrintingEnabled = enabled;
saveSettingsLocked(userHandle);
}
}
}
/**
* Returns whether printing is enabled for current user.
* @hide
*/
@Override
public boolean isPrintingEnabled() {
if (!hasPrinting()) {
return false;
}
if (!mHasFeature) {
return true;
}
synchronized (this) {
final int userHandle = mInjector.userHandleGetCallingUserId();
DevicePolicyData policy = getUserData(userHandle);
return policy.mPrintingEnabled;
}
}
/**
* Returns text of error message if printing is disabled.
* Only to be called by Print Service.
* @hide
*/
@Override
public CharSequence getPrintingDisabledReason() {
if (!hasPrinting() || !mHasFeature) {
Log.e(LOG_TAG, "no printing or no management");
return null;
}
synchronized (this) {
final int userHandle = mInjector.userHandleGetCallingUserId();
DevicePolicyData policy = getUserData(userHandle);
if (policy.mPrintingEnabled) {
Log.e(LOG_TAG, "printing is enabled");
return null;
}
String ownerPackage = mOwners.getProfileOwnerPackage(userHandle);
if (ownerPackage == null) {
ownerPackage = mOwners.getDeviceOwnerPackageName();
}
PackageManager pm = mInjector.getPackageManager();
PackageInfo packageInfo;
try {
packageInfo = pm.getPackageInfo(ownerPackage, 0);
} catch (NameNotFoundException e) {
Log.e(LOG_TAG, "getPackageInfo error", e);
return null;
}
if (packageInfo == null) {
Log.e(LOG_TAG, "packageInfo is inexplicably null");
return null;
}
ApplicationInfo appInfo = packageInfo.applicationInfo;
if (appInfo == null) {
Log.e(LOG_TAG, "appInfo is inexplicably null");
return null;
}
CharSequence appLabel = pm.getApplicationLabel(appInfo);
if (appLabel == null) {
Log.e(LOG_TAG, "appLabel is inexplicably null");
return null;
}
return ((Context) ActivityThread.currentActivityThread().getSystemUiContext())
.getResources().getString(R.string.printing_disabled_by, appLabel);
}
}
}

View File

@@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -32,6 +33,7 @@ import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -54,6 +56,7 @@ import android.service.print.PrintServiceDumpProto;
import android.util.Log;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.widget.Toast;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
@@ -110,9 +113,12 @@ public final class PrintManagerService extends SystemService {
private final SparseArray<UserState> mUserStates = new SparseArray<>();
private final DevicePolicyManager mDpc;
PrintManagerImpl(Context context) {
mContext = context;
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mDpc = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
registerContentObservers();
registerBroadcastReceivers();
}
@@ -120,8 +126,26 @@ public final class PrintManagerService extends SystemService {
@Override
public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
PrintAttributes attributes, String packageName, int appId, int userId) {
printJobName = Preconditions.checkStringNotEmpty(printJobName);
adapter = Preconditions.checkNotNull(adapter);
if (!isPrintingEnabled()) {
final CharSequence disabledMessage = mDpc.getPrintingDisabledReason();
if (disabledMessage != null) {
Toast.makeText(mContext, Looper.getMainLooper(), disabledMessage,
Toast.LENGTH_LONG).show();
}
try {
adapter.start();
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error calling IPrintDocumentAdapter.start()");
}
try {
adapter.finish();
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error calling IPrintDocumentAdapter.finish()");
}
return null;
}
printJobName = Preconditions.checkStringNotEmpty(printJobName);
packageName = Preconditions.checkStringNotEmpty(packageName);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
@@ -240,7 +264,8 @@ public final class PrintManagerService extends SystemService {
@Override
public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
if (printJobId == null) {
if (printJobId == null || !isPrintingEnabled()) {
// if printing is disabled the state just remains "failed".
return;
}
@@ -685,6 +710,10 @@ public final class PrintManagerService extends SystemService {
}
}
private boolean isPrintingEnabled() {
return mDpc == null || mDpc.isPrintingEnabled();
}
private void dump(@NonNull DualDumpOutputStream dumpStream,
@NonNull ArrayList<UserState> userStatesToDump) {
final int userStateCount = userStatesToDump.size();