summaryrefslogtreecommitdiffstats
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/android/hardware/camera2/CameraMetadata.java22
-rw-r--r--core/java/android/hardware/camera2/impl/CameraMetadataNative.java14
-rw-r--r--core/java/android/hardware/usb/IUsbManager.aidl3
-rw-r--r--core/java/android/hardware/usb/UsbManager.java15
-rw-r--r--core/java/android/provider/Settings.java6
-rw-r--r--core/java/android/view/ViewRootImpl.java18
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java11
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java11
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java16
-rw-r--r--core/java/com/android/internal/os/KernelWakelockReader.java10
-rw-r--r--core/java/com/android/internal/widget/ResolverDrawerLayout.java28
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp1
-rw-r--r--core/jni/android_hardware_camera2_CameraMetadata.cpp167
-rw-r--r--core/res/res/values/colors_material.xml3
-rw-r--r--core/res/res/values/themes_material.xml12
-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--media/java/android/media/MediaCodec.java142
-rw-r--r--media/java/android/media/MediaCodecInfo.java26
-rw-r--r--media/java/android/media/MediaCodecList.java14
-rw-r--r--media/java/android/media/Ringtone.java3
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java29
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java38
-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--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java33
-rw-r--r--services/core/java/com/android/server/AppOpsService.java8
-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/am/RecentTasks.java10
-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/DefaultPermissionGrantPolicy.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java5
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java43
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java13
-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
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java17
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java11
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.pngbin9786 -> 5188 bytes
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.pngbin636 -> 566 bytes
-rw-r--r--tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java14
65 files changed, 939 insertions, 543 deletions
diff --git a/api/current.txt b/api/current.txt
index 68ecf96..e16294e 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 2e0613a..a784378 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 9c401c7..3e4a66d 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 8c84b4d..9394d2c 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 bdea608..3c8af0d 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 b758a7a..e144c29 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 dbe91f9..0adce5d 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 9ebbb9b..90216af 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 c2d901d..69b8b95 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 aaaa745..ec443cd 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 0336645..a5e9faf 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/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index af1367c..c580083 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -173,6 +173,28 @@ public abstract class CameraMetadata<TKey> {
}
}
+ ArrayList<TKey> vendorKeys = CameraMetadataNative.getAllVendorKeys(keyClass);
+
+ if (vendorKeys != null) {
+ for (TKey k : vendorKeys) {
+ String keyName;
+ if (k instanceof CaptureRequest.Key<?>) {
+ keyName = ((CaptureRequest.Key<?>) k).getName();
+ } else if (k instanceof CaptureResult.Key<?>) {
+ keyName = ((CaptureResult.Key<?>) k).getName();
+ } else if (k instanceof CameraCharacteristics.Key<?>) {
+ keyName = ((CameraCharacteristics.Key<?>) k).getName();
+ } else {
+ continue;
+ }
+
+ if (filterTags == null || Arrays.binarySearch(filterTags,
+ CameraMetadataNative.getTag(keyName)) >= 0) {
+ keyList.add(k);
+ }
+ }
+ }
+
return keyList;
}
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 7e50fd9..12a2910 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1078,6 +1078,7 @@ public class CameraMetadataNative implements Parcelable {
private native synchronized void nativeWriteValues(int tag, byte[] src);
private native synchronized void nativeDump() throws IOException; // dump to ALOGD
+ private static native ArrayList nativeGetAllVendorKeys(Class keyClass);
private static native int nativeGetTagFromKey(String keyName)
throws IllegalArgumentException;
private static native int nativeGetTypeFromTag(int tag)
@@ -1113,6 +1114,19 @@ public class CameraMetadataNative implements Parcelable {
return nativeIsEmpty();
}
+
+ /**
+ * Return a list containing keys of the given key class for all defined vendor tags.
+ *
+ * @hide
+ */
+ public static <K> ArrayList<K> getAllVendorKeys(Class<K> keyClass) {
+ if (keyClass == null) {
+ throw new NullPointerException();
+ }
+ return (ArrayList<K>) nativeGetAllVendorKeys(keyClass);
+ }
+
/**
* Convert a key string into the equivalent native tag.
*
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 80c7b1a..6e4c9de 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -97,9 +97,6 @@ interface IUsbManager
*/
void setUsbDataUnlocked(boolean unlock);
- /* Returns true iff sensitive user data is exposed on the USB connection. */
- boolean isUsbDataUnlocked();
-
/* Allow USB debugging from the attached host. If alwaysAllow is true, add the
* the public key to list of host keys that the user has approved.
*/
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index c88f213..3b3ee52 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -520,21 +520,6 @@ public class UsbManager {
}
/**
- * Returns {@code true} iff access to sensitive USB data is currently allowed when
- * in device mode.
- *
- * {@hide}
- */
- public boolean isUsbDataUnlocked() {
- try {
- return mService.isUsbDataUnlocked();
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in isUsbDataUnlocked", e);
- }
- return false;
- }
-
- /**
* Returns a list of physical USB ports on the device.
* <p>
* This list is guaranteed to contain all dual-role USB Type C ports but it might
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a836cc5..6f98788 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8333,9 +8333,9 @@ public final class Settings {
return true;
case AppOpsManager.MODE_DEFAULT:
// this is the default operating mode after an app's installation
- if (!throwException) {
- return context.checkCallingOrSelfPermission(permissionName) ==
- PackageManager.PERMISSION_GRANTED;
+ if(context.checkCallingOrSelfPermission(permissionName) == PackageManager
+ .PERMISSION_GRANTED) {
+ return true;
}
default:
// this is for all other cases trickled down here...
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 928fe93..6e93a30 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3159,6 +3159,17 @@ public final class ViewRootImpl implements ViewParent,
return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
}
+ private static void forceLayout(View view) {
+ view.forceLayout();
+ if (view instanceof ViewGroup) {
+ ViewGroup group = (ViewGroup) view;
+ final int count = group.getChildCount();
+ for (int i = 0; i < count; i++) {
+ forceLayout(group.getChildAt(i));
+ }
+ }
+ }
+
private final static int MSG_INVALIDATE = 1;
private final static int MSG_INVALIDATE_RECT = 2;
private final static int MSG_DIE = 3;
@@ -3297,6 +3308,10 @@ public final class ViewRootImpl implements ViewParent,
mReportNextDraw = true;
}
+ if (mView != null) {
+ forceLayout(mView);
+ }
+
requestLayout();
}
break;
@@ -3311,6 +3326,9 @@ public final class ViewRootImpl implements ViewParent,
mWinFrame.top = t;
mWinFrame.bottom = t + h;
+ if (mView != null) {
+ forceLayout(mView);
+ }
requestLayout();
}
break;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 6af2e8b..d9faece 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -517,6 +517,7 @@ public class ChooserActivity extends ResolverActivity {
private final ResolveInfo mBackupResolveInfo;
private final ChooserTarget mChooserTarget;
private Drawable mBadgeIcon = null;
+ private CharSequence mBadgeContentDescription;
private Drawable mDisplayIcon;
private final Intent mFillInIntent;
private final int mFillInFlags;
@@ -532,7 +533,9 @@ public class ChooserActivity extends ResolverActivity {
if (ri != null) {
final ActivityInfo ai = ri.activityInfo;
if (ai != null && ai.applicationInfo != null) {
- mBadgeIcon = getPackageManager().getApplicationIcon(ai.applicationInfo);
+ final PackageManager pm = getPackageManager();
+ mBadgeIcon = pm.getApplicationIcon(ai.applicationInfo);
+ mBadgeContentDescription = pm.getApplicationLabel(ai.applicationInfo);
}
}
}
@@ -555,6 +558,7 @@ public class ChooserActivity extends ResolverActivity {
mBackupResolveInfo = other.mBackupResolveInfo;
mChooserTarget = other.mChooserTarget;
mBadgeIcon = other.mBadgeIcon;
+ mBadgeContentDescription = other.mBadgeContentDescription;
mDisplayIcon = other.mDisplayIcon;
mFillInIntent = fillInIntent;
mFillInFlags = flags;
@@ -647,6 +651,11 @@ public class ChooserActivity extends ResolverActivity {
}
@Override
+ public CharSequence getBadgeContentDescription() {
+ return mBadgeContentDescription;
+ }
+
+ @Override
public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
return new ChooserTargetInfo(this, fillInIntent, flags);
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 89599e0..7dd3bed 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -932,6 +932,11 @@ public class ResolverActivity extends Activity {
}
@Override
+ public CharSequence getBadgeContentDescription() {
+ return null;
+ }
+
+ @Override
public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
return new DisplayResolveInfo(this, fillInIntent, flags);
}
@@ -1072,6 +1077,11 @@ public class ResolverActivity extends Activity {
public Drawable getBadgeIcon();
/**
+ * @return The content description for the badge icon
+ */
+ public CharSequence getBadgeContentDescription();
+
+ /**
* Clone this target with the given fill-in information.
*/
public TargetInfo cloneFilledIn(Intent fillInIntent, int flags);
@@ -1542,6 +1552,7 @@ public class ResolverActivity extends Activity {
final Drawable badge = info.getBadgeIcon();
if (badge != null) {
holder.badge.setImageDrawable(badge);
+ holder.badge.setContentDescription(info.getBadgeContentDescription());
holder.badge.setVisibility(View.VISIBLE);
} else {
holder.badge.setVisibility(View.GONE);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index e7c58f4..4f42ed9 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 0369c3f..6654ea5 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/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index fc9a1a5..7679624 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -34,6 +34,7 @@ import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.OverScroller;
@@ -609,19 +610,37 @@ public class ResolverDrawerLayout extends ViewGroup {
}
@Override
- public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(info);
+ public CharSequence getAccessibilityClassName() {
+ // Since we support scrolling, make this ViewGroup look like a
+ // ScrollView. This is kind of a hack until we have support for
+ // specifying auto-scroll behavior.
+ return android.widget.ScrollView.class.getName();
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfoInternal(info);
+
if (isEnabled()) {
if (mCollapseOffset != 0) {
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
info.setScrollable(true);
}
}
+
+ // This view should never get accessibility focus, but it's interactive
+ // via nested scrolling, so we can't hide it completely.
+ info.removeAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
}
@Override
- public boolean performAccessibilityAction(int action, Bundle arguments) {
- if (super.performAccessibilityAction(action, arguments)) {
+ public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+ if (action == AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS.getId()) {
+ // This view should never get accessibility focus.
+ return false;
+ }
+
+ if (super.performAccessibilityActionInternal(action, arguments)) {
return true;
}
@@ -629,6 +648,7 @@ public class ResolverDrawerLayout extends ViewGroup {
smoothScrollTo(0, 0);
return true;
}
+
return false;
}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 670d3c0..fbe3ece 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/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 7c8769d..fb22689 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -23,7 +23,9 @@
#include <utils/Vector.h>
#include <utils/SortedVector.h>
#include <utils/KeyedVector.h>
+#include <stdio.h>
#include <string.h>
+#include <vector>
#include "jni.h"
#include "JNIHelp.h"
@@ -45,9 +47,30 @@ static const bool kIsDebug = false;
// fully-qualified class name
#define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative"
+#define CHARACTERISTICS_KEY_CLASS_NAME "android/hardware/camera2/CameraCharacteristics$Key"
+#define REQUEST_KEY_CLASS_NAME "android/hardware/camera2/CaptureRequest$Key"
+#define RESULT_KEY_CLASS_NAME "android/hardware/camera2/CaptureResult$Key"
using namespace android;
+static struct metadata_java_key_offsets_t {
+ jclass mCharacteristicsKey;
+ jclass mResultKey;
+ jclass mRequestKey;
+ jmethodID mCharacteristicsConstr;
+ jmethodID mResultConstr;
+ jmethodID mRequestConstr;
+ jclass mByteArray;
+ jclass mInt32Array;
+ jclass mFloatArray;
+ jclass mInt64Array;
+ jclass mDoubleArray;
+ jclass mRationalArray;
+ jclass mArrayList;
+ jmethodID mArrayListConstr;
+ jmethodID mArrayListAdd;
+} gMetadataOffsets;
+
struct fields_t {
jfieldID metadata_ptr;
};
@@ -141,6 +164,7 @@ struct Helpers {
extern "C" {
static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
+static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType);
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag);
static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz);
@@ -510,6 +534,9 @@ static JNINativeMethod gCameraMetadataMethods[] = {
{ "nativeClassInit",
"()V",
(void *)CameraMetadata_classInit },
+ { "nativeGetAllVendorKeys",
+ "(Ljava/lang/Class;)Ljava/util/ArrayList;",
+ (void *)CameraMetadata_getAllVendorKeys},
{ "nativeGetTagFromKey",
"(Ljava/lang/String;)I",
(void *)CameraMetadata_getTagFromKey },
@@ -588,6 +615,44 @@ static int find_fields(JNIEnv *env, field *fields, int count)
// Get all the required offsets in java class and register native functions
int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
{
+
+ // Store global references to Key-related classes and methods used natively
+ jclass characteristicsKeyClazz = FindClassOrDie(env, CHARACTERISTICS_KEY_CLASS_NAME);
+ jclass requestKeyClazz = FindClassOrDie(env, REQUEST_KEY_CLASS_NAME);
+ jclass resultKeyClazz = FindClassOrDie(env, RESULT_KEY_CLASS_NAME);
+ gMetadataOffsets.mCharacteristicsKey = MakeGlobalRefOrDie(env, characteristicsKeyClazz);
+ gMetadataOffsets.mRequestKey = MakeGlobalRefOrDie(env, requestKeyClazz);
+ gMetadataOffsets.mResultKey = MakeGlobalRefOrDie(env, resultKeyClazz);
+ gMetadataOffsets.mCharacteristicsConstr = GetMethodIDOrDie(env,
+ gMetadataOffsets.mCharacteristicsKey, "<init>",
+ "(Ljava/lang/String;Ljava/lang/Class;)V");
+ gMetadataOffsets.mRequestConstr = GetMethodIDOrDie(env,
+ gMetadataOffsets.mRequestKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V");
+ gMetadataOffsets.mResultConstr = GetMethodIDOrDie(env,
+ gMetadataOffsets.mResultKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V");
+
+ // Store global references for primitive array types used by Keys
+ jclass byteClazz = FindClassOrDie(env, "[B");
+ jclass int32Clazz = FindClassOrDie(env, "[I");
+ jclass floatClazz = FindClassOrDie(env, "[F");
+ jclass int64Clazz = FindClassOrDie(env, "[J");
+ jclass doubleClazz = FindClassOrDie(env, "[D");
+ jclass rationalClazz = FindClassOrDie(env, "[Landroid/util/Rational;");
+ gMetadataOffsets.mByteArray = MakeGlobalRefOrDie(env, byteClazz);
+ gMetadataOffsets.mInt32Array = MakeGlobalRefOrDie(env, int32Clazz);
+ gMetadataOffsets.mFloatArray = MakeGlobalRefOrDie(env, floatClazz);
+ gMetadataOffsets.mInt64Array = MakeGlobalRefOrDie(env, int64Clazz);
+ gMetadataOffsets.mDoubleArray = MakeGlobalRefOrDie(env, doubleClazz);
+ gMetadataOffsets.mRationalArray = MakeGlobalRefOrDie(env, rationalClazz);
+
+ // Store global references for ArrayList methods used
+ jclass arrayListClazz = FindClassOrDie(env, "java/util/ArrayList");
+ gMetadataOffsets.mArrayList = MakeGlobalRefOrDie(env, arrayListClazz);
+ gMetadataOffsets.mArrayListConstr = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
+ "<init>", "(I)V");
+ gMetadataOffsets.mArrayListAdd = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
+ "add", "(Ljava/lang/Object;)Z");
+
// Register native functions
return RegisterMethodsOrDie(env,
CAMERA_METADATA_CLASS_NAME,
@@ -596,6 +661,7 @@ int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
}
extern "C" {
+
static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
// XX: Why do this separately instead of doing it in the register function?
ALOGV("%s", __FUNCTION__);
@@ -612,6 +678,107 @@ static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
env->FindClass(CAMERA_METADATA_CLASS_NAME);
}
+static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType) {
+
+ // Get all vendor tags
+ sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
+ if (vTags.get() == nullptr) {
+ // No vendor tags.
+ return NULL;
+ }
+
+ int count = vTags->getTagCount();
+ if (count <= 0) {
+ // No vendor tags.
+ return NULL;
+ }
+
+ std::vector<uint32_t> tagIds(count, /*initializer value*/0);
+ vTags->getTagArray(&tagIds[0]);
+
+ // Which key class/constructor should we use?
+ jclass keyClazz;
+ jmethodID keyConstr;
+ if (env->IsSameObject(keyType, gMetadataOffsets.mCharacteristicsKey)) {
+ keyClazz = gMetadataOffsets.mCharacteristicsKey;
+ keyConstr = gMetadataOffsets.mCharacteristicsConstr;
+ } else if (env->IsSameObject(keyType, gMetadataOffsets.mResultKey)) {
+ keyClazz = gMetadataOffsets.mResultKey;
+ keyConstr = gMetadataOffsets.mResultConstr;
+ } else if (env->IsSameObject(keyType, gMetadataOffsets.mRequestKey)) {
+ keyClazz = gMetadataOffsets.mRequestKey;
+ keyConstr = gMetadataOffsets.mRequestConstr;
+ } else {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Invalid key class given as argument.");
+ return NULL;
+ }
+
+ // Allocate arrayList to return
+ jobject arrayList = env->NewObject(gMetadataOffsets.mArrayList,
+ gMetadataOffsets.mArrayListConstr, static_cast<jint>(count));
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+
+ for (uint32_t id : tagIds) {
+ const char* section = vTags->getSectionName(id);
+ const char* tag = vTags->getTagName(id);
+ int type = vTags->getTagType(id);
+
+ size_t totalLen = strlen(section) + strlen(tag) + 2;
+ std::vector<char> fullName(totalLen, 0);
+ snprintf(&fullName[0], totalLen, "%s.%s", section, tag);
+
+ jstring name = env->NewStringUTF(&fullName[0]);
+
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+
+ jclass valueClazz;
+ switch (type) {
+ case TYPE_BYTE:
+ valueClazz = gMetadataOffsets.mByteArray;
+ break;
+ case TYPE_INT32:
+ valueClazz = gMetadataOffsets.mInt32Array;
+ break;
+ case TYPE_FLOAT:
+ valueClazz = gMetadataOffsets.mFloatArray;
+ break;
+ case TYPE_INT64:
+ valueClazz = gMetadataOffsets.mInt64Array;
+ break;
+ case TYPE_DOUBLE:
+ valueClazz = gMetadataOffsets.mDoubleArray;
+ break;
+ case TYPE_RATIONAL:
+ valueClazz = gMetadataOffsets.mRationalArray;
+ break;
+ default:
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Invalid type %d given for key %s", type, &fullName[0]);
+ return NULL;
+ }
+
+ jobject key = env->NewObject(keyClazz, keyConstr, name, valueClazz);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+
+ env->CallBooleanMethod(arrayList, gMetadataOffsets.mArrayListAdd, key);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+
+ env->DeleteLocalRef(name);
+ env->DeleteLocalRef(key);
+ }
+
+ return arrayList;
+}
+
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName) {
ScopedUtfChars keyScoped(env, keyName);
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 1cb39f0..7399fa9 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -41,9 +41,6 @@
<color name="switch_thumb_disabled_material_dark">#ff616161</color>
<color name="switch_thumb_disabled_material_light">#ffbdbdbd</color>
- <color name="link_text_material_light">@color/material_deep_teal_500</color>
- <color name="link_text_material_dark">@color/material_deep_teal_200</color>
-
<!-- Text & foreground colors -->
<eat-comment />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 9d3a7ef..e88a4fb 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -67,8 +67,8 @@ please see themes_device_defaults.xml.
<item name="textColorHintInverse">@color/hint_foreground_material_light</item>
<item name="textColorHighlight">@color/highlighted_text_material</item>
<item name="textColorHighlightInverse">@color/highlighted_text_material</item>
- <item name="textColorLink">@color/link_text_material_dark</item>
- <item name="textColorLinkInverse">@color/link_text_material_light</item>
+ <item name="textColorLink">?attr/colorAccent</item>
+ <item name="textColorLinkInverse">?attr/colorAccent</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
@@ -422,8 +422,8 @@ please see themes_device_defaults.xml.
<item name="textColorHintInverse">@color/hint_foreground_material_dark</item>
<item name="textColorHighlight">@color/highlighted_text_material</item>
<item name="textColorHighlightInverse">@color/highlighted_text_material</item>
- <item name="textColorLink">@color/link_text_material_light</item>
- <item name="textColorLinkInverse">@color/link_text_material_dark</item>
+ <item name="textColorLink">?attr/colorAccent</item>
+ <item name="textColorLinkInverse">?attr/colorAccent</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
@@ -793,8 +793,6 @@ please see themes_device_defaults.xml.
<item name="textColorHintInverse">@color/hint_foreground_material_dark</item>
<item name="textColorHighlight">@color/highlighted_text_material</item>
<item name="textColorHighlightInverse">@color/highlighted_text_material</item>
- <item name="textColorLink">@color/link_text_material_light</item>
- <item name="textColorLinkInverse">@color/link_text_material_dark</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
@@ -827,8 +825,6 @@ please see themes_device_defaults.xml.
<item name="textColorHintInverse">@color/hint_foreground_material_light</item>
<item name="textColorHighlight">@color/highlighted_text_material</item>
<item name="textColorHighlightInverse">@color/highlighted_text_material</item>
- <item name="textColorLink">@color/link_text_material_dark</item>
- <item name="textColorLinkInverse">@color/link_text_material_light</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 8ad7c12..3e4d93b 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 3ebd57b..1e39bfa 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 e472e93..6dfb6e8 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/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 3c459d8..6c224e5 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.ImageFormat;
import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.os.Bundle;
import android.os.Handler;
@@ -32,6 +33,7 @@ import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.util.Arrays;
import java.util.HashMap;
@@ -228,8 +230,9 @@ import java.util.Map;
data and submit it as a single codec-config buffer.
<p>
Android uses the following codec-specific data buffers. These are also required to be set in
- the track format for proper {@link MediaMuxer} track configuration. Each parameter set and
- codec-specific-data must start with a start code of {@code "\x00\x00\x00\x01"}.
+ the track format for proper {@link MediaMuxer} track configuration. Each parameter set and the
+ codec-specific-data sections marked with (<sup>*</sup>) must start with a start code of
+ {@code "\x00\x00\x00\x01"}.
<p>
<style>td.NA { background: #ccc; } .mid > tr > td { vertical-align: middle; }</style>
<table>
@@ -237,28 +240,48 @@ import java.util.Map;
<th>Format</th>
<th>CSD buffer #0</th>
<th>CSD buffer #1</th>
+ <th>CSD buffer #2</th>
</thead>
<tbody class=mid>
<tr>
<td>AAC</td>
- <td>Decoder-specific information from ESDS</td>
+ <td>Decoder-specific information from ESDS<sup>*</sup></td>
<td class=NA>Not Used</td>
+ <td class=NA>Not Used</td>
+ </tr>
+ <tr>
+ <td>VORBIS</td>
+ <td>Identification header</td>
+ <td>Setup header</td>
+ <td class=NA>Not Used</td>
+ </tr>
+ <tr>
+ <td>OPUS</td>
+ <td>Identification header</td>
+ <td>Pre-skip in nanosecs<br>
+ (unsigned 64-bit {@linkplain ByteOrder#nativeOrder native-order} integer.)<br>
+ This overrides the pre-skip value in the identification header.</td>
+ <td>Seek Pre-roll in nanosecs<br>
+ (unsigned 64-bit {@linkplain ByteOrder#nativeOrder native-order} integer.)</td>
</tr>
<tr>
<td>MPEG-4</td>
- <td>Decoder-specific information from ESDS</td>
+ <td>Decoder-specific information from ESDS<sup>*</sup></td>
+ <td class=NA>Not Used</td>
<td class=NA>Not Used</td>
</tr>
<tr>
<td>H.264 AVC</td>
- <td>SPS (Sequence Parameter Sets)</td>
- <td>PPS (Picture Parameter Sets)</td>
+ <td>SPS (Sequence Parameter Sets<sup>*</sup>)</td>
+ <td>PPS (Picture Parameter Sets<sup>*</sup>)</td>
+ <td class=NA>Not Used</td>
</tr>
<tr>
<td>H.265 HEVC</td>
- <td>VPS (Video Parameter Sets) +<br>
- SPS (Sequence Parameter Sets) +<br>
- PPS (Picture Parameter Sets)</td>
+ <td>VPS (Video Parameter Sets<sup>*</sup>) +<br>
+ SPS (Sequence Parameter Sets<sup>*</sup>) +<br>
+ PPS (Picture Parameter Sets<sup>*</sup>)</td>
+ <td class=NA>Not Used</td>
<td class=NA>Not Used</td>
</tr>
</tbody>
@@ -297,10 +320,10 @@ import java.util.Map;
releaseOutputBuffer} methods to return the buffer to the codec.
<p>
While you are not required to resubmit/release buffers immediately to the codec, holding onto
- input and/or output buffers may stall the codec, and this behavior is device dependent. E.g. it
- is possible that a codec may hold off on generating output buffers until all outstanding buffers
- have been released/resubmitted. Therefore, try to hold onto to available buffers as little as
- possible.
+ input and/or output buffers may stall the codec, and this behavior is device dependent.
+ <strong>Specifically, it is possible that a codec may hold off on generating output buffers until
+ <em>all</em> outstanding buffers have been released/resubmitted.</strong> Therefore, try to
+ hold onto to available buffers as little as possible.
<p>
Depending on the API version, you can process data in three ways:
<table>
@@ -346,7 +369,7 @@ import java.util.Map;
<p>
MediaCodec is typically used like this in asynchronous mode:
<pre class=prettyprint>
- MediaCodec codec = MediaCodec.createCodecByName(name);
+ MediaCodec codec = MediaCodec.createByCodecName(name);
MediaFormat mOutputFormat; // member variable
codec.setCallback(new MediaCodec.Callback() {
{@literal @Override}
@@ -403,7 +426,7 @@ import java.util.Map;
<p>
MediaCodec is typically used like this in synchronous mode:
<pre>
- MediaCodec codec = MediaCodec.createCodecByName(name);
+ MediaCodec codec = MediaCodec.createByCodecName(name);
codec.configure(format, &hellip;);
MediaFormat outputFormat = codec.getOutputFormat(); // option B
codec.start();
@@ -442,7 +465,7 @@ import java.util.Map;
between the size of the arrays and the number of input and output buffers used by the system,
although the array size provides an upper bound.
<pre>
- MediaCodec codec = MediaCodec.createCodecByName(name);
+ MediaCodec codec = MediaCodec.createByCodecName(name);
codec.configure(format, &hellip;);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
@@ -643,10 +666,10 @@ import java.util.Map;
class. For API version numbers, see {@link android.os.Build.VERSION_CODES}.
<style>
- .api > tr > th, td { text-align: center; padding: 4px 4px; }
+ .api > tr > th, .api > tr > td { text-align: center; padding: 4px 4px; }
.api > tr > th { vertical-align: bottom; }
.api > tr > td { vertical-align: middle; }
- .sml > tr > th, td { text-align: center; padding: 2px 4px; }
+ .sml > tr > th, .sml > tr > td { text-align: center; padding: 2px 4px; }
.fn { text-align: left; }
.fn > code > a { font: 14px/19px Roboto Condensed, sans-serif; }
.deg45 {
@@ -1561,7 +1584,7 @@ final public class MediaCodec {
private boolean mHasSurface = false;
/**
- * Instantiate a decoder supporting input data of the given mime type.
+ * Instantiate the preferred decoder supporting input data of the given mime type.
*
* The following is a partial list of defined mime types and their semantics:
* <ul>
@@ -1580,6 +1603,10 @@ final public class MediaCodec {
* <li>"audio/g711-mlaw" - G.711 ulaw audio
* </ul>
*
+ * <strong>Note:</strong> It is preferred to use {@link MediaCodecList#findDecoderForFormat}
+ * and {@link #createByCodecName} to ensure that the resulting codec can handle a
+ * given format.
+ *
* @param type The mime type of the input data.
* @throws IOException if the codec cannot be created.
* @throws IllegalArgumentException if type is not a valid mime type.
@@ -1592,7 +1619,12 @@ final public class MediaCodec {
}
/**
- * Instantiate an encoder supporting output data of the given mime type.
+ * Instantiate the preferred encoder supporting output data of the given mime type.
+ *
+ * <strong>Note:</strong> It is preferred to use {@link MediaCodecList#findEncoderForFormat}
+ * and {@link #createByCodecName} to ensure that the resulting codec can handle a
+ * given format.
+ *
* @param type The desired mime type of the output data.
* @throws IOException if the codec cannot be created.
* @throws IllegalArgumentException if type is not a valid mime type.
@@ -1661,6 +1693,8 @@ final public class MediaCodec {
private native final void native_reset();
/**
+ * Free up resources used by the codec instance.
+ *
* Make sure you call this when you're done to free up any opened
* component instance instead of relying on the garbage collector
* to do this for you at some point in the future.
@@ -1881,17 +1915,25 @@ final public class MediaCodec {
private native final void native_stop();
/**
- * Flush both input and output ports of the component, all indices
- * previously returned in calls to {@link #dequeueInputBuffer} and
- * {@link #dequeueOutputBuffer} become invalid.
+ * Flush both input and output ports of the component.
* <p>
- * If codec is configured in asynchronous mode, call {@link #start}
- * after {@code flush} has returned to resume codec operations. The
- * codec will not request input buffers until this has happened.
+ * Upon return, all indices previously returned in calls to {@link #dequeueInputBuffer
+ * dequeueInputBuffer} and {@link #dequeueOutputBuffer dequeueOutputBuffer} &mdash; or obtained
+ * via {@link Callback#onInputBufferAvailable onInputBufferAvailable} or
+ * {@link Callback#onOutputBufferAvailable onOutputBufferAvailable} callbacks &mdash; become
+ * invalid, and all buffers are owned by the codec.
* <p>
- * If codec is configured in synchronous mode, codec will resume
- * automatically if an input surface was created. Otherwise, it
- * will resume when {@link #dequeueInputBuffer} is called.
+ * If the codec is configured in asynchronous mode, call {@link #start}
+ * after {@code flush} has returned to resume codec operations. The codec
+ * will not request input buffers until this has happened.
+ * <strong>Note, however, that there may still be outstanding {@code onOutputBufferAvailable}
+ * callbacks that were not handled prior to calling {@code flush}.
+ * The indices returned via these callbacks also become invalid upon calling {@code flush} and
+ * should be discarded.</strong>
+ * <p>
+ * If the codec is configured in synchronous mode, codec will resume
+ * automatically if it is configured with an input surface. Otherwise, it
+ * will resume when {@link #dequeueInputBuffer dequeueInputBuffer} is called.
*
* @throws IllegalStateException if not in the Executing state.
* @throws MediaCodec.CodecException upon codec error.
@@ -2082,6 +2124,15 @@ final public class MediaCodec {
* To indicate that this is the final piece of input data (or rather that
* no more input data follows unless the decoder is subsequently flushed)
* specify the flag {@link #BUFFER_FLAG_END_OF_STREAM}.
+ * <p class=note>
+ * <strong>Note:</strong> Prior to {@link android.os.Build.VERSION_CODES#M},
+ * {@code presentationTimeUs} was not propagated to the frame timestamp of (rendered)
+ * Surface output buffers, and the resulting frame timestamp was undefined.
+ * Use {@link #releaseOutputBuffer(int, long)} to ensure a specific frame timestamp is set.
+ * Similarly, since frame timestamps can be used by the destination surface for rendering
+ * synchronization, <strong>care must be taken to normalize presentationTimeUs so as to not be
+ * mistaken for a system time. (See {@linkplain #releaseOutputBuffer(int, long)
+ * SurfaceView specifics}).</strong>
*
* @param index The index of a client-owned input buffer previously returned
* in a call to {@link #dequeueInputBuffer}.
@@ -2089,7 +2140,10 @@ final public class MediaCodec {
* @param size The number of bytes of valid input data.
* @param presentationTimeUs The presentation timestamp in microseconds for this
* buffer. This is normally the media time at which this
- * buffer should be presented (rendered).
+ * buffer should be presented (rendered). When using an output
+ * surface, this will be propagated as the {@link
+ * SurfaceTexture#getTimestamp timestamp} for the frame (after
+ * conversion to nanoseconds).
* @param flags A bitmask of flags
* {@link #BUFFER_FLAG_CODEC_CONFIG} and {@link #BUFFER_FLAG_END_OF_STREAM}.
* While not prohibited, most codecs do not use the
@@ -2202,8 +2256,10 @@ final public class MediaCodec {
};
/**
- * Similar to {@link #queueInputBuffer} but submits a buffer that is
+ * Similar to {@link #queueInputBuffer queueInputBuffer} but submits a buffer that is
* potentially encrypted.
+ * <strong>Check out further notes at {@link #queueInputBuffer queueInputBuffer}.</strong>
+ *
* @param index The index of a client-owned input buffer previously returned
* in a call to {@link #dequeueInputBuffer}.
* @param offset The byte offset into the input buffer at which the data starts.
@@ -2310,7 +2366,7 @@ final public class MediaCodec {
/**
* Dequeue an output buffer, block at most "timeoutUs" microseconds.
* Returns the index of an output buffer that has been successfully
- * decoded or one of the INFO_* constants below.
+ * decoded or one of the INFO_* constants.
* @param info Will be filled with buffer meta data.
* @param timeoutUs The timeout in microseconds, a negative timeout indicates "infinite".
* @throws IllegalStateException if not in the Executing state,
@@ -2338,9 +2394,11 @@ final public class MediaCodec {
@NonNull BufferInfo info, long timeoutUs);
/**
- * If you are done with a buffer, use this call to return the buffer to
- * the codec. If you previously specified a surface when configuring this
- * video decoder you can optionally render the buffer.
+ * If you are done with a buffer, use this call to return the buffer to the codec
+ * or to render it on the output surface. If you configured the codec with an
+ * output surface, setting {@code render} to {@code true} will first send the buffer
+ * to that output surface. The surface will release the buffer back to the codec once
+ * it is no longer used/displayed.
*
* Once an output buffer is released to the codec, it MUST NOT
* be used until it is later retrieved by {@link #getOutputBuffer} in response
@@ -2674,6 +2732,8 @@ final public class MediaCodec {
* <b>Note:</b> As of API 21, dequeued input buffers are
* automatically {@link java.nio.Buffer#clear cleared}.
*
+ * <em>Do not use this method if using an input surface.</em>
+ *
* @throws IllegalStateException if not in the Executing state,
* or codec is configured in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error.
@@ -2703,6 +2763,8 @@ final public class MediaCodec {
* buffers that are dequeued will be set to the valid data
* range.
*
+ * <em>Do not use this method if using an output surface.</em>
+ *
* @throws IllegalStateException if not in the Executing state,
* or codec is configured in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error.
@@ -2988,6 +3050,10 @@ final public class MediaCodec {
/**
* Called when an output frame has rendered on the output surface.
+ * <p>
+ * <strong>Note:</strong> This callback is for informational purposes only: to get precise
+ * render timing samples, and can be significantly delayed and batched. Some frames may have
+ * been rendered even if there was no callback generated.
*
* @param codec the MediaCodec instance
* @param presentationTimeUs the presentation time (media time) of the frame rendered.
@@ -3004,10 +3070,14 @@ final public class MediaCodec {
}
/**
- * Register a callback to be invoked when an output frame is rendered on the output surface.
+ * Registers a callback to be invoked when an output frame is rendered on the output surface.
* <p>
* This method can be called in any codec state, but will only have an effect in the
* Executing state for codecs that render buffers to the output surface.
+ * <p>
+ * <strong>Note:</strong> This callback is for informational purposes only: to get precise
+ * render timing samples, and can be significantly delayed and batched. Some frames may have
+ * been rendered even if there was no callback generated.
*
* @param listener the callback that will be run
* @param handler the callback will be run on the handler's thread. If {@code null},
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 8243d40..4101935 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -525,6 +525,14 @@ public final class MediaCodecInfo {
/**
* Query whether codec supports a given {@link MediaFormat}.
+ *
+ * <p class=note>
+ * <strong>Note:</strong> On {@link android.os.Build.VERSION_CODES#LOLLIPOP},
+ * {@code format} must not contain a {@linkplain MediaFormat#KEY_FRAME_RATE
+ * frame rate}. Use
+ * <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code>
+ * to clear any existing frame rate setting in the format.
+ *
* @param format media format with optional feature directives.
* @throws IllegalArgumentException if format is not a valid media format.
* @return whether the codec capabilities support the given format
@@ -1230,8 +1238,22 @@ public final class MediaCodecInfo {
* May return {@code null}, if the codec did not publish any measurement
* data.
* <p>
- * This is a performance estimate, based on full-speed decoding
- * and encoding measurements of common video sizes supported by the codec.
+ * This is a performance estimate provided by the device manufacturer
+ * based on full-speed decoding and encoding measurements in various configurations
+ * of common video sizes supported by the codec. As such it should only be used to
+ * compare individual codecs on the device. The value is not suitable for comparing
+ * different devices or even different android releases for the same device.
+ * <p>
+ * The returned range corresponds to the fastest frame rates achieved in the tested
+ * configurations. It is interpolated from the nearest frame size(s) tested. Codec
+ * performance is severely impacted by other activity on the device, and can vary
+ * significantly.
+ * <p class=note>
+ * Use this method in cases where only codec performance matters, e.g. to evaluate if
+ * a codec has any chance of meeting a performance target. Codecs are listed
+ * in {@link MediaCodecList} in the preferred order as defined by the device
+ * manufacturer. As such, applications should use the first suitable codec in the
+ * list to achieve the best balance between power use and performance.
*
* @param width the width of the video
* @param height the height of the video
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index f44e048..cd7b3d3 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -190,6 +190,13 @@ final public class MediaCodecList {
* Find a decoder supporting a given {@link MediaFormat} in the list
* of media-codecs.
*
+ * <p class=note>
+ * <strong>Note:</strong> On {@link android.os.Build.VERSION_CODES#LOLLIPOP},
+ * {@code format} must not contain a {@linkplain MediaFormat#KEY_FRAME_RATE
+ * frame rate}. Use
+ * <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code>
+ * to clear any existing frame rate setting in the format.
+ *
* @param format A decoder media format with optional feature directives.
* @throws IllegalArgumentException if format is not a valid media format.
* @throws NullPointerException if format is null.
@@ -204,6 +211,13 @@ final public class MediaCodecList {
* Find an encoder supporting a given {@link MediaFormat} in the list
* of media-codecs.
*
+ * <p class=note>
+ * <strong>Note:</strong> On {@link android.os.Build.VERSION_CODES#LOLLIPOP},
+ * {@code format} must not contain a {@linkplain MediaFormat#KEY_FRAME_RATE
+ * frame rate}. Use
+ * <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code>
+ * to clear any existing frame rate setting in the format.
+ *
* @param format An encoder media format with optional feature directives.
* @throws IllegalArgumentException if format is not a valid media format.
* @throws NullPointerException if format is null.
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 9e9d602..c2bcd93 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -52,7 +52,8 @@ public class Ringtone {
MediaStore.Audio.Media.TITLE
};
/** Selection that limits query results to just audio files */
- private static final String MEDIA_SELECTION = MediaColumns.MIME_TYPE + " LIKE 'audio/%'";
+ private static final String MEDIA_SELECTION = MediaColumns.MIME_TYPE + " LIKE 'audio/%' OR "
+ + MediaColumns.MIME_TYPE + " IN ('application/ogg', 'application/x-flac')";
// keep references on active Ringtones until stopped or completion listener called.
private static final ArrayList<Ringtone> sActiveRingtones = new ArrayList<Ringtone>();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 0c6837f..8f792de 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -53,15 +53,18 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
super(context, attrs);
}
+ @Override
public void setKeyguardCallback(KeyguardSecurityCallback callback) {
mCallback = callback;
}
+ @Override
public void setLockPatternUtils(LockPatternUtils utils) {
mLockPatternUtils = utils;
mEnableHaptics = mLockPatternUtils.isTactileFeedbackEnabled();
}
+ @Override
public void reset() {
// start fresh
resetPasswordText(false /* animate */);
@@ -95,6 +98,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
}
}
+ @Override
public void onEmergencyButtonClickedWhenInCall() {
mCallback.reset();
}
@@ -115,11 +119,11 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
mPendingLockCheck.cancel(false);
}
- if (entry.length() < MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
+ if (entry.length() <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
// to avoid accidental lockout, only count attempts that are long enough to be a
// real password. This may require some tweaking.
setPasswordEntryInputEnabled(true);
- onPasswordChecked(entry, false, 0);
+ onPasswordChecked(false /* matched */, 0, false /* not valid - too short */);
return;
}
@@ -132,24 +136,27 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
public void onChecked(boolean matched, int timeoutMs) {
setPasswordEntryInputEnabled(true);
mPendingLockCheck = null;
- onPasswordChecked(entry, matched, timeoutMs);
+ onPasswordChecked(matched, timeoutMs, true /* isValidPassword */);
}
});
}
- private void onPasswordChecked(String entry, boolean matched, int timeoutMs) {
+ private void onPasswordChecked(boolean matched, int timeoutMs, boolean isValidPassword) {
if (matched) {
mCallback.reportUnlockAttempt(true, 0);
mCallback.dismiss(true);
} else {
- mCallback.reportUnlockAttempt(false, timeoutMs);
- int attempts = KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
- if (timeoutMs > 0) {
- long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
- KeyguardUpdateMonitor.getCurrentUser(), timeoutMs);
- handleAttemptLockout(deadline);
+ if (isValidPassword) {
+ mCallback.reportUnlockAttempt(false, timeoutMs);
+ if (timeoutMs > 0) {
+ long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
+ KeyguardUpdateMonitor.getCurrentUser(), timeoutMs);
+ handleAttemptLockout(deadline);
+ }
+ }
+ if (timeoutMs == 0) {
+ mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true);
}
- mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true);
}
resetPasswordText(true /* animate */);
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index b000e26..4bd1a2e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -82,6 +82,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
* Useful for clearing out the wrong pattern after a delay
*/
private Runnable mCancelPatternRunnable = new Runnable() {
+ @Override
public void run() {
mLockPatternView.clearPattern();
}
@@ -117,10 +118,12 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
R.dimen.disappear_y_translation);
}
+ @Override
public void setKeyguardCallback(KeyguardSecurityCallback callback) {
mCallback = callback;
}
+ @Override
public void setLockPatternUtils(LockPatternUtils utils) {
mLockPatternUtils = utils;
}
@@ -153,6 +156,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
}
}
+ @Override
public void onEmergencyButtonClickedWhenInCall() {
mCallback.reset();
}
@@ -174,6 +178,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
return result;
}
+ @Override
public void reset() {
// reset lock pattern
mLockPatternView.enableInput();
@@ -207,18 +212,22 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
private class UnlockPatternListener implements LockPatternView.OnPatternListener {
+ @Override
public void onPatternStart() {
mLockPatternView.removeCallbacks(mCancelPatternRunnable);
mSecurityMessageDisplay.setMessage("", false);
}
+ @Override
public void onPatternCleared() {
}
+ @Override
public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
mCallback.userActivity();
}
+ @Override
public void onPatternDetected(final List<LockPatternView.Cell> pattern) {
mLockPatternView.disableInput();
if (mPendingLockCheck != null) {
@@ -227,7 +236,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
mLockPatternView.enableInput();
- onPatternChecked(pattern, false, 0);
+ onPatternChecked(false, 0, false /* not valid - too short */);
return;
}
@@ -240,29 +249,30 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
public void onChecked(boolean matched, int timeoutMs) {
mLockPatternView.enableInput();
mPendingLockCheck = null;
- onPatternChecked(pattern, matched, timeoutMs);
+ onPatternChecked(matched, timeoutMs, true);
}
});
+ if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
+ mCallback.userActivity();
+ }
}
- private void onPatternChecked(List<LockPatternView.Cell> pattern, boolean matched,
- int timeoutMs) {
+ private void onPatternChecked(boolean matched, int timeoutMs, boolean isValidPattern) {
if (matched) {
mCallback.reportUnlockAttempt(true, 0);
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
mCallback.dismiss(true);
} else {
- if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
- mCallback.userActivity();
- }
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
- mCallback.reportUnlockAttempt(false, timeoutMs);
- int attempts = mKeyguardUpdateMonitor.getFailedUnlockAttempts();
- if (timeoutMs > 0) {
- long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
- KeyguardUpdateMonitor.getCurrentUser(), timeoutMs);
- handleAttemptLockout(deadline);
- } else {
+ if (isValidPattern) {
+ mCallback.reportUnlockAttempt(false, timeoutMs);
+ if (timeoutMs > 0) {
+ long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
+ KeyguardUpdateMonitor.getCurrentUser(), timeoutMs);
+ handleAttemptLockout(deadline);
+ }
+ }
+ if (timeoutMs == 0) {
mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern, true);
mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 249eaa5..b0429ef 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 3e9b122..73971ad 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 5d74604..21cbef2 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 cd1914c..29a8f67 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/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 13e9b16..ed1dca3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -51,7 +51,7 @@ public class MobileSignalController extends SignalController<
@VisibleForTesting
final PhoneStateListener mPhoneStateListener;
// Save entire info for logging, we only use the id.
- private final SubscriptionInfo mSubscriptionInfo;
+ final SubscriptionInfo mSubscriptionInfo;
// @VisibleForDemoMode
final SparseArray<MobileIconGroup> mNetworkToIconLookup;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 57dfff5..2996808 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -66,6 +66,11 @@ public class NetworkControllerImpl extends BroadcastReceiver
// additional diagnostics, but not logspew
static final boolean CHATTY = Log.isLoggable(TAG + "Chat", Log.DEBUG);
+ private static final int EMERGENCY_NO_CONTROLLERS = 0;
+ private static final int EMERGENCY_FIRST_CONTROLLER = 100;
+ private static final int EMERGENCY_VOICE_CONTROLLER = 200;
+ private static final int EMERGENCY_NO_SUB = 300;
+
private final Context mContext;
private final TelephonyManager mPhone;
private final WifiManager mWifiManager;
@@ -118,6 +123,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
// Handler that all callbacks are made on.
private final CallbackHandler mCallbackHandler;
+ private int mEmergencySource;
+ private boolean mIsEmergency;
+
@VisibleForTesting
ServiceState mLastServiceState;
@@ -267,6 +275,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
if (mMobileSignalControllers.size() == 0) {
// When there are no active subscriptions, determine emengency state from last
// broadcast.
+ mEmergencySource = EMERGENCY_NO_CONTROLLERS;
return mLastServiceState != null && mLastServiceState.isEmergencyOnly();
}
int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
@@ -274,16 +283,20 @@ public class NetworkControllerImpl extends BroadcastReceiver
for (MobileSignalController mobileSignalController :
mMobileSignalControllers.values()) {
if (!mobileSignalController.getState().isEmergency) {
+ mEmergencySource = EMERGENCY_FIRST_CONTROLLER
+ + mobileSignalController.mSubscriptionInfo.getSubscriptionId();
if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag);
return false;
}
}
}
if (mMobileSignalControllers.containsKey(voiceSubId)) {
+ mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId;
if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
}
if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
+ mEmergencySource = EMERGENCY_NO_SUB + voiceSubId;
// Something is wrong, better assume we can't make calls...
return true;
}
@@ -293,7 +306,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
* so we should recheck and send out the state to listeners.
*/
void recalculateEmergency() {
- mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
+ mIsEmergency = isEmergencyOnly();
+ mCallbackHandler.setEmergencyCallsOnly(mIsEmergency);
}
public void addSignalCallback(SignalCallback cb) {
@@ -606,6 +620,10 @@ public class NetworkControllerImpl extends BroadcastReceiver
pw.println(mLocale);
pw.print(" mLastServiceState=");
pw.println(mLastServiceState);
+ pw.print(" mIsEmergency=");
+ pw.println(mIsEmergency);
+ pw.print(" mEmergencySource=");
+ pw.println(emergencyToString(mEmergencySource));
for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
mobileSignalController.dump(pw);
@@ -617,6 +635,19 @@ public class NetworkControllerImpl extends BroadcastReceiver
mAccessPoints.dump(pw);
}
+ private static final String emergencyToString(int emergencySource) {
+ if (emergencySource > EMERGENCY_NO_SUB) {
+ return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")";
+ } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) {
+ return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")";
+ } else if (emergencySource > EMERGENCY_FIRST_CONTROLLER) {
+ return "FIRST_CONTROLLER(" + (emergencySource - EMERGENCY_FIRST_CONTROLLER) + ")";
+ } else if (emergencySource == EMERGENCY_NO_CONTROLLERS) {
+ return "NO_CONTROLLERS";
+ }
+ return "UNKNOWN_SOURCE";
+ }
+
private boolean mDemoMode;
private boolean mDemoInetCondition;
private WifiSignalController.WifiState mDemoWifiState;
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index ec02789..2a3492b 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1718,11 +1718,15 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private static String[] getPackagesForUid(int uid) {
+ String[] packageNames = null;
try {
- return AppGlobals.getPackageManager().getPackagesForUid(uid);
+ packageNames= AppGlobals.getPackageManager().getPackagesForUid(uid);
} catch (RemoteException e) {
/* ignore - local call */
}
- return EmptyArray.STRING;
+ if (packageNames == null) {
+ return EmptyArray.STRING;
+ }
+ return packageNames;
}
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 10a4cd1..50bd544 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 6ab2fd7..53e8d14 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 83e8db0..32fd56a 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 783dea5..b8d32c3 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 0957eb5..3de2009 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 0be2f6f..71fd49b 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 a7e6471..1fbfd9f 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/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 6ee1650..b216114 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -435,7 +435,8 @@ class RecentTasks extends ArrayList<TaskRecord> {
*/
int trimForTaskLocked(TaskRecord task, boolean doTrim) {
int recentsCount = size();
- final boolean document = task.intent != null && task.intent.isDocument();
+ final Intent intent = task.intent;
+ final boolean document = intent != null && intent.isDocument();
int maxRecents = task.maxRecents - 1;
for (int i = 0; i < recentsCount; i++) {
final TaskRecord tr = get(i);
@@ -446,12 +447,13 @@ class RecentTasks extends ArrayList<TaskRecord> {
if (i > MAX_RECENT_BITMAPS) {
tr.freeLastThumbnail();
}
+ final Intent trIntent = tr.intent;
final boolean sameAffinity =
task.affinity != null && task.affinity.equals(tr.affinity);
- final boolean trIsDocument = tr.intent != null && tr.intent.isDocument();
+ final boolean sameIntent = (intent != null && intent.filterEquals(trIntent));
+ final boolean trIsDocument = trIntent != null && trIntent.isDocument();
final boolean bothDocuments = document && trIsDocument;
- if (!sameAffinity && !bothDocuments) {
- // Not the same affinity and not documents. Move along...
+ if (!sameAffinity && !sameIntent && !bothDocuments) {
continue;
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 658f6f8..c998c2c 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 7a6895f..9426b76 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/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 669b8e5..3227ef8 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -696,7 +696,7 @@ final class DefaultPermissionGrantPolicy {
List<PackageParser.Package> syncAdapterPackages = new ArrayList<>();
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
- homeIntent.addCategory(Intent.CATEGORY_HOME);
+ homeIntent.addCategory(Intent.CATEGORY_LAUNCHER);
for (String syncAdapterPackageName : syncAdapterPackageNames) {
homeIntent.setPackage(syncAdapterPackageName);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 26304ab..6fe8b8a 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/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 1787b91..09e15a8 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -49,10 +49,8 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
import java.io.File;
-import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.PrintWriter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -316,6 +314,9 @@ public class UsbDeviceManager {
// Restore default functions.
mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE);
+ if (UsbManager.USB_FUNCTION_NONE.equals(mCurrentFunctions)) {
+ mCurrentFunctions = UsbManager.USB_FUNCTION_MTP;
+ }
mCurrentFunctionsApplied = mCurrentFunctions.equals(
SystemProperties.get(USB_STATE_PROPERTY));
mAdbEnabled = UsbManager.containsFunction(getDefaultFunctions(),
@@ -400,6 +401,14 @@ public class UsbDeviceManager {
return waitForState(config);
}
+ private void setUsbDataUnlocked(boolean enable) {
+ if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked: " + enable);
+ mUsbDataUnlocked = enable;
+ updateUsbNotification();
+ updateUsbStateBroadcast();
+ setEnabledFunctions(mCurrentFunctions, true);
+ }
+
private void setAdbEnabled(boolean enable) {
if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
if (enable != mAdbEnabled) {
@@ -471,7 +480,6 @@ public class UsbDeviceManager {
}
functions = applyAdbFunction(functions);
functions = applyOemOverrideFunction(functions);
- functions = applyUserRestrictions(functions);
if (!mCurrentFunctions.equals(functions) || !mCurrentFunctionsApplied
|| forceRestart) {
@@ -502,13 +510,9 @@ public class UsbDeviceManager {
return functions;
}
- private String applyUserRestrictions(String functions) {
+ private boolean isUsbTransferAllowed() {
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
- functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_MTP);
- functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_PTP);
- }
- return functions;
+ return !userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
}
private void updateCurrentAccessory() {
@@ -555,7 +559,7 @@ public class UsbDeviceManager {
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
- intent.putExtra(UsbManager.USB_DATA_UNLOCKED, mUsbDataUnlocked);
+ intent.putExtra(UsbManager.USB_DATA_UNLOCKED, isUsbTransferAllowed() && mUsbDataUnlocked);
if (mCurrentFunctions != null) {
String[] functions = mCurrentFunctions.split(",");
@@ -659,10 +663,7 @@ public class UsbDeviceManager {
setEnabledFunctions(mCurrentFunctions, false);
break;
case MSG_SET_USB_DATA_UNLOCKED:
- mUsbDataUnlocked = (msg.arg1 == 1);
- updateUsbNotification();
- updateUsbStateBroadcast();
- setEnabledFunctions(mCurrentFunctions, true);
+ setUsbDataUnlocked(msg.arg1 == 1);
break;
case MSG_SYSTEM_READY:
updateUsbNotification();
@@ -807,8 +808,12 @@ public class UsbDeviceManager {
}
private String getDefaultFunctions() {
- return SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY,
- UsbManager.USB_FUNCTION_ADB);
+ String func = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY,
+ UsbManager.USB_FUNCTION_NONE);
+ if (UsbManager.USB_FUNCTION_NONE.equals(func)) {
+ func = UsbManager.USB_FUNCTION_MTP;
+ }
+ return func;
}
public void dump(IndentingPrintWriter pw) {
@@ -817,6 +822,7 @@ public class UsbDeviceManager {
pw.println(" mCurrentFunctionsApplied: " + mCurrentFunctionsApplied);
pw.println(" mConnected: " + mConnected);
pw.println(" mConfigured: " + mConfigured);
+ pw.println(" mUsbDataUnlocked: " + mUsbDataUnlocked);
pw.println(" mCurrentAccessory: " + mCurrentAccessory);
try {
pw.println(" Kernel state: "
@@ -864,11 +870,6 @@ public class UsbDeviceManager {
mHandler.sendMessage(MSG_SET_USB_DATA_UNLOCKED, unlocked);
}
- public boolean isUsbDataUnlocked() {
- if (DEBUG) Slog.d(TAG, "isUsbDataUnlocked() -> " + mHandler.mUsbDataUnlocked);
- return mHandler.mUsbDataUnlocked;
- }
-
private void readOemUsbOverrideConfig() {
String[] configList = mContext.getResources().getStringArray(
com.android.internal.R.array.config_oemUsbModeOverride);
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index f93a2ef..edd9201 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -322,23 +322,10 @@ public class UsbService extends IUsbManager.Stub {
@Override
public void setUsbDataUnlocked(boolean unlocked) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- // If attempt to change USB function while file transfer is restricted, ensure that
- // usb data is always locked, and return.
- UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
- if (mDeviceManager != null) mDeviceManager.setUsbDataUnlocked(false);
- return;
- }
mDeviceManager.setUsbDataUnlocked(unlocked);
}
@Override
- public boolean isUsbDataUnlocked() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- return mDeviceManager.isUsbDataUnlocked();
- }
-
- @Override
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
diff --git a/tests/VoiceInteraction/res/layout/test_interaction.xml b/tests/VoiceInteraction/res/layout/test_interaction.xml
index d1a7ad5..277117e 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 29ffe21..c665c23 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 e10d89f..ada0e21 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) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index 1105c7b..a503e50 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -673,7 +673,7 @@ public final class Matrix_Delegate {
return;
}
- System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE);
+ System.arraycopy(d.mValues, 0, values, 0, MATRIX_SIZE);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 34d0985..3c9a062 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -36,7 +36,6 @@ import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
-import java.util.ArrayList;
/**
* Delegate implementing the native methods of android.graphics.Path
@@ -504,13 +503,13 @@ public final class Path_Delegate {
switch (type) {
case PathIterator.SEG_MOVETO:
case PathIterator.SEG_LINETO:
- store(coords, tmp, 1, isFirstPoint);
+ store(tmp, coords, 1, isFirstPoint);
break;
case PathIterator.SEG_QUADTO:
- store(coords, tmp, 2, isFirstPoint);
+ store(tmp, coords, 2, isFirstPoint);
break;
case PathIterator.SEG_CUBICTO:
- store(coords, tmp, 3, isFirstPoint);
+ store(tmp, coords, 3, isFirstPoint);
break;
case PathIterator.SEG_CLOSE:
// No points returned.
@@ -528,14 +527,14 @@ public final class Path_Delegate {
private static void store(float[] src, float[] dst, int count, boolean isFirst) {
if (isFirst) {
- dst[0] = 0;
- dst[1] = src[0];
- dst[2] = src[1];
+ dst[0] = 0; // fraction
+ dst[1] = src[0]; // abscissa
+ dst[2] = src[1]; // ordinate
}
if (count > 1 || !isFirst) {
dst[3] = 1;
- dst[4] = src[2 * count];
- dst[5] = src[2 * count + 1];
+ dst[4] = src[2 * count - 2];
+ dst[5] = src[2 * count - 1];
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index 8c7ea8a..c72c979 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
@@ -83,7 +83,7 @@ class Layout extends RelativeLayout {
// Theme attributes used for configuring appearance of the system decor.
private static final String ATTR_WINDOW_FLOATING = "windowIsFloating";
private static final String ATTR_WINDOW_BACKGROUND = "windowBackground";
- private static final String ATTR_WINDOW_FULL_SCREEN = "windowFullScreen";
+ private static final String ATTR_WINDOW_FULL_SCREEN = "windowFullscreen";
private static final String ATTR_NAV_BAR_HEIGHT = "navigation_bar_height";
private static final String ATTR_NAV_BAR_WIDTH = "navigation_bar_width";
private static final String ATTR_STATUS_BAR_HEIGHT = "status_bar_height";
@@ -329,9 +329,12 @@ class Layout extends RelativeLayout {
mWindowIsFloating = getBooleanThemeValue(mResources, ATTR_WINDOW_FLOATING, true, true);
findBackground();
- findStatusBar();
- findActionBar();
- findNavBar();
+
+ if (!mParams.isForceNoDecor()) {
+ findStatusBar();
+ findActionBar();
+ findNavBar();
+ }
}
private void findBackground() {
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png
index 9a13568..336f9d8 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png
index 92eb3e1..0c16215 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index ee448ca..9ebeebd 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -329,8 +329,8 @@ public class Main {
.setNavigation(Navigation.NONAV);
SessionParams params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", RenderingMode.V_SCROLL,
- 22);
+ layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+ RenderingMode.V_SCROLL, 22);
renderAndVerify(params, "expand_vert_layout.png");
@@ -342,8 +342,8 @@ public class Main {
parser = new LayoutPullParser(APP_TEST_RES + "/layout/" +
"expand_horz_layout.xml");
params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", RenderingMode
- .H_SCROLL, 22);
+ layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+ RenderingMode.H_SCROLL, 22);
renderAndVerify(params, "expand_horz_layout.png");
}
@@ -390,7 +390,7 @@ public class Main {
// TODO: Set up action bar handler properly to test menu rendering.
// Create session params.
SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.Light.DarkActionBar", RenderingMode.NORMAL, 22);
+ layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22);
renderAndVerify(params, goldenFileName);
}
@@ -399,12 +399,12 @@ public class Main {
*/
private SessionParams getSessionParams(LayoutPullParser layoutParser,
ConfigGenerator configGenerator, LayoutLibTestCallback layoutLibCallback,
- String themeName, RenderingMode renderingMode, int targetSdk) {
+ String themeName, boolean isProjectTheme, RenderingMode renderingMode, int targetSdk) {
FolderConfiguration config = configGenerator.getFolderConfig();
ResourceResolver resourceResolver =
ResourceResolver.create(sProjectResources.getConfiguredResources(config),
sFrameworkRepo.getConfiguredResources(config),
- themeName, false);
+ themeName, isProjectTheme);
return new SessionParams(
layoutParser,