summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/svc/src/com/android/commands/svc/NfcCommand.java3
-rw-r--r--core/java/android/app/AppOpsManager.java4
-rw-r--r--core/java/android/app/SharedPreferencesImpl.java72
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java17
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl1
-rw-r--r--core/java/android/widget/Toast.java61
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java45
-rw-r--r--core/jni/android_view_PointerIcon.cpp3
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java60
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java55
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java143
-rw-r--r--services/java/com/android/server/SystemServer.java5
14 files changed, 327 insertions, 150 deletions
diff --git a/cmds/svc/src/com/android/commands/svc/NfcCommand.java b/cmds/svc/src/com/android/commands/svc/NfcCommand.java
index 8e9791f8b731..02a92b9c19ff 100644
--- a/cmds/svc/src/com/android/commands/svc/NfcCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/NfcCommand.java
@@ -58,7 +58,8 @@ public class NfcCommand extends Svc.Command {
IPackageManager pm = IPackageManager.Stub.asInterface(
ServiceManager.getService("package"));
try {
- if (pm.hasSystemFeature(PackageManager.FEATURE_NFC, 0)) {
+ if (pm.hasSystemFeature(PackageManager.FEATURE_NFC, 0) ||
+ pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0)) {
INfcAdapter nfc = INfcAdapter.Stub
.asInterface(ServiceManager.getService(Context.NFC_SERVICE));
try {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1e4ffbeca33d..440ddd63147f 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -403,8 +403,8 @@ public class AppOpsManager {
OP_WRITE_SMS,
OP_RECEIVE_SMS,
OP_RECEIVE_SMS,
- OP_RECEIVE_SMS,
- OP_RECEIVE_SMS,
+ OP_RECEIVE_MMS,
+ OP_RECEIVE_WAP_PUSH,
OP_SEND_SMS,
OP_READ_SMS,
OP_WRITE_SMS,
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index c1180e25a0d3..f273cd8670f0 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -26,6 +26,8 @@ import android.system.StructStat;
import android.util.Log;
import com.google.android.collect.Maps;
+
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.XmlUtils;
import dalvik.system.BlockGuard;
@@ -72,6 +74,14 @@ final class SharedPreferencesImpl implements SharedPreferences {
private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
+ /** Current memory state (always increasing) */
+ @GuardedBy("this")
+ private long mCurrentMemoryStateGeneration;
+
+ /** Latest memory state that was committed to disk */
+ @GuardedBy("mWritingToDiskLock")
+ private long mDiskStateGeneration;
+
SharedPreferencesImpl(File file, int mode) {
mFile = file;
mBackupFile = makeBackupFile(file);
@@ -289,7 +299,7 @@ final class SharedPreferencesImpl implements SharedPreferences {
// Return value from EditorImpl#commitToMemory()
private static class MemoryCommitResult {
- public boolean changesMade; // any keys different?
+ public long memoryStateGeneration;
public List<String> keysModified; // may be null
public Set<OnSharedPreferenceChangeListener> listeners; // may be null
public Map<?, ?> mapToWriteToDisk;
@@ -412,9 +422,11 @@ final class SharedPreferencesImpl implements SharedPreferences {
}
synchronized (this) {
+ boolean changesMade = false;
+
if (mClear) {
if (!mMap.isEmpty()) {
- mcr.changesMade = true;
+ changesMade = true;
mMap.clear();
}
mClear = false;
@@ -441,13 +453,19 @@ final class SharedPreferencesImpl implements SharedPreferences {
mMap.put(k, v);
}
- mcr.changesMade = true;
+ changesMade = true;
if (hasListeners) {
mcr.keysModified.add(k);
}
}
mModified.clear();
+
+ if (changesMade) {
+ mCurrentMemoryStateGeneration++;
+ }
+
+ mcr.memoryStateGeneration = mCurrentMemoryStateGeneration;
}
}
return mcr;
@@ -509,10 +527,12 @@ final class SharedPreferencesImpl implements SharedPreferences {
*/
private void enqueueDiskWrite(final MemoryCommitResult mcr,
final Runnable postWriteRunnable) {
+ final boolean isFromSyncCommit = (postWriteRunnable == null);
+
final Runnable writeToDiskRunnable = new Runnable() {
public void run() {
synchronized (mWritingToDiskLock) {
- writeToFile(mcr);
+ writeToFile(mcr, isFromSyncCommit);
}
synchronized (SharedPreferencesImpl.this) {
mDiskWritesInFlight--;
@@ -523,8 +543,6 @@ final class SharedPreferencesImpl implements SharedPreferences {
}
};
- final boolean isFromSyncCommit = (postWriteRunnable == null);
-
// Typical #commit() path with fewer allocations, doing a write on
// the current thread.
if (isFromSyncCommit) {
@@ -538,6 +556,10 @@ final class SharedPreferencesImpl implements SharedPreferences {
}
}
+ if (DEBUG) {
+ Log.d(TAG, "added " + mcr.memoryStateGeneration + " -> " + mFile.getName());
+ }
+
QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
}
@@ -565,17 +587,34 @@ final class SharedPreferencesImpl implements SharedPreferences {
}
// Note: must hold mWritingToDiskLock
- private void writeToFile(MemoryCommitResult mcr) {
+ private void writeToFile(MemoryCommitResult mcr, boolean isFromSyncCommit) {
// Rename the current file so it may be used as a backup during the next read
if (mFile.exists()) {
- if (!mcr.changesMade) {
- // If the file already exists, but no changes were
- // made to the underlying map, it's wasteful to
- // re-write the file. Return as if we wrote it
- // out.
+ boolean needsWrite = false;
+
+ // Only need to write if the disk state is older than this commit
+ if (mDiskStateGeneration < mcr.memoryStateGeneration) {
+ if (isFromSyncCommit) {
+ needsWrite = true;
+ } else {
+ synchronized (this) {
+ // No need to persist intermediate states. Just wait for the latest state to
+ // be persisted.
+ if (mCurrentMemoryStateGeneration == mcr.memoryStateGeneration) {
+ needsWrite = true;
+ }
+ }
+ }
+ }
+
+ if (!needsWrite) {
+ if (DEBUG) {
+ Log.d(TAG, "skipped " + mcr.memoryStateGeneration + " -> " + mFile.getName());
+ }
mcr.setDiskWriteResult(true);
return;
}
+
if (!mBackupFile.exists()) {
if (!mFile.renameTo(mBackupFile)) {
Log.e(TAG, "Couldn't rename file " + mFile
@@ -599,6 +638,11 @@ final class SharedPreferencesImpl implements SharedPreferences {
}
XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
FileUtils.sync(str);
+
+ if (DEBUG) {
+ Log.d(TAG, "wrote " + mcr.memoryStateGeneration + " -> " + mFile.getName());
+ }
+
str.close();
ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
try {
@@ -612,7 +656,11 @@ final class SharedPreferencesImpl implements SharedPreferences {
}
// Writing was successful, delete the backup file if there is one.
mBackupFile.delete();
+
+ mDiskStateGeneration = mcr.memoryStateGeneration;
+
mcr.setDiskWriteResult(true);
+
return;
} catch (XmlPullParserException e) {
Log.w(TAG, "writeToFile: Got exception:", e);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a2f9bdd2370d..e23f142317ac 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2016,7 +2016,8 @@ public class DevicePolicyManager {
* Determine whether the current password the user has set is sufficient to meet the policy
* requirements (e.g. quality, minimum length) that have been requested by the admins of this
* user and its participating profiles. Restrictions on profiles that have a separate challenge
- * are not taken into account.
+ * are not taken into account. If the user has a password, it must have been entered in order to
+ * perform this check.
* <p>
* The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
@@ -2029,6 +2030,7 @@ public class DevicePolicyManager {
* @return Returns true if the password meets the current requirements, else false.
* @throws SecurityException if the calling application does not own an active administrator
* that uses {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
+ * @throws IllegalStateException if the user has a password but has not entered it yet.
*/
public boolean isActivePasswordSufficient() {
if (mService != null) {
@@ -3541,6 +3543,19 @@ public class DevicePolicyManager {
/**
* @hide
*/
+ public void reportPasswordChanged(int userId) {
+ if (mService != null) {
+ try {
+ mService.reportPasswordChanged(userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
public void reportFailedPasswordAttempt(int userHandle) {
if (mService != null) {
try {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index f39cb5ae9fbd..90632a19a09b 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -119,6 +119,7 @@ interface IDevicePolicyManager {
void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase,
int numbers, int symbols, int nonletter, int userHandle);
+ void reportPasswordChanged(int userId);
void reportFailedPasswordAttempt(int userHandle);
void reportSuccessfulPasswordAttempt(int userHandle);
void reportFailedFingerprintAttempt(int userHandle);
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index a400d90c64c5..4d9192ba8d24 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -100,13 +100,13 @@ public class Toast {
*/
public Toast(Context context) {
mContext = context;
- mTN = new TN();
+ mTN = new TN(context.getPackageName());
mTN.mY = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.toast_y_offset);
mTN.mGravity = context.getResources().getInteger(
com.android.internal.R.integer.config_toastDefaultGravity);
}
-
+
/**
* Show the view for the specified duration.
*/
@@ -133,15 +133,9 @@ public class Toast {
* after the appropriate duration.
*/
public void cancel() {
- mTN.hide();
-
- try {
- getService().cancelToast(mContext.getPackageName(), mTN);
- } catch (RemoteException e) {
- // Empty
- }
+ mTN.cancel();
}
-
+
/**
* Set the view to show.
* @see #getView
@@ -331,18 +325,40 @@ public class Toast {
final Runnable mHide = new Runnable() {
@Override
public void run() {
- handleHide();
- // Don't do this in handleHide() because it is also invoked by handleShow()
- mNextView = null;
}
};
private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
+
+ private static final int SHOW = 0;
+ private static final int HIDE = 1;
+ private static final int CANCEL = 2;
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- IBinder token = (IBinder) msg.obj;
- handleShow(token);
+ switch (msg.what) {
+ case SHOW: {
+ IBinder token = (IBinder) msg.obj;
+ handleShow(token);
+ break;
+ }
+ case HIDE: {
+ handleHide();
+ // Don't do this in handleHide() because it is also invoked by handleShow()
+ mNextView = null;
+ break;
+ }
+ case CANCEL: {
+ handleHide();
+ // Don't do this in handleHide() because it is also invoked by handleShow()
+ mNextView = null;
+ try {
+ getService().cancelToast(mPackageName, TN.this);
+ } catch (RemoteException e) {
+ }
+ break;
+ }
+ }
}
};
@@ -358,10 +374,12 @@ public class Toast {
WindowManager mWM;
+ String mPackageName;
+
static final long SHORT_DURATION_TIMEOUT = 5000;
static final long LONG_DURATION_TIMEOUT = 1000;
- TN() {
+ TN(String packageName) {
// XXX This should be changed to use a Dialog, with a Theme.Toast
// defined that sets up the layout params appropriately.
final WindowManager.LayoutParams params = mParams;
@@ -374,6 +392,8 @@ public class Toast {
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+
+ mPackageName = packageName;
}
/**
@@ -382,7 +402,7 @@ public class Toast {
@Override
public void show(IBinder windowToken) {
if (localLOGV) Log.v(TAG, "SHOW: " + this);
- mHandler.obtainMessage(0, windowToken).sendToTarget();
+ mHandler.obtainMessage(SHOW, windowToken).sendToTarget();
}
/**
@@ -391,7 +411,12 @@ public class Toast {
@Override
public void hide() {
if (localLOGV) Log.v(TAG, "HIDE: " + this);
- mHandler.post(mHide);
+ mHandler.obtainMessage(HIDE).sendToTarget();
+ }
+
+ public void cancel() {
+ if (localLOGV) Log.v(TAG, "CANCEL: " + this);
+ mHandler.obtainMessage(CANCEL).sendToTarget();
}
public void handleShow(IBinder windowToken) {
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 479b3b7a7a71..d49d433d665d 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -593,9 +593,6 @@ public class LockPatternUtils {
setCredentialRequiredToDecrypt(false);
}
- getDevicePolicyManager().setActivePasswordState(
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, userHandle);
-
onAfterChangingPassword(userHandle);
}
@@ -642,6 +639,7 @@ public class LockPatternUtils {
+ MIN_LOCK_PATTERN_SIZE + " dots long.");
}
+ setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
getLockSettings().setLockPattern(patternToString(pattern), savedPattern, userId);
DevicePolicyManager dpm = getDevicePolicyManager();
@@ -658,9 +656,6 @@ public class LockPatternUtils {
setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
- setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
- dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
- pattern.size(), 0, 0, 0, 0, 0, 0, userId);
onAfterChangingPassword(userId);
} catch (RemoteException re) {
Log.e(TAG, "Couldn't save lock pattern " + re);
@@ -863,9 +858,9 @@ public class LockPatternUtils {
+ "of length " + MIN_LOCK_PASSWORD_SIZE);
}
+ final int computedQuality = computePasswordQuality(password);
+ setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
getLockSettings().setLockPassword(password, savedPassword, userHandle);
- getLockSettings().setSeparateProfileChallengeEnabled(userHandle, true, null);
- int computedQuality = computePasswordQuality(password);
// Update the device encryption password.
if (userHandle == UserHandle.USER_SYSTEM
@@ -883,40 +878,6 @@ public class LockPatternUtils {
}
}
- setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
- if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
- int letters = 0;
- int uppercase = 0;
- int lowercase = 0;
- int numbers = 0;
- int symbols = 0;
- int nonletter = 0;
- for (int i = 0; i < password.length(); i++) {
- char c = password.charAt(i);
- if (c >= 'A' && c <= 'Z') {
- letters++;
- uppercase++;
- } else if (c >= 'a' && c <= 'z') {
- letters++;
- lowercase++;
- } else if (c >= '0' && c <= '9') {
- numbers++;
- nonletter++;
- } else {
- symbols++;
- nonletter++;
- }
- }
- dpm.setActivePasswordState(Math.max(quality, computedQuality),
- password.length(), letters, uppercase, lowercase,
- numbers, symbols, nonletter, userHandle);
- } else {
- // The password is not anything.
- dpm.setActivePasswordState(
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
- 0, 0, 0, 0, 0, 0, 0, userHandle);
- }
-
// Add the password to the password history. We assume all
// password hashes have the same length for simplicity of implementation.
String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp
index 6b634dfbef3e..4150636cae12 100644
--- a/core/jni/android_view_PointerIcon.cpp
+++ b/core/jni/android_view_PointerIcon.cpp
@@ -78,6 +78,9 @@ status_t android_view_PointerIcon_load(JNIEnv* env, jobject pointerIconObj, jobj
status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIconObj,
PointerIcon* outPointerIcon) {
+ if (!pointerIconObj) {
+ return BAD_VALUE;
+ }
outPointerIcon->style = env->GetIntField(pointerIconObj, gPointerIconClassInfo.mType);
outPointerIcon->hotSpotX = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotX);
outPointerIcon->hotSpotY = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotY);
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 203d2474fca1..fbcb62a3a8af 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -927,6 +927,7 @@ public class LockSettingsService extends ILockSettings.Stub {
synchronized (mSeparateChallengeLock) {
setLockPatternInternal(pattern, savedCredential, userId);
setSeparateProfileChallengeEnabled(userId, true, null);
+ notifyPasswordChanged(userId);
}
}
@@ -941,6 +942,7 @@ public class LockSettingsService extends ILockSettings.Stub {
setKeystorePassword(null, userId);
fixateNewestUserKeyAuth(userId);
onUserLockChanged(userId);
+ notifyActivePasswordMetricsAvailable(null, userId);
return;
}
@@ -990,6 +992,7 @@ public class LockSettingsService extends ILockSettings.Stub {
synchronized (mSeparateChallengeLock) {
setLockPasswordInternal(password, savedCredential, userId);
setSeparateProfileChallengeEnabled(userId, true, null);
+ notifyPasswordChanged(userId);
}
}
@@ -1003,6 +1006,7 @@ public class LockSettingsService extends ILockSettings.Stub {
setKeystorePassword(null, userId);
fixateNewestUserKeyAuth(userId);
onUserLockChanged(userId);
+ notifyActivePasswordMetricsAvailable(null, userId);
return;
}
@@ -1412,6 +1416,7 @@ public class LockSettingsService extends ILockSettings.Stub {
// migrate credential to GateKeeper
credentialUtil.setCredential(credential, null, userId);
if (!hasChallenge) {
+ notifyActivePasswordMetricsAvailable(credential, userId);
return VerifyCredentialResponse.OK;
}
// Fall through to get the auth token. Technically this should never happen,
@@ -1451,6 +1456,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (progressCallback != null) {
progressCallback.onCredentialVerified();
}
+ notifyActivePasswordMetricsAvailable(credential, userId);
unlockKeystore(credential, userId);
Slog.i(TAG, "Unlocking user " + userId +
@@ -1474,6 +1480,60 @@ public class LockSettingsService extends ILockSettings.Stub {
return response;
}
+ private void notifyActivePasswordMetricsAvailable(final String password, int userId) {
+ final int quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(userId);
+
+ // Asynchronous to avoid dead lock
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ int length = 0;
+ int letters = 0;
+ int uppercase = 0;
+ int lowercase = 0;
+ int numbers = 0;
+ int symbols = 0;
+ int nonletter = 0;
+ if (password != null) {
+ length = password.length();
+ for (int i = 0; i < length; i++) {
+ char c = password.charAt(i);
+ if (c >= 'A' && c <= 'Z') {
+ letters++;
+ uppercase++;
+ } else if (c >= 'a' && c <= 'z') {
+ letters++;
+ lowercase++;
+ } else if (c >= '0' && c <= '9') {
+ numbers++;
+ nonletter++;
+ } else {
+ symbols++;
+ nonletter++;
+ }
+ }
+ }
+ DevicePolicyManager dpm = (DevicePolicyManager)
+ mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ dpm.setActivePasswordState(quality, length, letters, uppercase, lowercase, numbers,
+ symbols, nonletter, userId);
+ }
+ });
+ }
+
+ /**
+ * Call after {@link #notifyActivePasswordMetricsAvailable} so metrics are updated before
+ * reporting the password changed.
+ */
+ private void notifyPasswordChanged(int userId) {
+ // Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering
+ mHandler.post(() -> {
+ DevicePolicyManager dpm = (DevicePolicyManager)
+ mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ dpm.reportPasswordChanged(userId);
+ });
+ }
+
@Override
public boolean checkVoldPassword(int userId) throws RemoteException {
if (!mFirstCallToVold) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 74095acca16a..719ce7618fd0 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -25,6 +25,7 @@ import android.view.Display;
import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.os.SomeArgs;
import com.android.internal.R;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
@@ -1705,6 +1706,7 @@ public class InputManagerService extends IInputManager.Stub
// Binder call
@Override
public void setCustomPointerIcon(PointerIcon icon) {
+ Preconditions.checkNotNull(icon);
nativeSetCustomPointerIcon(mPtr, icon);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3bd533d03628..03612ab67c8f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1646,9 +1646,11 @@ public class PackageManagerService extends IPackageManager.Stub {
}
// Now that we successfully installed the package, grant runtime
- // permissions if requested before broadcasting the install.
- if (grantPermissions && res.pkg.applicationInfo.targetSdkVersion
- >= Build.VERSION_CODES.M) {
+ // permissions if requested before broadcasting the install. Also
+ // for legacy apps in permission review mode we clear the permission
+ // review flag which is used to emulate runtime permissions for
+ // legacy apps.
+ if (grantPermissions) {
grantRequestedRuntimePermissions(res.pkg, res.newUsers, grantedPermissions);
}
@@ -1885,11 +1887,6 @@ public class PackageManagerService extends IPackageManager.Stub {
for (int userId : userIds) {
grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions);
}
-
- // We could have touched GID membership, so flush out packages.list
- synchronized (mPackages) {
- mSettings.writePackageListLPr();
- }
}
private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
@@ -1904,6 +1901,9 @@ public class PackageManagerService extends IPackageManager.Stub {
final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
| PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+ final boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
+ >= Build.VERSION_CODES.M;
+
for (String permission : pkg.requestedPermissions) {
final BasePermission bp;
synchronized (mPackages) {
@@ -1913,9 +1913,18 @@ public class PackageManagerService extends IPackageManager.Stub {
&& (grantedPermissions == null
|| ArrayUtils.contains(grantedPermissions, permission))) {
final int flags = permissionsState.getPermissionFlags(permission, userId);
- // Installer cannot change immutable permissions.
- if ((flags & immutableFlags) == 0) {
- grantRuntimePermission(pkg.packageName, permission, userId);
+ if (supportsRuntimePermissions) {
+ // Installer cannot change immutable permissions.
+ if ((flags & immutableFlags) == 0) {
+ grantRuntimePermission(pkg.packageName, permission, userId);
+ }
+ } else if (mPermissionReviewRequired) {
+ // In permission review mode we clear the review flag when we
+ // are asked to install the app with all permissions granted.
+ if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
+ updatePermissionFlags(permission, pkg.packageName,
+ PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0 /*value*/, userId);
+ }
}
}
}
@@ -10108,12 +10117,30 @@ public class PackageManagerService extends IPackageManager.Stub {
int flags = permissionState != null
? permissionState.getFlags() : 0;
if (origPermissions.hasRuntimePermission(bp.name, userId)) {
- if (permissionsState.grantRuntimePermission(bp, userId) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // If we cannot put the permission as it was, we have to write.
+ // Don't propagate the permission in a permission review mode if
+ // the former was revoked, i.e. marked to not propagate on upgrade.
+ // Note that in a permission review mode install permissions are
+ // represented as constantly granted runtime ones since we need to
+ // keep a per user state associated with the permission. Also the
+ // revoke on upgrade flag is no longer applicable and is reset.
+ final boolean revokeOnUpgrade = (flags & PackageManager
+ .FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0;
+ if (revokeOnUpgrade) {
+ flags &= ~PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+ // Since we changed the flags, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
+ if (!mPermissionReviewRequired || !revokeOnUpgrade) {
+ if (permissionsState.grantRuntimePermission(bp, userId) ==
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ // If we cannot put the permission as it was,
+ // we have to write.
+ changedRuntimePermissionUserIds = ArrayUtils.appendInt(
+ changedRuntimePermissionUserIds, userId);
+ }
+ }
+
// If the app supports runtime permissions no need for a review.
if ((mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED)
&& appSupportsRuntimePermissions
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 2f72a5cd1ab5..88cfce8023af 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1462,7 +1462,11 @@ static void nativeSetCustomPointerIcon(JNIEnv* env, jclass /* clazz */,
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
PointerIcon pointerIcon;
- android_view_PointerIcon_getLoadedIcon(env, iconObj, &pointerIcon);
+ status_t result = android_view_PointerIcon_getLoadedIcon(env, iconObj, &pointerIcon);
+ if (result) {
+ jniThrowRuntimeException(env, "Failed to load custom pointer icon.");
+ return;
+ }
SpriteIcon spriteIcon;
pointerIcon.bitmap.copyTo(&spriteIcon.bitmap, kN32_SkColorType);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 96331e83dd31..f23378cf03f8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2273,10 +2273,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.endTag(null, "failed-password-attempts");
}
- if (policy.mActivePasswordQuality != 0 || policy.mActivePasswordLength != 0
+ // Don't save metrics for FBE devices
+ if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()
+ && (policy.mActivePasswordQuality != 0 || policy.mActivePasswordLength != 0
|| policy.mActivePasswordUpperCase != 0 || policy.mActivePasswordLowerCase != 0
|| policy.mActivePasswordLetters != 0 || policy.mActivePasswordNumeric != 0
- || policy.mActivePasswordSymbols != 0 || policy.mActivePasswordNonLetter != 0) {
+ || policy.mActivePasswordSymbols != 0
+ || policy.mActivePasswordNonLetter != 0)) {
out.startTag(null, "active-password");
out.attribute(null, "quality", Integer.toString(policy.mActivePasswordQuality));
out.attribute(null, "length", Integer.toString(policy.mActivePasswordLength));
@@ -2369,6 +2372,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
JournaledFile journal = makeJournaledFile(userHandle);
FileInputStream stream = null;
File file = journal.chooseForRead();
+ boolean needsRewrite = false;
try {
stream = new FileInputStream(file);
XmlPullParser parser = Xml.newPullParser();
@@ -2455,23 +2459,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if ("password-owner".equals(tag)) {
policy.mPasswordOwner = Integer.parseInt(
parser.getAttributeValue(null, "value"));
- } else if ("active-password".equals(tag)) {
- policy.mActivePasswordQuality = Integer.parseInt(
- parser.getAttributeValue(null, "quality"));
- policy.mActivePasswordLength = Integer.parseInt(
- parser.getAttributeValue(null, "length"));
- policy.mActivePasswordUpperCase = Integer.parseInt(
- parser.getAttributeValue(null, "uppercase"));
- policy.mActivePasswordLowerCase = Integer.parseInt(
- parser.getAttributeValue(null, "lowercase"));
- policy.mActivePasswordLetters = Integer.parseInt(
- parser.getAttributeValue(null, "letters"));
- policy.mActivePasswordNumeric = Integer.parseInt(
- parser.getAttributeValue(null, "numeric"));
- policy.mActivePasswordSymbols = Integer.parseInt(
- parser.getAttributeValue(null, "symbols"));
- policy.mActivePasswordNonLetter = Integer.parseInt(
- parser.getAttributeValue(null, "nonletter"));
} else if (TAG_ACCEPTED_CA_CERTIFICATES.equals(tag)) {
policy.mAcceptedCaCertificates.add(parser.getAttributeValue(null, ATTR_NAME));
} else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
@@ -2488,6 +2475,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policy.mAdminBroadcastPending = Boolean.toString(true).equals(pending);
} else if (TAG_INITIALIZATION_BUNDLE.equals(tag)) {
policy.mInitBundle = PersistableBundle.restoreFromXml(parser);
+ } else if ("active-password".equals(tag)) {
+ if (mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
+ // Remove this from FBE devices
+ needsRewrite = true;
+ } else {
+ policy.mActivePasswordQuality = Integer.parseInt(
+ parser.getAttributeValue(null, "quality"));
+ policy.mActivePasswordLength = Integer.parseInt(
+ parser.getAttributeValue(null, "length"));
+ policy.mActivePasswordUpperCase = Integer.parseInt(
+ parser.getAttributeValue(null, "uppercase"));
+ policy.mActivePasswordLowerCase = Integer.parseInt(
+ parser.getAttributeValue(null, "lowercase"));
+ policy.mActivePasswordLetters = Integer.parseInt(
+ parser.getAttributeValue(null, "letters"));
+ policy.mActivePasswordNumeric = Integer.parseInt(
+ parser.getAttributeValue(null, "numeric"));
+ policy.mActivePasswordSymbols = Integer.parseInt(
+ parser.getAttributeValue(null, "symbols"));
+ policy.mActivePasswordNonLetter = Integer.parseInt(
+ parser.getAttributeValue(null, "nonletter"));
+ }
} else {
Slog.w(LOG_TAG, "Unknown tag: " + tag);
XmlUtils.skipCurrentTag(parser);
@@ -2510,29 +2519,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Generate a list of admins from the admin map
policy.mAdminList.addAll(policy.mAdminMap.values());
- // Validate that what we stored for the password quality matches
- // sufficiently what is currently set. Note that this is only
- // a sanity check in case the two get out of sync; this should
- // never normally happen.
- final long identity = mInjector.binderClearCallingIdentity();
- try {
- int actualPasswordQuality = mLockPatternUtils.getActivePasswordQuality(userHandle);
- if (actualPasswordQuality < policy.mActivePasswordQuality) {
- Slog.w(LOG_TAG, "Active password quality 0x"
- + Integer.toHexString(policy.mActivePasswordQuality)
- + " does not match actual quality 0x"
- + Integer.toHexString(actualPasswordQuality));
- policy.mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- policy.mActivePasswordLength = 0;
- policy.mActivePasswordUpperCase = 0;
- policy.mActivePasswordLowerCase = 0;
- policy.mActivePasswordLetters = 0;
- policy.mActivePasswordNumeric = 0;
- policy.mActivePasswordSymbols = 0;
- policy.mActivePasswordNonLetter = 0;
- }
- } finally {
- mInjector.binderRestoreCallingIdentity(identity);
+ // Might need to upgrade the file by rewriting it
+ if (needsRewrite) {
+ saveSettingsLocked(userHandle);
}
validatePasswordOwnerLocked(policy);
@@ -3758,6 +3747,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private boolean isActivePasswordSufficientForUserLocked(
DevicePolicyData policy, int userHandle, boolean parent) {
+ enforceUserUnlocked(userHandle, parent);
+
final int requiredPasswordQuality = getPasswordQuality(null, userHandle, parent);
if (policy.mActivePasswordQuality < requiredPasswordQuality) {
return false;
@@ -4832,40 +4823,66 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return;
}
enforceFullCrossUsersPermission(userHandle);
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+
+ // If the managed profile doesn't have a separate password, set the metrics to default
+ if (isManagedProfile(userHandle) && !isSeparateProfileChallengeEnabled(userHandle)) {
+ quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ length = 0;
+ letters = 0;
+ uppercase = 0;
+ lowercase = 0;
+ numbers = 0;
+ symbols = 0;
+ nonletter = 0;
+ }
+
+ validateQualityConstant(quality);
+ DevicePolicyData policy = getUserData(userHandle);
+ synchronized (this) {
+ policy.mActivePasswordQuality = quality;
+ policy.mActivePasswordLength = length;
+ policy.mActivePasswordLetters = letters;
+ policy.mActivePasswordLowerCase = lowercase;
+ policy.mActivePasswordUpperCase = uppercase;
+ policy.mActivePasswordNumeric = numbers;
+ policy.mActivePasswordSymbols = symbols;
+ policy.mActivePasswordNonLetter = nonletter;
+ }
+ }
+
+ @Override
+ public void reportPasswordChanged(int userId) {
+ if (!mHasFeature) {
+ return;
+ }
+ enforceFullCrossUsersPermission(userId);
// Managed Profile password can only be changed when it has a separate challenge.
- if (!isSeparateProfileChallengeEnabled(userHandle)) {
- enforceNotManagedProfile(userHandle, "set the active password");
+ if (!isSeparateProfileChallengeEnabled(userId)) {
+ enforceNotManagedProfile(userId, "set the active password");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
- validateQualityConstant(quality);
- DevicePolicyData policy = getUserData(userHandle);
+ DevicePolicyData policy = getUserData(userId);
long ident = mInjector.binderClearCallingIdentity();
try {
synchronized (this) {
- policy.mActivePasswordQuality = quality;
- policy.mActivePasswordLength = length;
- policy.mActivePasswordLetters = letters;
- policy.mActivePasswordLowerCase = lowercase;
- policy.mActivePasswordUpperCase = uppercase;
- policy.mActivePasswordNumeric = numbers;
- policy.mActivePasswordSymbols = symbols;
- policy.mActivePasswordNonLetter = nonletter;
policy.mFailedPasswordAttempts = 0;
- saveSettingsLocked(userHandle);
- updatePasswordExpirationsLocked(userHandle);
- setExpirationAlarmCheckLocked(mContext, userHandle, /* parent */ false);
+ saveSettingsLocked(userId);
+ updatePasswordExpirationsLocked(userId);
+ setExpirationAlarmCheckLocked(mContext, userId, /* parent */ false);
// Send a broadcast to each profile using this password as its primary unlock.
sendAdminCommandForLockscreenPoliciesLocked(
DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
- DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userId);
}
- removeCaApprovalsIfNeeded(userHandle);
+ removeCaApprovalsIfNeeded(userId);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
@@ -6454,6 +6471,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"User must be running and unlocked");
}
+ private void enforceUserUnlocked(int userId, boolean parent) {
+ if (parent) {
+ enforceUserUnlocked(getProfileParentId(userId));
+ } else {
+ enforceUserUnlocked(userId);
+ }
+ }
+
private void enforceManageUsers() {
final int callingUid = mInjector.binderGetCallingUid();
if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0de6b7790856..05071ad2eee7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -162,6 +162,8 @@ public final class SystemServer {
"com.google.android.clockwork.bluetooth.WearBluetoothService";
private static final String WEAR_WIFI_MEDIATOR_SERVICE_CLASS =
"com.google.android.clockwork.wifi.WearWifiMediatorService";
+ private static final String WEAR_CELLULAR_MEDIATOR_SERVICE_CLASS =
+ "com.google.android.clockwork.cellular.WearCellularMediatorService";
private static final String WEAR_TIME_SERVICE_CLASS =
"com.google.android.clockwork.time.WearTimeService";
private static final String ACCOUNT_SERVICE_CLASS =
@@ -1186,6 +1188,9 @@ public final class SystemServer {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
mSystemServiceManager.startService(WEAR_BLUETOOTH_SERVICE_CLASS);
mSystemServiceManager.startService(WEAR_WIFI_MEDIATOR_SERVICE_CLASS);
+ if (SystemProperties.getBoolean("config.enable_cellmediator", false)) {
+ mSystemServiceManager.startService(WEAR_CELLULAR_MEDIATOR_SERVICE_CLASS);
+ }
if (!disableNonCoreServices) {
mSystemServiceManager.startService(WEAR_TIME_SERVICE_CLASS);
}