summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--core/java/android/accounts/AbstractAccountAuthenticator.java23
-rw-r--r--core/java/android/accounts/AccountManager.java53
-rw-r--r--core/java/android/app/Activity.java16
-rw-r--r--core/java/android/app/ActivityManagerNative.java23
-rw-r--r--core/java/android/app/ApplicationPackageManager.java4
-rw-r--r--core/java/android/app/IActivityManager.java3
-rw-r--r--core/java/android/app/Instrumentation.java11
-rw-r--r--core/java/android/content/Intent.java8
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl2
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java16
-rw-r--r--core/java/com/android/internal/os/KernelWakelockReader.java10
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp1
-rw-r--r--graphics/java/android/graphics/Bitmap.java36
-rw-r--r--libs/hwui/renderstate/RenderState.cpp12
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp9
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java2
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java4
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java2
-rw-r--r--services/core/java/com/android/server/MountService.java14
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java250
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java14
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityRecord.java10
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java9
-rw-r--r--services/core/java/com/android/server/am/BroadcastRecord.java4
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java119
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java8
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java5
-rw-r--r--tests/VoiceInteraction/res/layout/test_interaction.xml13
-rw-r--r--tests/VoiceInteraction/res/values/strings.xml1
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java11
34 files changed, 387 insertions, 378 deletions
diff --git a/api/current.txt b/api/current.txt
index 68ecf968b73a..e16294edb380 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3341,6 +3341,7 @@ package android.app {
method public boolean isImmersive();
method public boolean isTaskRoot();
method public boolean isVoiceInteraction();
+ method public boolean isVoiceInteractionRoot();
method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public boolean moveTaskToBack(boolean);
method public boolean navigateUpTo(android.content.Intent);
diff --git a/api/system-current.txt b/api/system-current.txt
index 2e0613a0d48b..a784378e5f5f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3444,6 +3444,7 @@ package android.app {
method public boolean isImmersive();
method public boolean isTaskRoot();
method public boolean isVoiceInteraction();
+ method public boolean isVoiceInteractionRoot();
method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public boolean moveTaskToBack(boolean);
method public boolean navigateUpTo(android.content.Intent);
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index 9c401c7f6e51..3e4a66dc127c 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -138,9 +138,7 @@ public abstract class AbstractAccountAuthenticator {
new AccountAuthenticatorResponse(response),
accountType, authTokenType, features, options);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- if (result != null) {
- result.keySet(); // force it to be unparcelled
- }
+ result.keySet(); // force it to be unparcelled
Log.v(TAG, "addAccount: result " + AccountManager.sanitizeResult(result));
}
if (result != null) {
@@ -162,9 +160,7 @@ public abstract class AbstractAccountAuthenticator {
final Bundle result = AbstractAccountAuthenticator.this.confirmCredentials(
new AccountAuthenticatorResponse(response), account, options);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- if (result != null) {
- result.keySet(); // force it to be unparcelled
- }
+ result.keySet(); // force it to be unparcelled
Log.v(TAG, "confirmCredentials: result "
+ AccountManager.sanitizeResult(result));
}
@@ -189,9 +185,7 @@ public abstract class AbstractAccountAuthenticator {
result.putString(AccountManager.KEY_AUTH_TOKEN_LABEL,
AbstractAccountAuthenticator.this.getAuthTokenLabel(authTokenType));
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- if (result != null) {
- result.keySet(); // force it to be unparcelled
- }
+ result.keySet(); // force it to be unparcelled
Log.v(TAG, "getAuthTokenLabel: result "
+ AccountManager.sanitizeResult(result));
}
@@ -215,9 +209,7 @@ public abstract class AbstractAccountAuthenticator {
new AccountAuthenticatorResponse(response), account,
authTokenType, loginOptions);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- if (result != null) {
- result.keySet(); // force it to be unparcelled
- }
+ result.keySet(); // force it to be unparcelled
Log.v(TAG, "getAuthToken: result " + AccountManager.sanitizeResult(result));
}
if (result != null) {
@@ -242,10 +234,7 @@ public abstract class AbstractAccountAuthenticator {
new AccountAuthenticatorResponse(response), account,
authTokenType, loginOptions);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- // Result may be null.
- if (result != null) {
- result.keySet(); // force it to be unparcelled
- }
+ result.keySet(); // force it to be unparcelled
Log.v(TAG, "updateCredentials: result "
+ AccountManager.sanitizeResult(result));
}
@@ -501,7 +490,7 @@ public abstract class AbstractAccountAuthenticator {
* <ul>
* <li> {@link AccountManager#KEY_INTENT}, or
* <li> {@link AccountManager#KEY_ACCOUNT_NAME} and {@link AccountManager#KEY_ACCOUNT_TYPE} of
- * the account whose credentials were updated, or
+ * the account that was added, or
* <li> {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to
* indicate an error
* </ul>
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 8c84b4d203ee..9394d2c05a2e 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -333,7 +333,7 @@ public class AccountManager {
try {
return mService.getPassword(account);
} catch (RemoteException e) {
- // won't ever happen
+ // will never happen
throw new RuntimeException(e);
}
}
@@ -362,7 +362,7 @@ public class AccountManager {
try {
return mService.getUserData(account, key);
} catch (RemoteException e) {
- // won't ever happen
+ // will never happen
throw new RuntimeException(e);
}
}
@@ -415,10 +415,8 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>Clients of this method that have not been granted the
- * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
- * will only see those accounts managed by AbstractAccountAuthenticators whose
- * signature matches the client.
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#GET_ACCOUNTS}.
*
* @return An array of {@link Account}, one for each account. Empty
* (never null) if no accounts have been added.
@@ -440,10 +438,8 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>Clients of this method that have not been granted the
- * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
- * will only see those accounts managed by AbstractAccountAuthenticators whose
- * signature matches the client.
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#GET_ACCOUNTS}.
*
* @return An array of {@link Account}, one for each account. Empty
* (never null) if no accounts have been added.
@@ -470,7 +466,7 @@ public class AccountManager {
try {
return mService.getAccountsForPackage(packageName, uid);
} catch (RemoteException re) {
- // won't ever happen
+ // possible security exception
throw new RuntimeException(re);
}
}
@@ -487,7 +483,7 @@ public class AccountManager {
try {
return mService.getAccountsByTypeForPackage(type, packageName);
} catch (RemoteException re) {
- // won't ever happen
+ // possible security exception
throw new RuntimeException(re);
}
}
@@ -501,10 +497,9 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>Clients of this method that have not been granted the
- * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
- * will only see those accounts managed by AbstractAccountAuthenticators whose
- * signature matches the client.
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#GET_ACCOUNTS} or share a uid with the
+ * authenticator that owns the account type.
*
* <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
* GET_ACCOUNTS permission is needed for those platforms, irrespective of uid
@@ -590,8 +585,7 @@ public class AccountManager {
* {@link AccountManagerFuture} must not be used on the main thread.
*
* <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#GET_ACCOUNTS} or be a signature
- * match with the AbstractAccountAuthenticator that manages the account.
+ * {@link android.Manifest.permission#GET_ACCOUNTS}.
*
* @param account The {@link Account} to test
* @param features An array of the account features to check
@@ -634,10 +628,9 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>Clients of this method that have not been granted the
- * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
- * will only see those accounts managed by AbstractAccountAuthenticators whose
- * signature matches the client.
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#GET_ACCOUNTS} or share a uid with the
+ * authenticator that owns the account type.
*
* @param type The type of accounts to return, must not be null
* @param features An array of the account features to require,
@@ -708,7 +701,7 @@ public class AccountManager {
try {
return mService.addAccountExplicitly(account, password, userdata);
} catch (RemoteException e) {
- // Can happen if there was a SecurityException was thrown.
+ // won't ever happen
throw new RuntimeException(e);
}
}
@@ -973,7 +966,7 @@ public class AccountManager {
try {
return mService.removeAccountExplicitly(account);
} catch (RemoteException e) {
- // May happen if the caller doesn't match the signature of the authenticator.
+ // won't ever happen
throw new RuntimeException(e);
}
}
@@ -1121,7 +1114,7 @@ public class AccountManager {
try {
mService.setUserData(account, key, value);
} catch (RemoteException e) {
- // Will happen if there is not signature match.
+ // won't ever happen
throw new RuntimeException(e);
}
}
@@ -1740,7 +1733,7 @@ public class AccountManager {
* with these fields if an activity was supplied and the account
* credentials were successfully updated:
* <ul>
- * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account
+ * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account created
* <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
* </ul>
*
@@ -2508,13 +2501,11 @@ public class AccountManager {
* listeners are added in an Activity or Service's {@link Activity#onCreate}
* and removed in {@link Activity#onDestroy}.
*
- * <p>The listener will only be informed of accounts that would be returned
- * to the caller via {@link #getAccounts()}. Typically this means that to
- * get any accounts, the caller will need to be grated the GET_ACCOUNTS
- * permission.
- *
* <p>It is safe to call this method from the main thread.
*
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#GET_ACCOUNTS}.
+ *
* @param listener The listener to send notifications to
* @param handler {@link Handler} identifying the thread to use
* for notifications, null for the main thread
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index bdea6088c529..3c8af0d5444a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1229,6 +1229,22 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Like {@link #isVoiceInteraction}, but only returns true if this is also the root
+ * of a voice interaction. That is, returns true if this activity was directly
+ * started by the voice interaction service as the initiation of a voice interaction.
+ * Otherwise, for example if it was started by another activity while under voice
+ * interaction, returns false.
+ */
+ public boolean isVoiceInteractionRoot() {
+ try {
+ return mVoiceInteractor != null
+ && ActivityManagerNative.getDefault().isRootVoiceInteraction(mToken);
+ } catch (RemoteException e) {
+ }
+ return false;
+ }
+
+ /**
* Retrieve the active {@link VoiceInteractor} that the user is going through to
* interact with this activity.
*/
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b758a7a5493d..e144c297f50e 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2582,6 +2582,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeInt(res ? 1 : 0);
return true;
}
+
+ case IS_ROOT_VOICE_INTERACTION_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ boolean res = isRootVoiceInteraction(token);
+ reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -5962,5 +5971,19 @@ class ActivityManagerProxy implements IActivityManager
return res != 0;
}
+ @Override
+ public boolean isRootVoiceInteraction(IBinder token) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ mRemote.transact(IS_ROOT_VOICE_INTERACTION_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int res = reply.readInt();
+ data.recycle();
+ reply.recycle();
+ return res != 0;
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index dbe91f97dfbf..0adce5dc193d 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -777,7 +777,9 @@ final class ApplicationPackageManager extends PackageManager {
public List<ProviderInfo> queryContentProviders(String processName,
int uid, int flags) {
try {
- return mPM.queryContentProviders(processName, uid, flags);
+ ParceledListSlice<ProviderInfo> slice
+ = mPM.queryContentProviders(processName, uid, flags);
+ return slice != null ? slice.getList() : null;
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 9ebbb9b9a671..90216af3745c 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -515,6 +515,8 @@ public interface IActivityManager extends IInterface {
public boolean setProcessMemoryTrimLevel(String process, int uid, int level)
throws RemoteException;
+ public boolean isRootVoiceInteraction(IBinder token) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -861,4 +863,5 @@ public interface IActivityManager extends IInterface {
int IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION
= IBinder.FIRST_CALL_TRANSACTION+299;
int SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+300;
+ int IS_ROOT_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+301;
}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index c2d901dfa058..69b8b9510b3a 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1810,9 +1810,14 @@ public class Instrumentation {
throw new SecurityException(
"Starting under voice control not allowed for: " + intent);
case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
- throw new SecurityException(
- "Not allowed to start background user activity that shouldn't be"
- + " displayed for all users.");
+ // Fail silently for this case so we don't break current apps.
+ // TODO(b/22929608): Instead of failing silently or throwing an exception,
+ // we should properly position the activity in the stack (i.e. behind all current
+ // user activity/task) and not change the positioning of stacks.
+ Log.e(TAG,
+ "Not allowed to start background user activity that shouldn't be displayed"
+ + " for all users. Failing silently...");
+ break;
default:
throw new AndroidRuntimeException("Unknown error code "
+ res + " when starting " + intent);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index aaaa745bc2da..ec443cddf99b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1782,14 +1782,6 @@ public class Intent implements Parcelable, Cloneable {
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ALARM_CHANGED = "android.intent.action.ALARM_CHANGED";
/**
- * Sync State Changed Action: This is broadcast when the sync starts or stops or when one has
- * been failing for a long time. It is used by the SyncManager and the StatusBar service.
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_SYNC_STATE_CHANGED
- = "android.intent.action.SYNC_STATE_CHANGED";
- /**
* Broadcast Action: This is broadcast once, after the system has finished
* booting. It can be used to perform application-specific initialization,
* such as installing alarms. You must hold the
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 03366455cda8..a5e9faf7b1b9 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -203,7 +203,7 @@ interface IPackageManager {
void querySyncProviders(inout List<String> outNames,
inout List<ProviderInfo> outInfo);
- List<ProviderInfo> queryContentProviders(
+ ParceledListSlice queryContentProviders(
String processName, int uid, int flags);
InstrumentationInfo getInstrumentationInfo(
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index e7c58f45c18c..4f42ed994f32 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -7915,6 +7915,8 @@ public final class BatteryStatsImpl extends BatteryStats {
return;
}
+ // Record whether we've seen a non-zero time (for debugging b/22716723).
+ boolean seenNonZeroTime = false;
for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
String name = ent.getKey();
KernelWakelockStats.Entry kws = ent.getValue();
@@ -7928,17 +7930,31 @@ public final class BatteryStatsImpl extends BatteryStats {
kwlt.updateCurrentReportedCount(kws.mCount);
kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
kwlt.setUpdateVersion(kws.mVersion);
+
+ if (kws.mVersion != wakelockStats.kernelWakelockVersion)
+ seenNonZeroTime |= kws.mTotalTime > 0;
}
+ int numWakelocksSetStale = 0;
if (wakelockStats.size() != mKernelWakelockStats.size()) {
// Set timers to stale if they didn't appear in /proc/wakelocks this time.
for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
SamplingTimer st = ent.getValue();
if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
st.setStale();
+ numWakelocksSetStale++;
}
}
}
+
+ if (!seenNonZeroTime) {
+ Slog.wtf(TAG, "All kernel wakelocks had time of zero");
+ }
+
+ if (numWakelocksSetStale == mKernelWakelockStats.size()) {
+ Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
+ wakelockStats.kernelWakelockVersion);
+ }
}
// We use an anonymous class to access these variables,
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index 0369c3ff248d..6654ea5683e3 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -75,6 +75,8 @@ public class KernelWakelockReader {
is = new FileInputStream(sWakeupSourceFile);
wakeup_sources = true;
} catch (java.io.FileNotFoundException e2) {
+ Slog.wtf(TAG, "neither " + sWakelockFile + " nor " +
+ sWakeupSourceFile + " exists");
return null;
}
}
@@ -82,6 +84,7 @@ public class KernelWakelockReader {
len = is.read(buffer);
is.close();
} catch (java.io.IOException e) {
+ Slog.wtf(TAG, "failed to read kernel wakelocks", e);
return null;
}
@@ -171,6 +174,13 @@ public class KernelWakelockReader {
numUpdatedWlNames++;
}
}
+ } else if (!parsed) {
+ try {
+ Slog.wtf(TAG, "Failed to parse proc line: " +
+ new String(wlBuffer, startIndex, endIndex - startIndex));
+ } catch (Exception e) {
+ Slog.wtf(TAG, "Failed to parse proc line!");
+ }
}
startIndex = endIndex;
}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 670d3c01e030..fbe3ececc348 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -218,7 +218,6 @@ int Bitmap::getAshmemFd() const {
}
const SkImageInfo& Bitmap::info() const {
- assertValid();
return mPixelRef->info();
}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 8ad7c12c342e..3e4d93bb3df9 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -23,6 +23,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.Trace;
import android.util.DisplayMetrics;
+import android.util.Log;
import dalvik.system.VMRuntime;
@@ -33,6 +34,8 @@ import java.nio.IntBuffer;
import java.nio.ShortBuffer;
public final class Bitmap implements Parcelable {
+ private static final String TAG = "Bitmap";
+
/**
* Indicates that the bitmap was created for an unknown pixel density.
*
@@ -159,6 +162,9 @@ public final class Bitmap implements Parcelable {
* @see #DENSITY_NONE
*/
public int getDensity() {
+ if (mRecycled) {
+ Log.w(TAG, "Called getDensity() on a recycle()'d bitmap! This is undefined behavior!");
+ }
return mDensity;
}
@@ -330,7 +336,9 @@ public final class Bitmap implements Parcelable {
* @return The current generation ID for this bitmap.
*/
public int getGenerationId() {
- if (mRecycled) return 0;
+ if (mRecycled) {
+ Log.w(TAG, "Called getGenerationId() on a recycle()'d bitmap! This is undefined behavior!");
+ }
return nativeGenerationId(mFinalizer.mNativeBitmap);
}
@@ -1057,7 +1065,9 @@ public final class Bitmap implements Parcelable {
* @see BitmapFactory.Options#inPremultiplied
*/
public final boolean isPremultiplied() {
- if (mRecycled) return false;
+ if (mRecycled) {
+ Log.w(TAG, "Called isPremultiplied() on a recycle()'d bitmap! This is undefined behavior!");
+ }
return nativeIsPremultiplied(mFinalizer.mNativeBitmap);
}
@@ -1089,11 +1099,17 @@ public final class Bitmap implements Parcelable {
/** Returns the bitmap's width */
public final int getWidth() {
+ if (mRecycled) {
+ Log.w(TAG, "Called getWidth() on a recycle()'d bitmap! This is undefined behavior!");
+ }
return mWidth;
}
/** Returns the bitmap's height */
public final int getHeight() {
+ if (mRecycled) {
+ Log.w(TAG, "Called getHeight() on a recycle()'d bitmap! This is undefined behavior!");
+ }
return mHeight;
}
@@ -1176,7 +1192,9 @@ public final class Bitmap implements Parcelable {
* @return number of bytes between rows of the native bitmap pixels.
*/
public final int getRowBytes() {
- if (mRecycled) return 0;
+ if (mRecycled) {
+ Log.w(TAG, "Called getRowBytes() on a recycle()'d bitmap! This is undefined behavior!");
+ }
return nativeRowBytes(mFinalizer.mNativeBitmap);
}
@@ -1220,7 +1238,9 @@ public final class Bitmap implements Parcelable {
* that config, otherwise return null.
*/
public final Config getConfig() {
- if (mRecycled) return Config.ARGB_8888;
+ if (mRecycled) {
+ Log.w(TAG, "Called getConfig() on a recycle()'d bitmap! This is undefined behavior!");
+ }
return Config.nativeToConfig(nativeConfig(mFinalizer.mNativeBitmap));
}
@@ -1233,7 +1253,9 @@ public final class Bitmap implements Parcelable {
* it will return true by default.
*/
public final boolean hasAlpha() {
- if (mRecycled) return false;
+ if (mRecycled) {
+ Log.w(TAG, "Called hasAlpha() on a recycle()'d bitmap! This is undefined behavior!");
+ }
return nativeHasAlpha(mFinalizer.mNativeBitmap);
}
@@ -1270,7 +1292,9 @@ public final class Bitmap implements Parcelable {
* @see #setHasMipMap(boolean)
*/
public final boolean hasMipMap() {
- if (mRecycled) return false;
+ if (mRecycled) {
+ Log.w(TAG, "Called hasMipMap() on a recycle()'d bitmap! This is undefined behavior!");
+ }
return nativeHasMipMap(mFinalizer.mNativeBitmap);
}
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 3ebd57b33c81..1e39bfa4b583 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -124,9 +124,15 @@ void RenderState::bindFramebuffer(GLuint fbo) {
}
void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) {
- interruptForFunctorInvoke();
- (*functor)(mode, info);
- resumeFromFunctorInvoke();
+ if (mode == DrawGlInfo::kModeProcessNoContext) {
+ // If there's no context we don't need to interrupt as there's
+ // no gl state to save/restore
+ (*functor)(mode, info);
+ } else {
+ interruptForFunctorInvoke();
+ (*functor)(mode, info);
+ resumeFromFunctorInvoke();
+ }
}
void RenderState::interruptForFunctorInvoke() {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index e472e937316b..6dfb6e811e60 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -229,10 +229,11 @@ void CanvasContext::draw() {
SkRect dirty;
mDamageAccumulator.finish(&dirty);
- if (dirty.isEmpty() && Properties::skipEmptyFrames) {
- mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
- return;
- }
+ // TODO: Re-enable after figuring out cause of b/22592975
+// if (dirty.isEmpty() && Properties::skipEmptyFrames) {
+// mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
+// return;
+// }
mCurrentFrameInfo->markIssueDrawCommandsStart();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 249eaa5d44d3..b0429ef43cf9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -808,7 +808,7 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe
// The pairing dialog now warns of phone-book access for paired devices.
// No separate prompt is displayed after pairing.
if (getPhonebookPermissionChoice() == CachedBluetoothDevice.ACCESS_UNKNOWN) {
- setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_REJECTED);
+ setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_ALLOWED);
}
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 3e9b12266733..73971adaca0c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -42,6 +42,9 @@ import android.os.Build;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemProperties;
@@ -204,9 +207,6 @@ public class SettingsProvider extends ContentProvider {
// We have to call in the user manager with no lock held,
private volatile UserManager mUserManager;
- // We have to call in the app ops manager with no lock held,
- private volatile AppOpsManager mAppOpsManager;
-
// We have to call in the package manager with no lock held,
private volatile PackageManager mPackageManager;
@@ -214,7 +214,6 @@ public class SettingsProvider extends ContentProvider {
public boolean onCreate() {
synchronized (mLock) {
mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
- mAppOpsManager = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mPackageManager = getContext().getPackageManager();
mSettingsRegistry = new SettingsRegistry();
}
@@ -532,7 +531,7 @@ public class SettingsProvider extends ContentProvider {
} while (cursor.moveToNext());
}
- private static final String toDumpString(String s) {
+ private static String toDumpString(String s) {
if (s != null) {
return s;
}
@@ -1158,18 +1157,6 @@ public class SettingsProvider extends ContentProvider {
getCallingPackage());
}
- private void sendNotify(Uri uri, int userId) {
- final long identity = Binder.clearCallingIdentity();
- try {
- getContext().getContentResolver().notifyChange(uri, null, true, userId);
- if (DEBUG) {
- Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri);
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
int targetSdkVersion, String name) {
// If the app targets Lollipop MR1 or older SDK we warn, otherwise crash.
@@ -1390,8 +1377,11 @@ public class SettingsProvider extends ContentProvider {
private final BackupManager mBackupManager;
+ private final Handler mHandler;
+
public SettingsRegistry() {
mBackupManager = new BackupManager(getContext());
+ mHandler = new MyHandler(getContext().getMainLooper());
migrateAllLegacySettingsIfNeeded();
}
@@ -1733,7 +1723,7 @@ public class SettingsProvider extends ContentProvider {
// Inform the backup manager about a data change
if (backedUpDataChanged) {
- mBackupManager.dataChanged();
+ mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
}
// Now send the notification through the content framework.
@@ -1741,7 +1731,9 @@ public class SettingsProvider extends ContentProvider {
final int userId = getUserIdFromKey(key);
Uri uri = getNotificationUriFor(key, name);
- sendNotify(uri, userId);
+ mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
+ userId, 0, uri).sendToTarget();
+
if (isSecureSettingsKey(key)) {
maybeNotifyProfiles(userId, uri, name, sSecureCloneToManagedSettings);
} else if (isSystemSettingsKey(key)) {
@@ -1758,7 +1750,8 @@ public class SettingsProvider extends ContentProvider {
UserInfo profile = profiles.get(i);
// the notification for userId has already been sent.
if (profile.id != userId) {
- sendNotify(uri, profile.id);
+ mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
+ profile.id, 0, uri).sendToTarget();
}
}
}
@@ -1834,6 +1827,33 @@ public class SettingsProvider extends ContentProvider {
}
}
+ private final class MyHandler extends Handler {
+ private static final int MSG_NOTIFY_URI_CHANGED = 1;
+ private static final int MSG_NOTIFY_DATA_CHANGED = 2;
+
+ public MyHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_NOTIFY_URI_CHANGED: {
+ final int userId = msg.arg1;
+ Uri uri = (Uri) msg.obj;
+ getContext().getContentResolver().notifyChange(uri, null, true, userId);
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri);
+ }
+ } break;
+
+ case MSG_NOTIFY_DATA_CHANGED: {
+ mBackupManager.dataChanged();
+ } break;
+ }
+ }
+ }
+
private final class UpgradeController {
private static final int SETTINGS_VERSION = 122;
@@ -1963,9 +1983,11 @@ public class SettingsProvider extends ContentProvider {
currentVersion = 120;
}
- // Before 121, we used a different string encoding logic. We just bump the version
- // here; SettingsState knows how to handle pre-version 120 files.
- currentVersion = 121;
+ if (currentVersion == 120) {
+ // Before 121, we used a different string encoding logic. We just bump the
+ // version here; SettingsState knows how to handle pre-version 120 files.
+ currentVersion = 121;
+ }
if (currentVersion == 121) {
// Version 122: allow OEMs to set a default payment component in resources.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 5d7460460a8b..21cbef21c22a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -79,6 +79,8 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
return;
}
state.value = value;
+ } else {
+ state.value = mFlashlightController.isEnabled();
}
final AnimationIcon icon = state.value ? mEnable : mDisable;
icon.setAllowAnimation(arg instanceof UserBoolean && ((UserBoolean) arg).userInitiated);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index cd1914c55663..29a8f67e4cfe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -93,6 +93,10 @@ public class FlashlightController {
}
}
+ public synchronized boolean isEnabled() {
+ return mFlashlightEnabled;
+ }
+
public synchronized boolean isAvailable() {
return mTorchAvailable;
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 10a4cd1dae89..50bd544a308f 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1506,6 +1506,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
//Unbind
mContext.unbindService(mConnection);
}
+ mBluetoothGatt = null;
}
SystemClock.sleep(100);
@@ -1811,6 +1812,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
//Unbind
mContext.unbindService(mConnection);
}
+ mBluetoothGatt = null;
}
mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 7d26a8f3dab7..7fa1d09144d5 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -559,6 +559,7 @@ class MountService extends IMountService.Stub
private static final int H_FSTRIM = 4;
private static final int H_VOLUME_MOUNT = 5;
private static final int H_VOLUME_BROADCAST = 6;
+ private static final int H_INTERNAL_BROADCAST = 7;
class MountServiceHandler extends Handler {
public MountServiceHandler(Looper looper) {
@@ -655,6 +656,13 @@ class MountService extends IMountService.Stub
}
break;
}
+ case H_INTERNAL_BROADCAST: {
+ // Internal broadcasts aimed at system components, not for
+ // third-party apps.
+ final Intent intent = (Intent) msg.obj;
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ android.Manifest.permission.WRITE_MEDIA_STORAGE);
+ }
}
}
}
@@ -1126,8 +1134,7 @@ class MountService extends IMountService.Stub
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
- android.Manifest.permission.WRITE_MEDIA_STORAGE);
+ mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
if (latch != null) {
@@ -1239,8 +1246,7 @@ class MountService extends IMountService.Stub
intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
- android.Manifest.permission.WRITE_MEDIA_STORAGE);
+ mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
}
final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 83e8db06d6f1..32fd56ae4c3b 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -527,14 +527,14 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (account == null) throw new IllegalArgumentException("account is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot get secrets for accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -627,14 +627,14 @@ public class AccountManagerService
}
if (account == null) throw new IllegalArgumentException("account is null");
if (key == null) throw new IllegalArgumentException("key is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot get user data for accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -664,32 +664,22 @@ public class AccountManagerService
final long identityToken = clearCallingIdentity();
try {
- return getAuthenticatorTypesInternal(userId);
-
+ Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
+ authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
+ AuthenticatorDescription[] types =
+ new AuthenticatorDescription[authenticatorCollection.size()];
+ int i = 0;
+ for (AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticator
+ : authenticatorCollection) {
+ types[i] = authenticator.type;
+ i++;
+ }
+ return types;
} finally {
restoreCallingIdentity(identityToken);
}
}
- /**
- * Should only be called inside of a clearCallingIdentity block.
- */
- private AuthenticatorDescription[] getAuthenticatorTypesInternal(int userId) {
- Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
- authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
- AuthenticatorDescription[] types =
- new AuthenticatorDescription[authenticatorCollection.size()];
- int i = 0;
- for (AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticator
- : authenticatorCollection) {
- types[i] = authenticator.type;
- i++;
- }
- return types;
- }
-
-
-
private boolean isCrossUser(int callingUid, int userId) {
return (userId != UserHandle.getCallingUserId()
&& callingUid != Process.myUid()
@@ -707,8 +697,7 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (account == null) throw new IllegalArgumentException("account is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot explicitly add accounts of type: %s",
callingUid,
@@ -724,10 +713,12 @@ public class AccountManagerService
*/
// fails if the account already exists
+ int uid = getCallingUid();
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
- return addAccountInternal(accounts, account, password, extras, false, callingUid);
+ return addAccountInternal(accounts, account, password, extras, false, uid);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -803,26 +794,25 @@ public class AccountManagerService
if (account == null) {
throw new IllegalArgumentException("account is null");
}
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot notify authentication for accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
-
+ int userId = Binder.getCallingUserHandle().getIdentifier();
if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
return false;
}
-
+ int user = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
- UserAccounts accounts = getUserAccounts(userId);
- return updateLastAuthenticatedTime(account);
+ UserAccounts accounts = getUserAccounts(user);
} finally {
restoreCallingIdentity(identityToken);
}
+ return updateLastAuthenticatedTime(account);
}
private boolean updateLastAuthenticatedTime(Account account) {
@@ -995,9 +985,8 @@ public class AccountManagerService
if (response == null) throw new IllegalArgumentException("response is null");
if (account == null) throw new IllegalArgumentException("account is null");
if (features == null) throw new IllegalArgumentException("features is null");
+ checkReadAccountsPermitted(callingUid, account.type);
int userId = UserHandle.getCallingUserId();
- checkReadAccountsPermitted(callingUid, account.type, userId);
-
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -1073,14 +1062,14 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (accountToRename == null) throw new IllegalArgumentException("account is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(accountToRename.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(accountToRename.type, callingUid)) {
String msg = String.format(
"uid %s cannot rename accounts of type: %s",
callingUid,
accountToRename.type);
throw new SecurityException(msg);
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -1222,15 +1211,14 @@ public class AccountManagerService
* authenticator. This will let users remove accounts (via Settings in the system) but not
* arbitrary applications (like competing authenticators).
*/
- UserHandle user = new UserHandle(userId);
- if (!isAccountManagedByCaller(account.type, callingUid, user.getIdentifier())
- && !isSystemUid(callingUid)) {
+ if (!isAccountManagedByCaller(account.type, callingUid) && !isSystemUid(callingUid)) {
String msg = String.format(
"uid %s cannot remove accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
+
if (!canUserModifyAccounts(userId)) {
try {
response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
@@ -1247,7 +1235,10 @@ public class AccountManagerService
}
return;
}
+
+ UserHandle user = new UserHandle(userId);
long identityToken = clearCallingIdentity();
+
UserAccounts accounts = getUserAccounts(userId);
cancelNotification(getSigninRequiredNotificationId(accounts, account), user);
synchronized(accounts.credentialsPermissionNotificationIds) {
@@ -1277,7 +1268,6 @@ public class AccountManagerService
+ ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
- int userId = Binder.getCallingUserHandle().getIdentifier();
if (account == null) {
/*
* Null accounts should result in returning false, as per
@@ -1285,18 +1275,22 @@ public class AccountManagerService
*/
Log.e(TAG, "account is null");
return false;
- } else if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ } else if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot explicitly add accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
+
UserAccounts accounts = getUserAccountsForCaller();
+ int userId = Binder.getCallingUserHandle().getIdentifier();
if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
return false;
}
+
logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS);
+
long identityToken = clearCallingIdentity();
try {
return removeAccountInternal(accounts, account);
@@ -1530,14 +1524,14 @@ public class AccountManagerService
}
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot peek the authtokens associated with accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -1558,14 +1552,14 @@ public class AccountManagerService
}
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot set auth tokens associated with accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -1584,14 +1578,14 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (account == null) throw new IllegalArgumentException("account is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot set secrets for accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -1648,14 +1642,14 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (account == null) throw new IllegalArgumentException("account is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot clear passwords for accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -1676,14 +1670,14 @@ public class AccountManagerService
}
if (key == null) throw new IllegalArgumentException("key is null");
if (account == null) throw new IllegalArgumentException("account is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+ if (!isAccountManagedByCaller(account.type, callingUid)) {
String msg = String.format(
"uid %s cannot set user data for accounts of type: %s",
callingUid,
account.type);
throw new SecurityException(msg);
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -1846,8 +1840,8 @@ public class AccountManagerService
// skip the check if customTokens
final int callerUid = Binder.getCallingUid();
- final boolean permissionGranted =
- customTokens || permissionIsGranted(account, authTokenType, callerUid, userId);
+ final boolean permissionGranted = customTokens ||
+ permissionIsGranted(account, authTokenType, callerUid);
// Get the calling package. We will use it for the purpose of caching.
final String callerPkg = loginOptions.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
@@ -2369,14 +2363,14 @@ public class AccountManagerService
}
if (response == null) throw new IllegalArgumentException("response is null");
if (accountType == null) throw new IllegalArgumentException("accountType is null");
- int userId = UserHandle.getCallingUserId();
- if (!isAccountManagedByCaller(accountType, callingUid, userId) && !isSystemUid(callingUid)) {
+ if (!isAccountManagedByCaller(accountType, callingUid) && !isSystemUid(callingUid)) {
String msg = String.format(
"uid %s cannot edit authenticator properites for account type: %s",
callingUid,
accountType);
throw new SecurityException(msg);
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
@@ -2499,22 +2493,20 @@ public class AccountManagerService
}
/**
- * Returns the accounts visible to the client within the context of a specific user
+ * Returns the accounts for a specific user
* @hide
*/
public Account[] getAccounts(int userId) {
int callingUid = Binder.getCallingUid();
- List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId);
- if (visibleAccountTypes.isEmpty()) {
+ if (!isReadAccountsPermitted(callingUid, null)) {
return new Account[0];
}
long identityToken = clearCallingIdentity();
try {
- return getAccountsInternal(
- userId,
- callingUid,
- null, // packageName
- visibleAccountTypes);
+ UserAccounts accounts = getUserAccounts(userId);
+ synchronized (accounts.cacheLock) {
+ return getAccountsFromCacheLocked(accounts, null, callingUid, null);
+ }
} finally {
restoreCallingIdentity(identityToken);
}
@@ -2596,52 +2588,22 @@ public class AccountManagerService
callingUid = packageUid;
}
- List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId);
- if (visibleAccountTypes.isEmpty()
- || (type != null && !visibleAccountTypes.contains(type))) {
+ // Authenticators should be able to see their own accounts regardless of permissions.
+ if (TextUtils.isEmpty(type) && !isReadAccountsPermitted(callingUid, type)) {
return new Account[0];
- } else if (visibleAccountTypes.contains(type)) {
- // Prune the list down to just the requested type.
- visibleAccountTypes = new ArrayList<>();
- visibleAccountTypes.add(type);
- } // else aggregate all the visible accounts (it won't matter if the list is empty).
+ }
long identityToken = clearCallingIdentity();
try {
- return getAccountsInternal(
- userId,
- callingUid,
- callingPackage,
- visibleAccountTypes);
+ UserAccounts accounts = getUserAccounts(userId);
+ synchronized (accounts.cacheLock) {
+ return getAccountsFromCacheLocked(accounts, type, callingUid, callingPackage);
+ }
} finally {
restoreCallingIdentity(identityToken);
}
}
- private Account[] getAccountsInternal(
- int userId,
- int callingUid,
- String callingPackage,
- List<String> visibleAccountTypes) {
- UserAccounts accounts = getUserAccounts(userId);
- synchronized (accounts.cacheLock) {
- UserAccounts userAccounts = getUserAccounts(userId);
- ArrayList<Account> visibleAccounts = new ArrayList<>();
- for (String visibleType : visibleAccountTypes) {
- Account[] accountsForType = getAccountsFromCacheLocked(
- userAccounts, visibleType, callingUid, callingPackage);
- if (accountsForType != null) {
- visibleAccounts.addAll(Arrays.asList(accountsForType));
- }
- }
- Account[] result = new Account[visibleAccounts.size()];
- for (int i = 0; i < visibleAccounts.size(); i++) {
- result[i] = visibleAccounts.get(i);
- }
- return result;
- }
- }
-
@Override
public boolean addSharedAccountAsUser(Account account, int userId) {
userId = handleIncomingUser(userId);
@@ -2777,12 +2739,8 @@ public class AccountManagerService
}
if (response == null) throw new IllegalArgumentException("response is null");
if (type == null) throw new IllegalArgumentException("accountType is null");
- int userId = UserHandle.getCallingUserId();
-
- List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId);
- if (!visibleAccountTypes.contains(type)) {
+ if (!isReadAccountsPermitted(callingUid, type)) {
Bundle result = new Bundle();
- // Need to return just the accounts that are from matching signatures.
result.putParcelableArray(AccountManager.KEY_ACCOUNTS, new Account[0]);
try {
response.onResult(result);
@@ -2791,6 +2749,7 @@ public class AccountManagerService
}
return;
}
+ int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
UserAccounts userAccounts = getUserAccounts(userId);
@@ -2804,11 +2763,7 @@ public class AccountManagerService
onResult(response, result);
return;
}
- new GetAccountsByTypeAndFeatureSession(
- userAccounts,
- response,
- type,
- features,
+ new GetAccountsByTypeAndFeatureSession(userAccounts, response, type, features,
callingUid).bind();
} finally {
restoreCallingIdentity(identityToken);
@@ -3741,11 +3696,10 @@ public class AccountManagerService
return false;
}
- private boolean permissionIsGranted(
- Account account, String authTokenType, int callerUid, int userId) {
+ private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
final boolean isPrivileged = isPrivileged(callerUid);
final boolean fromAuthenticator = account != null
- && isAccountManagedByCaller(account.type, callerUid, userId);
+ && isAccountManagedByCaller(account.type, callerUid);
final boolean hasExplicitGrants = account != null
&& hasExplicitlyGrantedPermission(account, authTokenType, callerUid);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -3757,45 +3711,23 @@ public class AccountManagerService
return fromAuthenticator || hasExplicitGrants || isPrivileged;
}
- private boolean isAccountVisibleToCaller(String accountType, int callingUid, int userId) {
+ private boolean isAccountManagedByCaller(String accountType, int callingUid) {
if (accountType == null) {
return false;
- } else {
- return getTypesVisibleToCaller(callingUid, userId).contains(accountType);
}
- }
-
- private boolean isAccountManagedByCaller(String accountType, int callingUid, int userId) {
- if (accountType == null) {
- return false;
- } else {
- return getTypesManagedByCaller(callingUid, userId).contains(accountType);
- }
- }
-
- private List<String> getTypesVisibleToCaller(int callingUid, int userId) {
- boolean isPermitted =
- isPermitted(callingUid, Manifest.permission.GET_ACCOUNTS,
- Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
- Log.i(TAG, String.format("getTypesVisibleToCaller: isPermitted? %s", isPermitted));
- return getTypesForCaller(callingUid, userId, isPermitted);
- }
-
- private List<String> getTypesManagedByCaller(int callingUid, int userId) {
- return getTypesForCaller(callingUid, userId, false);
- }
-
- private List<String> getTypesForCaller(
- int callingUid, int userId, boolean isOtherwisePermitted) {
- List<String> managedAccountTypes = new ArrayList<>();
+ final int callingUserId = UserHandle.getUserId(callingUid);
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
- mAuthenticatorCache.getAllServices(userId)) {
- final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid);
- if (isOtherwisePermitted || sigChk == PackageManager.SIGNATURE_MATCH) {
- managedAccountTypes.add(serviceInfo.type.type);
+ mAuthenticatorCache.getAllServices(callingUserId)) {
+ if (serviceInfo.type.type.equals(accountType)) {
+ /*
+ * We can't simply compare uids because uids can be recycled before the
+ * authenticator cache is updated.
+ */
+ final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid);
+ return sigChk == PackageManager.SIGNATURE_MATCH;
}
}
- return managedAccountTypes;
+ return false;
}
private boolean isAccountPresentForCaller(String accountName, String accountType) {
@@ -3860,12 +3792,28 @@ public class AccountManagerService
return false;
}
+ private boolean isReadAccountsPermitted(int callingUid, String accountType) {
+ /*
+ * Settings app (which is in the same uid as AcocuntManagerService), apps with the
+ * GET_ACCOUNTS permission or authenticators that own the account type should be able to
+ * access accounts of the specified account.
+ */
+ boolean isPermitted =
+ isPermitted(callingUid, Manifest.permission.GET_ACCOUNTS,
+ Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
+ boolean isAccountManagedByCaller = isAccountManagedByCaller(accountType, callingUid);
+ Log.w(TAG, String.format(
+ "isReadAccountPermitted: isPermitted: %s, isAM: %s",
+ isPermitted,
+ isAccountManagedByCaller));
+ return isPermitted || isAccountManagedByCaller;
+ }
+
/** Succeeds if any of the specified permissions are granted. */
private void checkReadAccountsPermitted(
int callingUid,
- String accountType,
- int userId) {
- if (!isAccountVisibleToCaller(accountType, callingUid, userId)) {
+ String accountType) {
+ if (!isReadAccountsPermitted(callingUid, accountType)) {
String msg = String.format(
"caller uid %s cannot access %s accounts",
callingUid,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 783dea5acc5c..b8d32c3afb93 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6552,6 +6552,17 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
+ public boolean isRootVoiceInteraction(IBinder token) {
+ synchronized(this) {
+ ActivityRecord r = ActivityRecord.isInStackLocked(token);
+ if (r == null) {
+ return false;
+ }
+ return r.rootVoiceInteraction;
+ }
+ }
+
+ @Override
public IIntentSender getIntentSender(int type,
String packageName, IBinder token, String resultWho,
int requestCode, Intent[] intents, String[] resolvedTypes,
@@ -9154,9 +9165,10 @@ public final class ActivityManagerService extends ActivityManagerNative
private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
List<ProviderInfo> providers = null;
try {
- providers = AppGlobals.getPackageManager().
+ ParceledListSlice<ProviderInfo> slice = AppGlobals.getPackageManager().
queryContentProviders(app.processName, app.uid,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
+ providers = slice != null ? slice.getList() : null;
} catch (RemoteException ex) {
}
if (DEBUG_MU) Slog.v(TAG_MU,
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 0957eb5af120..3de200954b15 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -107,6 +107,7 @@ final class ActivityRecord {
boolean fullscreen; // covers the full screen?
final boolean noDisplay; // activity is not displayed?
final boolean componentSpecified; // did caller specifiy an explicit component?
+ final boolean rootVoiceInteraction; // was this the root activity of a voice interaction?
static final int APPLICATION_ACTIVITY_TYPE = 0;
static final int HOME_ACTIVITY_TYPE = 1;
@@ -207,6 +208,9 @@ final class ActivityRecord {
pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
pw.print(" componentSpecified="); pw.print(componentSpecified);
pw.print(" mActivityType="); pw.println(mActivityType);
+ if (rootVoiceInteraction) {
+ pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
+ }
pw.print(prefix); pw.print("compat="); pw.print(compat);
pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
@@ -432,7 +436,8 @@ final class ActivityRecord {
int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
ActivityRecord _resultTo, String _resultWho, int _reqCode,
- boolean _componentSpecified, ActivityStackSupervisor supervisor,
+ boolean _componentSpecified, boolean _rootVoiceInteraction,
+ ActivityStackSupervisor supervisor,
ActivityContainer container, Bundle options) {
service = _service;
appToken = new Token(this, service);
@@ -444,6 +449,7 @@ final class ActivityRecord {
shortComponentName = _intent.getComponent().flattenToShortString();
resolvedType = _resolvedType;
componentSpecified = _componentSpecified;
+ rootVoiceInteraction = _rootVoiceInteraction;
configuration = _configuration;
stackConfigOverride = (container != null)
? container.mStack.mOverrideConfig : Configuration.EMPTY;
@@ -1257,7 +1263,7 @@ final class ActivityRecord {
}
final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid,
launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(),
- null, null, 0, componentSpecified, stackSupervisor, null, null);
+ null, null, 0, componentSpecified, false, stackSupervisor, null, null);
r.persistentState = persistentState;
r.taskDescription = taskDescription;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0be2f6f4ec61..71fd49b71c98 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1506,6 +1506,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
&& sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
try {
+ intent.addCategory(Intent.CATEGORY_VOICE);
if (!AppGlobals.getPackageManager().activitySupportsIntent(
intent.getComponent(), intent, resolvedType)) {
err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
@@ -1626,7 +1627,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
- requestCode, componentSpecified, this, container, options);
+ requestCode, componentSpecified, voiceSession != null, this, container, options);
if (outActivity != null) {
outActivity[0] = r;
}
@@ -3721,19 +3722,19 @@ public final class ActivityStackSupervisor implements DisplayListener {
@Override
public void onDisplayAdded(int displayId) {
- Slog.v(TAG, "Display added displayId=" + displayId);
+ if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0));
}
@Override
public void onDisplayRemoved(int displayId) {
- Slog.v(TAG, "Display removed displayId=" + displayId);
+ if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0));
}
@Override
public void onDisplayChanged(int displayId) {
- Slog.v(TAG, "Display changed displayId=" + displayId);
+ if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
}
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index a7e6471d58a1..1fbfd9feff8e 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -240,8 +240,12 @@ final class BroadcastRecord extends Binder {
}
didSomething = true;
receivers.remove(i);
+ if (i < nextReceiver) {
+ nextReceiver--;
+ }
}
}
+ nextReceiver = Math.min(nextReceiver, receivers.size());
return didSomething;
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 658f6f858acc..c998c2c28aac 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -297,7 +297,6 @@ public class SyncManager {
private final UserManager mUserManager;
private static final long SYNC_ALARM_TIMEOUT_MIN = 30 * 1000; // 30 seconds
- private static final long SYNC_ALARM_TIMEOUT_MAX = 2 * 60 * 60 * 1000; // two hours
private List<UserInfo> getAllUsers() {
return mUserManager.getUsers();
@@ -1478,9 +1477,9 @@ public class SyncManager {
final long now = SystemClock.elapsedRealtime();
pw.print("now: "); pw.print(now);
pw.println(" (" + formatTime(System.currentTimeMillis()) + ")");
- pw.print("offset: "); pw.print(DateUtils.formatElapsedTime(mSyncRandomOffsetMillis/1000));
+ pw.print("offset: "); pw.print(DateUtils.formatElapsedTime(mSyncRandomOffsetMillis / 1000));
pw.println(" (HH:MM:SS)");
- pw.print("uptime: "); pw.print(DateUtils.formatElapsedTime(now/1000));
+ pw.print("uptime: "); pw.print(DateUtils.formatElapsedTime(now / 1000));
pw.println(" (HH:MM:SS)");
pw.print("time spent syncing: ");
pw.print(DateUtils.formatElapsedTime(
@@ -1497,11 +1496,6 @@ public class SyncManager {
pw.println("no alarm is scheduled (there had better not be any pending syncs)");
}
- pw.print("notification info: ");
- final StringBuilder sb = new StringBuilder();
- mSyncHandler.mSyncNotificationInfo.toString(sb);
- pw.println(sb.toString());
-
pw.println();
pw.println("Active Syncs: " + mActiveSyncContexts.size());
final PackageManager pm = mContext.getPackageManager();
@@ -1514,8 +1508,8 @@ public class SyncManager {
pw.println();
}
+ final StringBuilder sb = new StringBuilder();
synchronized (mSyncQueue) {
- sb.setLength(0);
mSyncQueue.dump(sb);
// Dump Pending Operations.
getSyncStorageEngine().dumpPendingOperations(sb);
@@ -2349,7 +2343,6 @@ public class SyncManager {
}
} finally {
- manageSyncNotificationLocked();
manageSyncAlarmLocked(earliestFuturePollTime, nextPendingSyncTime);
mSyncTimeTracker.update();
mSyncManagerWakeLock.release();
@@ -3169,67 +3162,6 @@ public class SyncManager {
throw new IllegalStateException("we are not in an error state, " + syncResult);
}
- private void manageSyncNotificationLocked() {
- boolean shouldCancel;
- boolean shouldInstall;
-
- if (mActiveSyncContexts.isEmpty()) {
- mSyncNotificationInfo.startTime = null;
-
- // we aren't syncing. if the notification is active then remember that we need
- // to cancel it and then clear out the info
- shouldCancel = mSyncNotificationInfo.isActive;
- shouldInstall = false;
- } else {
- // we are syncing
- final long now = SystemClock.elapsedRealtime();
- if (mSyncNotificationInfo.startTime == null) {
- mSyncNotificationInfo.startTime = now;
- }
-
- // there are three cases:
- // - the notification is up: do nothing
- // - the notification is not up but it isn't time yet: don't install
- // - the notification is not up and it is time: need to install
-
- if (mSyncNotificationInfo.isActive) {
- shouldInstall = shouldCancel = false;
- } else {
- // it isn't currently up, so there is nothing to cancel
- shouldCancel = false;
-
- final boolean timeToShowNotification =
- now > mSyncNotificationInfo.startTime + SYNC_NOTIFICATION_DELAY;
- if (timeToShowNotification) {
- shouldInstall = true;
- } else {
- // show the notification immediately if this is a manual sync
- shouldInstall = false;
- for (ActiveSyncContext activeSyncContext : mActiveSyncContexts) {
- final boolean manualSync = activeSyncContext.mSyncOperation.extras
- .getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
- if (manualSync) {
- shouldInstall = true;
- break;
- }
- }
- }
- }
- }
-
- if (shouldCancel && !shouldInstall) {
- mNeedSyncActiveNotification = false;
- sendSyncStateIntent();
- mSyncNotificationInfo.isActive = false;
- }
-
- if (shouldInstall) {
- mNeedSyncActiveNotification = true;
- sendSyncStateIntent();
- mSyncNotificationInfo.isActive = true;
- }
- }
-
private void manageSyncAlarmLocked(long nextPeriodicEventElapsedTime,
long nextPendingEventElapsedTime) {
// in each of these cases the sync loop will be kicked, which will cause this
@@ -3238,13 +3170,6 @@ public class SyncManager {
if (mStorageIsLow) return;
if (mDeviceIsIdle) return;
- // When the status bar notification should be raised
- final long notificationTime =
- (!mSyncHandler.mSyncNotificationInfo.isActive
- && mSyncHandler.mSyncNotificationInfo.startTime != null)
- ? mSyncHandler.mSyncNotificationInfo.startTime + SYNC_NOTIFICATION_DELAY
- : Long.MAX_VALUE;
-
// When we should consider canceling an active sync
long earliestTimeoutTime = Long.MAX_VALUE;
for (ActiveSyncContext currentSyncContext : mActiveSyncContexts) {
@@ -3260,24 +3185,14 @@ public class SyncManager {
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "manageSyncAlarm: notificationTime is " + notificationTime);
- }
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "manageSyncAlarm: earliestTimeoutTime is " + earliestTimeoutTime);
- }
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "manageSyncAlarm: nextPeriodicEventElapsedTime is "
+ nextPeriodicEventElapsedTime);
- }
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "manageSyncAlarm: nextPendingEventElapsedTime is "
+ nextPendingEventElapsedTime);
}
- long alarmTime = Math.min(notificationTime, earliestTimeoutTime);
- alarmTime = Math.min(alarmTime, nextPeriodicEventElapsedTime);
+ long alarmTime = Math.min(earliestTimeoutTime, nextPeriodicEventElapsedTime);
alarmTime = Math.min(alarmTime, nextPendingEventElapsedTime);
// Bound the alarm time.
@@ -3288,24 +3203,16 @@ public class SyncManager {
+ alarmTime + ", setting to " + (now + SYNC_ALARM_TIMEOUT_MIN));
}
alarmTime = now + SYNC_ALARM_TIMEOUT_MIN;
- } else if (alarmTime > now + SYNC_ALARM_TIMEOUT_MAX) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "manageSyncAlarm: the alarmTime is too large, "
- + alarmTime + ", setting to " + (now + SYNC_ALARM_TIMEOUT_MIN));
- }
- alarmTime = now + SYNC_ALARM_TIMEOUT_MAX;
}
- // determine if we need to set or cancel the alarm
+ // Determine if we need to set or cancel the alarm
boolean shouldSet = false;
boolean shouldCancel = false;
final boolean alarmIsActive = (mAlarmScheduleTime != null) && (now < mAlarmScheduleTime);
- final boolean needAlarm = alarmTime != Long.MAX_VALUE;
- if (needAlarm) {
- // Need the alarm if
- // - it's currently not set
- // - if the alarm is set in the past.
- if (!alarmIsActive || alarmTime < mAlarmScheduleTime) {
+
+ if (alarmTime != Long.MAX_VALUE) {
+ // Need the alarm if it isn't set or has changed.
+ if (!alarmIsActive || alarmTime != mAlarmScheduleTime) {
shouldSet = true;
}
} else {
@@ -3329,14 +3236,6 @@ public class SyncManager {
}
}
- private void sendSyncStateIntent() {
- Intent syncStateIntent = new Intent(Intent.ACTION_SYNC_STATE_CHANGED);
- syncStateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- syncStateIntent.putExtra("active", mNeedSyncActiveNotification);
- syncStateIntent.putExtra("failing", false);
- mContext.sendBroadcastAsUser(syncStateIntent, UserHandle.OWNER);
- }
-
private void installHandleTooManyDeletesNotification(Account account, String authority,
long numDeletes, int userId) {
if (mNotificationMgr == null) return;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7a6895f542e6..9426b76eba52 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1842,7 +1842,7 @@ public class NotificationManagerService extends SystemService {
}
pw.println(':');
int N;
- final boolean zenOnly = filter != null && filter.zen;
+ final boolean zenOnly = filter.filtered && filter.zen;
if (!zenOnly) {
synchronized (mToastQueue) {
@@ -1864,13 +1864,13 @@ public class NotificationManagerService extends SystemService {
pw.println(" Notification List:");
for (int i=0; i<N; i++) {
final NotificationRecord nr = mNotificationList.get(i);
- if (filter != null && !filter.matches(nr.sbn)) continue;
+ if (filter.filtered && !filter.matches(nr.sbn)) continue;
nr.dump(pw, " ", getContext(), filter.redact);
}
pw.println(" ");
}
- if (filter == null) {
+ if (!filter.filtered) {
N = mLights.size();
if (N > 0) {
pw.println(" Lights List:");
@@ -1911,7 +1911,7 @@ public class NotificationManagerService extends SystemService {
mUsageStats.dump(pw, " ", filter);
}
- if (filter == null || zenOnly) {
+ if (!filter.filtered || zenOnly) {
pw.println("\n Zen Mode:");
pw.print(" mInterruptionFilter="); pw.println(mInterruptionFilter);
mZenModeHelper.dump(pw, " ");
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 68a8e223782a..1d56a0ca0b70 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5435,7 +5435,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
- public List<ProviderInfo> queryContentProviders(String processName,
+ public ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
int uid, int flags) {
ArrayList<ProviderInfo> finalList = null;
// reader
@@ -5467,9 +5467,10 @@ public class PackageManagerService extends IPackageManager.Stub {
if (finalList != null) {
Collections.sort(finalList, mProviderInitOrderSorter);
+ return new ParceledListSlice<ProviderInfo>(finalList);
}
- return finalList;
+ return null;
}
@Override
diff --git a/tests/VoiceInteraction/res/layout/test_interaction.xml b/tests/VoiceInteraction/res/layout/test_interaction.xml
index d1a7ad532abd..277117e3e157 100644
--- a/tests/VoiceInteraction/res/layout/test_interaction.xml
+++ b/tests/VoiceInteraction/res/layout/test_interaction.xml
@@ -39,6 +39,19 @@
android:layout_marginTop="16dp"
android:orientation="horizontal">
+ <Button android:id="@+id/airplane"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/launchAirplane"
+ />
+
+ </LinearLayout>
+
+ <LinearLayout android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:orientation="horizontal">
+
<Button android:id="@+id/complete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/tests/VoiceInteraction/res/values/strings.xml b/tests/VoiceInteraction/res/values/strings.xml
index 29ffe211ce67..c665c23faa63 100644
--- a/tests/VoiceInteraction/res/values/strings.xml
+++ b/tests/VoiceInteraction/res/values/strings.xml
@@ -21,6 +21,7 @@
<string name="tree">Tree</string>
<string name="text">Text</string>
<string name="asyncStructure">(Async structure goes here)</string>
+ <string name="launchAirplane">Launch airplane mode</string>
<string name="confirm">Confirm</string>
<string name="abort">Abort</string>
<string name="complete">Complete</string>
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
index e10d89f0c002..ada0e21e059a 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
@@ -21,6 +21,7 @@ import android.app.VoiceInteractor;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
+import android.provider.Settings;
import android.service.voice.VoiceInteractionService;
import android.util.Log;
import android.view.View;
@@ -39,6 +40,7 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
VoiceInteractor mInteractor;
VoiceInteractor.Request mCurrentRequest = null;
TextView mLog;
+ Button mAirplaneButton;
Button mAbortButton;
Button mCompleteButton;
Button mCommandButton;
@@ -65,6 +67,8 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
setContentView(R.layout.test_interaction);
mLog = (TextView)findViewById(R.id.log);
+ mAirplaneButton = (Button)findViewById(R.id.airplane);
+ mAirplaneButton.setOnClickListener(this);
mAbortButton = (Button)findViewById(R.id.abort);
mAbortButton.setOnClickListener(this);
mCompleteButton = (Button)findViewById(R.id.complete);
@@ -122,7 +126,12 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
@Override
public void onClick(View v) {
- if (v == mAbortButton) {
+ if (v == mAirplaneButton) {
+ Intent intent = new Intent(Settings.ACTION_VOICE_CONTROL_AIRPLANE_MODE);
+ intent.addCategory(Intent.CATEGORY_VOICE);
+ intent.putExtra(Settings.EXTRA_AIRPLANE_MODE_ENABLED, true);
+ startActivity(intent);
+ } else if (v == mAbortButton) {
VoiceInteractor.AbortVoiceRequest req = new TestAbortVoice();
mInteractor.submitRequest(req, REQUEST_ABORT);
} else if (v == mCompleteButton) {