diff options
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) { |