summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java15
-rw-r--r--core/java/android/app/backup/BackupAgent.java7
-rw-r--r--media/java/android/media/ExifInterface.java7
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/IconUtils.java6
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java8
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java27
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java55
8 files changed, 97 insertions, 31 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index afdd43423c72..a2f9bdd2370d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2358,18 +2358,23 @@ public class DevicePolicyManager {
* <p>The calling device admin must be a device or profile owner. If it is not,
* a {@link SecurityException} will be thrown.
*
+ * <p>The calling device admin can verify the value it has set by calling
+ * {@link #getRequiredStrongAuthTimeout(ComponentName)} and passing in its instance.
+ *
* <p>This method can be called on the {@link DevicePolicyManager} instance returned by
* {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
* profile.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param timeoutMs The new timeout, after which the user will have to unlock with strong
- * authentication method. If the timeout is lower than 1 hour (minimum) or higher than
- * 72 hours (default and maximum) an {@link IllegalArgumentException} is thrown.
+ * authentication method. A value of 0 means the admin is not participating in
+ * controlling the timeout.
+ * The minimum and maximum timeouts are platform-defined and are typically 1 hour and
+ * 72 hours, respectively. Though discouraged, the admin may choose to require strong
+ * auth at all times using {@link #KEYGUARD_DISABLE_FINGERPRINT} and/or
+ * {@link #KEYGUARD_DISABLE_TRUST_AGENTS}.
*
* @throws SecurityException if {@code admin} is not a device or profile owner.
- * @throws IllegalArgumentException if the timeout is lower than 1 hour (minimum) or higher than
- * 72 hours (default and maximum)
*
* @hide
*/
@@ -2395,7 +2400,7 @@ public class DevicePolicyManager {
*
* @param admin The name of the admin component to check, or {@code null} to aggregate
* accross all participating admins.
- * @return The timeout or default timeout if not configured
+ * @return The timeout or 0 if not configured for the provided admin.
*
* @hide
*/
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 3ba81c8689b9..bad632555c42 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -649,10 +649,11 @@ public abstract class BackupAgent extends ContextWrapper {
File file = scanQueue.remove(0);
String filePath;
try {
- // Ignore symlinks outright
+ // Ignore things that aren't "real" files or dirs
StructStat stat = Os.lstat(file.getPath());
- if (OsConstants.S_ISLNK(stat.st_mode)) {
- if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file);
+ if (!OsConstants.S_ISREG(stat.st_mode)
+ && !OsConstants.S_ISDIR(stat.st_mode)) {
+ if (DEBUG) Log.i(TAG, "Not a file/dir (skipping)!: " + file);
continue;
}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 5e00dc1a4fa3..6f24f763d6a6 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1557,16 +1557,13 @@ public class ExifInterface {
* <p>
* This method is only supported for JPEG files.
* </p>
- *
- * @throws UnsupportedOperationException If this method is called with unsupported files.
*/
public void saveAttributes() throws IOException {
if (!mIsSupportedFile || mIsRaw) {
- throw new UnsupportedOperationException(
- "ExifInterface only supports saving attributes on JPEG formats.");
+ throw new IOException("ExifInterface only supports saving attributes on JPEG formats.");
}
if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) {
- throw new UnsupportedOperationException(
+ throw new IOException(
"ExifInterface does not support saving attributes for the current input.");
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
index 177ba0d20154..d87bc11a8495 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
@@ -42,12 +42,6 @@ public class IconUtils {
public static Drawable loadMimeIcon(
Context context, String mimeType, String authority, String docId, int mode) {
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
- // TODO: eventually move these hacky assets into that package
- if ("com.android.providers.media.documents".equals(authority)
- && docId.startsWith("album")) {
- return context.getDrawable(R.drawable.ic_doc_album);
- }
-
if (mode == State.MODE_GRID) {
return context.getDrawable(R.drawable.ic_grid_folder);
} else {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java
index cebc9b05679e..557a2f6abc9f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java
@@ -157,6 +157,9 @@ public class RecentsLoader extends AsyncTaskLoader<DirectoryResult> {
throw new RuntimeException(e);
} catch (ExecutionException e) {
// We already logged on other side
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to query Recents for authority: " + task.authority
+ + ". Skip this authority in Recents.", e);
}
} else {
allDone = false;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index 0a2960f8ffe0..94b8277f4edd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -107,7 +107,13 @@ public class Model {
mSortOrder = result.sortOrder;
doc = result.doc;
- updateModelData();
+ try {
+ updateModelData();
+ } catch (Exception e) {
+ Log.e(TAG, "Error while accessing cursors", e);
+ notifyUpdateListeners(e);
+ return;
+ }
final Bundle extras = mCursor.getExtras();
if (extras != null) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2eceb0b0a52e..92aa1b98238f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -611,7 +611,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
- long strongAuthUnlockTimeout = DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+ long strongAuthUnlockTimeout = 0; // admin doesn't participate by default
static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
@@ -4248,10 +4248,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- Preconditions.checkArgument(timeoutMs >= MINIMUM_STRONG_AUTH_TIMEOUT_MS,
- "Timeout must not be lower than the minimum strong auth timeout.");
- Preconditions.checkArgument(timeoutMs <= DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS,
- "Timeout must not be higher than the default strong auth timeout.");
+ Preconditions.checkArgument(timeoutMs >= 0, "Timeout must not be a negative number.");
+ // timeoutMs with value 0 means that the admin doesn't participate
+ // timeoutMs is clamped to the interval in case the internal constants change in the future
+ if (timeoutMs != 0 && timeoutMs < MINIMUM_STRONG_AUTH_TIMEOUT_MS) {
+ timeoutMs = MINIMUM_STRONG_AUTH_TIMEOUT_MS;
+ }
+ if (timeoutMs > DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS) {
+ timeoutMs = DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+ }
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (this) {
@@ -4267,7 +4272,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
/**
* Return a single admin's strong auth unlock timeout or minimum value (strictest) of all
* admins if who is null.
- * Returns default timeout if not configured.
+ * Returns 0 if not configured for the provided admin.
*/
@Override
public long getRequiredStrongAuthTimeout(ComponentName who, int userId, boolean parent) {
@@ -4278,9 +4283,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId, parent);
- return admin != null ? Math.max(admin.strongAuthUnlockTimeout,
- MINIMUM_STRONG_AUTH_TIMEOUT_MS)
- : DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+ return admin != null ? admin.strongAuthUnlockTimeout : 0;
}
// Return the strictest policy across all participating admins.
@@ -4288,8 +4291,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
long strongAuthUnlockTimeout = DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
for (int i = 0; i < admins.size(); i++) {
- strongAuthUnlockTimeout = Math.min(admins.get(i).strongAuthUnlockTimeout,
- strongAuthUnlockTimeout);
+ final long timeout = admins.get(i).strongAuthUnlockTimeout;
+ if (timeout != 0) { // take only participating admins into account
+ strongAuthUnlockTimeout = Math.min(timeout, strongAuthUnlockTimeout);
+ }
}
return Math.max(strongAuthUnlockTimeout, MINIMUM_STRONG_AUTH_TIMEOUT_MS);
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 2d96bff29bd7..11ec7ac64eda 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1909,6 +1909,61 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyScreenTimeoutCall(Integer.MAX_VALUE, false);
}
+ public void testSetRequiredStrongAuthTimeout_DeviceOwner() throws Exception {
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ setupDeviceOwner();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+
+ final long MINIMUM_STRONG_AUTH_TIMEOUT_MS = 1 * 60 * 60 * 1000; // 1h
+ final long ONE_MINUTE = 60 * 1000;
+
+ // aggregation should be the default if unset by any admin
+ assertEquals(dpm.getRequiredStrongAuthTimeout(null),
+ DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+
+ // admin not participating by default
+ assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
+
+ //clamping from the top
+ dpm.setRequiredStrongAuthTimeout(admin1,
+ DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS + ONE_MINUTE);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(admin1),
+ DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(null),
+ DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+
+ // 0 means default
+ dpm.setRequiredStrongAuthTimeout(admin1, 0);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(null),
+ DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+
+ // clamping from the bottom
+ dpm.setRequiredStrongAuthTimeout(admin1, MINIMUM_STRONG_AUTH_TIMEOUT_MS - ONE_MINUTE);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MINIMUM_STRONG_AUTH_TIMEOUT_MS);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(null), MINIMUM_STRONG_AUTH_TIMEOUT_MS);
+
+ // value within range
+ dpm.setRequiredStrongAuthTimeout(admin1, MINIMUM_STRONG_AUTH_TIMEOUT_MS + ONE_MINUTE);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MINIMUM_STRONG_AUTH_TIMEOUT_MS
+ + ONE_MINUTE);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(null), MINIMUM_STRONG_AUTH_TIMEOUT_MS
+ + ONE_MINUTE);
+
+ // reset to default
+ dpm.setRequiredStrongAuthTimeout(admin1, 0);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
+ assertEquals(dpm.getRequiredStrongAuthTimeout(null),
+ DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+
+ // negative value
+ try {
+ dpm.setRequiredStrongAuthTimeout(admin1, -ONE_MINUTE);
+ fail("Didn't throw IllegalArgumentException");
+ } catch (IllegalArgumentException iae) {
+ }
+ }
+
private void verifyScreenTimeoutCall(Integer expectedTimeout,
boolean shouldStayOnWhilePluggedInBeCleared) {
if (expectedTimeout == null) {