summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java40
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-rw-r--r--core/java/android/view/IWindowManager.aidl6
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java56
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java5
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java65
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java5
9 files changed, 183 insertions, 1 deletions
diff --git a/api/current.txt b/api/current.txt
index 3d08dd8..934452f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5355,6 +5355,7 @@ package android.app.admin {
method public int getPasswordMinimumSymbols(android.content.ComponentName);
method public int getPasswordMinimumUpperCase(android.content.ComponentName);
method public int getPasswordQuality(android.content.ComponentName);
+ method public boolean getScreenCaptureDisabled(android.content.ComponentName);
method public boolean getStorageEncryption(android.content.ComponentName);
method public int getStorageEncryptionStatus();
method public boolean hasAnyCaCertsInstalled();
@@ -5399,6 +5400,7 @@ package android.app.admin {
method public void setProfileName(android.content.ComponentName, java.lang.String);
method public void setRecommendedGlobalProxy(android.content.ComponentName, android.net.ProxyInfo);
method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
+ method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index efeded5..a193a34 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1775,6 +1775,46 @@ public class DevicePolicyManager {
}
/**
+ * Called by a device/profile owner to set whether the screen capture is disabled.
+ *
+ * <p>The calling device admin must be a device or profile owner. If it is not, a
+ * security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ */
+ public void setScreenCaptureDisabled(ComponentName admin, boolean disabled) {
+ if (mService != null) {
+ try {
+ mService.setScreenCaptureDisabled(admin, UserHandle.myUserId(), disabled);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Determine whether or not screen capture has been disabled by the current
+ * admin, if specified, or all admins.
+ * @param admin The name of the admin component to check, or null to check if any admins
+ * have disabled screen capture.
+ */
+ public boolean getScreenCaptureDisabled(ComponentName admin) {
+ return getScreenCaptureDisabled(admin, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean getScreenCaptureDisabled(ComponentName admin, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.getScreenCaptureDisabled(admin, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return false;
+ }
+
+ /**
* Called by an application that is administering the device to disable keyguard customizations,
* such as widgets. After setting this, keyguard features will be disabled according to the
* provided feature list.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 5fc8c5f..6499ae4 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -88,6 +88,9 @@ interface IDevicePolicyManager {
void setCameraDisabled(in ComponentName who, boolean disabled, int userHandle);
boolean getCameraDisabled(in ComponentName who, int userHandle);
+ void setScreenCaptureDisabled(in ComponentName who, int userHandle, boolean disabled);
+ boolean getScreenCaptureDisabled(in ComponentName who, int userHandle);
+
void setKeyguardDisabledFeatures(in ComponentName who, int which, int userHandle);
int getKeyguardDisabledFeatures(in ComponentName who, int userHandle);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index a61d771..5157c41 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -149,6 +149,12 @@ interface IWindowManager
// boolean string as parsed by SystemProperties.getBoolean().
void setStrictModeVisualIndicatorPreference(String enabled);
+ /**
+ * Update the windowmanagers cached value of
+ * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled(null, userId)}
+ */
+ void updateScreenCaptureDisabled(int userId);
+
// These can only be called with the SET_ORIENTATION permission.
/**
* Update the current screen rotation based on the current state of
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index cf2f5d3..416cd54 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -191,7 +191,7 @@
<!-- Notification title displayed when we fail to take a screenshot. [CHAR LIMIT=50] -->
<string name="screenshot_failed_title">Couldn\'t capture screenshot.</string>
<!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
- <string name="screenshot_failed_text">Couldn\'t save screenshot. Storage may be in use.</string>
+ <string name="screenshot_failed_text">Can\'t take screenshot due to limited storage space, or it isn\'t allowed by the app or your organization.</string>
<!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
<string name="usb_preference_title">USB file transfer options</string>
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index aae2bb8..eac2819 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import android.app.admin.DevicePolicyManager;
import android.app.AppOpsManager;
import android.util.ArraySet;
import android.util.TimeUtils;
@@ -425,6 +426,13 @@ public class WindowManagerService extends IWindowManager.Stub
*/
WindowState[] mRebuildTmp = new WindowState[20];
+ /**
+ * Stores for each user whether screencapture is disabled
+ * This array is essentially a cache for all userId for
+ * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled(null, userId)}
+ */
+ SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<Boolean>();
+
IInputMethodManager mInputMethodManager;
AccessibilityController mAccessibilityController;
@@ -2439,6 +2447,45 @@ public class WindowManagerService extends IWindowManager.Stub
return res;
}
+ /**
+ * Returns whether screen capture is disabled for all windows of a specific user.
+ */
+ boolean isScreenCaptureDisabledLocked(int userId) {
+ Boolean disabled = mScreenCaptureDisabled.get(userId);
+ if (disabled != null) {
+ return disabled;
+ }
+
+ // mScreenCaptureDisabled not set yet, try to update it.
+ updateScreenCaptureDisabledLocked(userId);
+ disabled = mScreenCaptureDisabled.get(userId);
+ if (disabled == null) {
+ // Not able to update, return false by default.
+ return false;
+ } else {
+ return disabled;
+ }
+ }
+
+ /**
+ * Update mScreenCaptureDisabled for specific user according to the device policy manager.
+ */
+ @Override
+ public void updateScreenCaptureDisabled(int userId) {
+ mH.sendMessage(mH.obtainMessage(H.UPDATE_SCRN_CAP, userId, 0 /* unused argument */));
+ }
+
+ void updateScreenCaptureDisabledLocked(int userId) {
+ DevicePolicyManager dpm = (DevicePolicyManager) mContext
+ .getSystemService(Context.DEVICE_POLICY_SERVICE);
+ if (dpm != null) {
+ boolean disabled = dpm.getScreenCaptureDisabled(null, userId);
+ mScreenCaptureDisabled.put(userId, disabled);
+ } else {
+ Slog.e(TAG, "Could not get DevicePolicyManager.");
+ }
+ }
+
public void removeWindow(Session session, IWindow client) {
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
@@ -7203,6 +7250,8 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int NEW_ANIMATOR_SCALE = 34;
+ public static final int UPDATE_SCRN_CAP = 35;
+
@Override
public void handleMessage(Message msg) {
if (DEBUG_WINDOW_TRACE) {
@@ -7677,6 +7726,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
break;
+
+ case UPDATE_SCRN_CAP: {
+ synchronized (mWindowMap) {
+ updateScreenCaptureDisabledLocked(msg.arg1);
+ }
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 49d4ae9..f3afe82 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -39,6 +39,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Debug;
+import android.os.UserHandle;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
@@ -690,6 +691,10 @@ class WindowStateAnimator {
flags |= SurfaceControl.SECURE;
}
+ if (mService.isScreenCaptureDisabledLocked(UserHandle.getUserId(mWin.mOwnerUid))) {
+ flags |= SurfaceControl.SECURE;
+ }
+
int width;
int height;
if ((attrs.flags & LayoutParams.FLAG_SCALED) != 0) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 5c661af..e0612eb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -258,6 +258,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
private static final String TAG_DISABLE_CAMERA = "disable-camera";
private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
+ private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
private static final String TAG_ACCOUNT_TYPE = "account-type";
private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
@@ -326,6 +327,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean encryptionRequested = false;
boolean disableCamera = false;
boolean disableCallerId = false;
+ boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
+
Set<String> accountTypesWithManagementDisabled = new HashSet<String>();
// TODO: review implementation decisions with frameworks team
@@ -443,6 +446,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.attribute(null, ATTR_VALUE, Boolean.toString(disableCallerId));
out.endTag(null, TAG_DISABLE_CALLER_ID);
}
+ if (disableScreenCapture) {
+ out.startTag(null, TAG_DISABLE_SCREEN_CAPTURE);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(disableScreenCapture));
+ out.endTag(null, TAG_DISABLE_SCREEN_CAPTURE);
+ }
if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures));
@@ -528,6 +536,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if (TAG_DISABLE_CALLER_ID.equals(tag)) {
disableCallerId = Boolean.parseBoolean(
parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_SCREEN_CAPTURE.equals(tag)) {
+ disableScreenCapture = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
} else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
disabledKeyguardFeatures = Integer.parseInt(
parser.getAttributeValue(null, ATTR_VALUE));
@@ -606,6 +617,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
pw.println(disableCamera);
pw.print(prefix); pw.print("disableCallerId=");
pw.println(disableCallerId);
+ pw.print(prefix); pw.print("disableScreenCapture=");
+ pw.println(disableScreenCapture);
pw.print(prefix); pw.print("disabledKeyguardFeatures=");
pw.println(disabledKeyguardFeatures);
}
@@ -2977,6 +2990,58 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private void setEncryptionRequested(boolean encrypt) {
}
+
+ /**
+ * Set whether the screen capture is disabled for the user managed by the specified admin.
+ */
+ public void setScreenCaptureDisabled(ComponentName who, int userHandle, boolean disabled) {
+ if (!mHasFeature) {
+ return;
+ }
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ if (ap.disableScreenCapture != disabled) {
+ ap.disableScreenCapture = disabled;
+ saveSettingsLocked(userHandle);
+ try {
+ getWindowManager().updateScreenCaptureDisabled(userHandle);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify WindowManager.", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns whether or not screen capture is disabled for a given admin, or disabled for any
+ * active admin (if given admin is null).
+ */
+ public boolean getScreenCaptureDisabled(ComponentName who, int userHandle) {
+ if (!mHasFeature) {
+ return false;
+ }
+ synchronized (this) {
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+ return (admin != null) ? admin.disableScreenCapture : false;
+ }
+
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
+ for (int i = 0; i < N; i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (admin.disableScreenCapture) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
/**
* The system property used to share the state of the camera. The native camera service
* is expected to read this property and act accordingly.
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 6927b26..2ffe4a2 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -360,6 +360,11 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
+ public void updateScreenCaptureDisabled(int userId) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
public void updateRotation(boolean arg0, boolean arg1) throws RemoteException {
// TODO Auto-generated method stub
}