diff options
20 files changed, 303 insertions, 98 deletions
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index d5fca4d0e85d..05099fba14d5 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -152,10 +152,24 @@ public class Process { public static final int LAST_ISOLATED_UID = 99999; /** + * First gid for applications to share resources. Used when forward-locking + * is enabled but all UserHandles need to be able to read the resources. + * @hide + */ + public static final int FIRST_SHARED_APPLICATION_GID = 50000; + + /** + * Last gid for applications to share resources. Used when forward-locking + * is enabled but all UserHandles need to be able to read the resources. + * @hide + */ + public static final int LAST_SHARED_APPLICATION_GID = 59999; + + /** * Defines a secondary group id for access to the bluetooth hardware. */ public static final int BLUETOOTH_GID = 2000; - + /** * Standard priority of application threads. * Use with {@link #setThreadPriority(int)} and diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index 7e4666c0dad5..22994ff3b271 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -139,6 +139,15 @@ public final class UserHandle implements Parcelable { } /** + * Returns the shared app gid for a given uid or appId. + * @hide + */ + public static final int getSharedAppGid(int id) { + return Process.FIRST_SHARED_APPLICATION_GID + (id % PER_USER_RANGE) + - Process.FIRST_APPLICATION_UID; + } + + /** * Returns the user id of the current process * @return user id of the current process * @hide diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 8ac84f7ae641..01b37c81ca24 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -79,6 +79,40 @@ public final class Display { public static final int DEFAULT_DISPLAY = 0; /** + * Display flag: Indicates that the display supports secure video output. + * <p> + * This flag is used to indicate that the display supports content protection + * mechanisms for secure video output at the display interface, such as HDCP. + * These mechanisms may be used to protect secure content as it leaves the device. + * </p><p> + * While mirroring content to multiple displays, it can happen that certain + * display devices support secure video output while other display devices do not. + * The secure content will be shown only on the display devices that support + * secure video output and will be blanked on other display devices that do + * not support secure video output. + * </p><p> + * This flag mainly applies to external display devices such as HDMI or + * Wifi display. Built-in display devices are usually considered secure. + * </p> + * + * @hide pending review + */ + public static final int FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT = 1 << 0; + + /** + * Display flag: Indicates that the display supports secure in-memory video buffers. + * <p> + * This flag is used to indicate that the display supports content protection + * mechanisms for decrypted in-memory video buffers, such as secure memory areas. + * These mechanisms may be used to protect secure video buffers in memory from + * the video decoder to the display compositor and the video interface. + * </p> + * + * @hide pending review + */ + public static final int FLAG_SUPPORTS_SECURE_VIDEO_BUFFERS = 1 << 1; + + /** * Internal method to create a display. * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} * or {@link android.hardware.display.DisplayManager#getDisplay} @@ -158,6 +192,20 @@ public final class Display { } /** + * Returns a combination of flags that describe the capabilities of the display. + * + * @return The display flags. + * + * @hide pending review + */ + public int getFlags() { + synchronized (this) { + updateDisplayInfoLocked(); + return mDisplayInfo.flags; + } + } + + /** * Gets the compatibility info used by this display instance. * * @return The compatibility info holder, or null if none is required. diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index b728d71cae70..c968ec549a7b 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -34,6 +34,11 @@ public final class DisplayInfo implements Parcelable { public int layerStack; /** + * Display flags. + */ + public int flags; + + /** * The human-readable name of the display. */ public String name; @@ -189,6 +194,7 @@ public final class DisplayInfo implements Parcelable { public void copyFrom(DisplayInfo other) { layerStack = other.layerStack; + flags = other.flags; name = other.name; appWidth = other.appWidth; appHeight = other.appHeight; @@ -207,6 +213,7 @@ public final class DisplayInfo implements Parcelable { public void readFromParcel(Parcel source) { layerStack = source.readInt(); + flags = source.readInt(); name = source.readString(); appWidth = source.readInt(); appHeight = source.readInt(); @@ -226,6 +233,7 @@ public final class DisplayInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(layerStack); + dest.writeInt(flags); dest.writeString(name); dest.writeInt(appWidth); dest.writeInt(appHeight); @@ -286,6 +294,17 @@ public final class DisplayInfo implements Parcelable { + ", rotation " + rotation + ", density " + logicalDensityDpi + ", " + physicalXDpi + " x " + physicalYDpi + " dpi" - + ", layerStack " + layerStack + "}"; + + ", layerStack " + layerStack + flagsToString(flags) + "}"; + } + + private static String flagsToString(int flags) { + StringBuilder result = new StringBuilder(); + if ((flags & Display.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT) != 0) { + result.append(", FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT"); + } + if ((flags & Display.FLAG_SUPPORTS_SECURE_VIDEO_BUFFERS) != 0) { + result.append(", FLAG_SUPPORTS_SECURE_VIDEO_BUFFERS"); + } + return result.toString(); } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 7567d88d63d9..8f77663aaad8 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -7436,7 +7436,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, void needGlobalAttributesUpdate(boolean force) { final AttachInfo ai = mAttachInfo; - if (ai != null) { + if (ai != null && !ai.mRecomputeGlobalAttributes) { if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0) || ai.mHasSystemUiListeners) { ai.mRecomputeGlobalAttributes = true; @@ -11719,6 +11719,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // If nobody has evaluated the drawable state yet, then do it now. refreshDrawableState(); } + needGlobalAttributesUpdate(false); } void dispatchDetachedFromWindow() { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e1312c19283a..47419bbd009c 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1007,17 +1007,15 @@ public final class ViewRootImpl implements ViewParent, //Log.i(TAG, "Computing view hierarchy attributes!"); attachInfo.mRecomputeGlobalAttributes = false; boolean oldScreenOn = attachInfo.mKeepScreenOn; - int oldVis = attachInfo.mSystemUiVisibility; - boolean oldHasSystemUiListeners = attachInfo.mHasSystemUiListeners; attachInfo.mKeepScreenOn = false; attachInfo.mSystemUiVisibility = 0; attachInfo.mHasSystemUiListeners = false; mView.dispatchCollectViewAttributes(attachInfo, 0); attachInfo.mSystemUiVisibility &= ~attachInfo.mDisabledSystemUiVisibility; + WindowManager.LayoutParams params = mWindowAttributes; if (attachInfo.mKeepScreenOn != oldScreenOn - || attachInfo.mSystemUiVisibility != oldVis - || attachInfo.mHasSystemUiListeners != oldHasSystemUiListeners) { - WindowManager.LayoutParams params = mWindowAttributes; + || attachInfo.mSystemUiVisibility != params.subtreeSystemUiVisibility + || attachInfo.mHasSystemUiListeners != params.hasSystemUiListeners) { applyKeepScreenOnFlag(params); params.subtreeSystemUiVisibility = attachInfo.mSystemUiVisibility; params.hasSystemUiListeners = attachInfo.mHasSystemUiListeners; diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java index 6bced1c6977a..037110548cae 100644 --- a/core/java/android/widget/TabWidget.java +++ b/core/java/android/widget/TabWidget.java @@ -24,6 +24,7 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.Bundle; import android.util.AttributeSet; import android.view.View; import android.view.View.OnFocusChangeListener; @@ -434,6 +435,42 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setClassName(TabWidget.class.getName()); + + final int tabCount = getTabCount(); + + if (tabCount > 1) { + if (mSelectedTab > 0) { + info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); + info.setScrollable(true); + } + + if (mSelectedTab < (tabCount - 1)) { + info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + info.setScrollable(true); + } + } + } + + @Override + public boolean performAccessibilityAction(int action, Bundle arguments) { + final int tabCount = getTabCount(); + + switch (action) { + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: + if ((tabCount > 1) && (mSelectedTab > 0)) { + focusCurrentTab(mSelectedTab - 1); + return true; + } + return false; + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: + if ((tabCount > 1) && (mSelectedTab < (tabCount - 1))) { + focusCurrentTab(mSelectedTab + 1); + return true; + } + return false; + } + + return super.performAccessibilityAction(action, arguments); } /** diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index bef363b75b8b..b127b53bda04 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -994,6 +994,12 @@ public class LocationManager { * <p> Internally, this method uses both {@link #NETWORK_PROVIDER} * and {@link #GPS_PROVIDER}. * + * <p>Before API version 17, this method could be used with + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or + * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. + * From API version 17 and onwards, this method requires + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. + * * @param latitude the latitude of the central point of the * alert region * @param longitude the longitude of the central point of the @@ -1005,7 +1011,8 @@ public class LocationManager { * @param intent a PendingIntent that will be used to generate an Intent to * fire when entry to or exit from the alert region is detected * - * @throws SecurityException if no suitable permission is present + * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} + * permission is not present * * @deprecated Use {@link LocationRequest} and {@link Geofence} instead */ @@ -1055,7 +1062,8 @@ public class LocationManager { * * @throws IllegalArgumentException if fence is null * @throws IllegalArgumentException if intent is null - * @throws SecurityException if no suitable permission is present + * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} + * permission is not present */ public void addGeofence(LocationRequest request, Geofence fence, PendingIntent intent) { checkPendingIntent(intent); @@ -1071,11 +1079,18 @@ public class LocationManager { /** * Removes the proximity alert with the given PendingIntent. * + * <p>Before API version 17, this method could be used with + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or + * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. + * From API version 17 and onwards, this method requires + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. + * * @param intent the PendingIntent that no longer needs to be notified of * proximity alerts * * @throws IllegalArgumentException if intent is null - * @throws SecurityException if no suitable permission is present + * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} + * permission is not present * * @deprecated Use {@link LocationRequest} and {@link Geofence} instead */ @@ -1102,7 +1117,8 @@ public class LocationManager { * * @throws IllegalArgumentException if fence is null * @throws IllegalArgumentException if intent is null - * @throws SecurityException if no suitable permission is present + * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} + * permission is not present */ public void removeGeofence(Geofence fence, PendingIntent intent) { checkPendingIntent(intent); @@ -1122,7 +1138,8 @@ public class LocationManager { * @param intent a pending intent previously passed to {@link #addGeofence} * * @throws IllegalArgumentException if intent is null - * @throws SecurityException if no suitable permission is present + * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} + * permission is not present */ public void removeAllGeofences(PendingIntent intent) { checkPendingIntent(intent); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 23b4b59a3f82..4ddebac8c485 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -1202,21 +1202,24 @@ public class DatabaseHelper extends SQLiteOpenHelper { if (upgradeVersion == 82) { // Move to per-user settings dbs - db.beginTransaction(); - SQLiteStatement stmt = null; - try { - // Migrate now-global settings. Note that this happens before - // new users can be created. - createGlobalTable(db); - String[] settingsToMove = hashsetToStringArray(SettingsProvider.sSystemGlobalKeys); - moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, false); - settingsToMove = hashsetToStringArray(SettingsProvider.sSecureGlobalKeys); - moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, false); + if (mUserHandle == UserHandle.USER_OWNER) { - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - if (stmt != null) stmt.close(); + db.beginTransaction(); + SQLiteStatement stmt = null; + try { + // Migrate now-global settings. Note that this happens before + // new users can be created. + createGlobalTable(db); + String[] settingsToMove = hashsetToStringArray(SettingsProvider.sSystemGlobalKeys); + moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, false); + settingsToMove = hashsetToStringArray(SettingsProvider.sSecureGlobalKeys); + moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, false); + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + if (stmt != null) stmt.close(); + } } upgradeVersion = 83; } @@ -1251,73 +1254,81 @@ public class DatabaseHelper extends SQLiteOpenHelper { } if (upgradeVersion == 84) { - db.beginTransaction(); - SQLiteStatement stmt = null; - try { - // Patch up the slightly-wrong key migration from 82 -> 83 for those - // devices that missed it, ignoring if the move is redundant - String[] settingsToMove = { - Settings.Secure.ADB_ENABLED, - Settings.Secure.BLUETOOTH_ON, - Settings.Secure.DATA_ROAMING, - Settings.Secure.DEVICE_PROVISIONED, - Settings.Secure.INSTALL_NON_MARKET_APPS, - Settings.Secure.USB_MASS_STORAGE_ENABLED - }; - moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - if (stmt != null) stmt.close(); + if (mUserHandle == UserHandle.USER_OWNER) { + db.beginTransaction(); + SQLiteStatement stmt = null; + try { + // Patch up the slightly-wrong key migration from 82 -> 83 for those + // devices that missed it, ignoring if the move is redundant + String[] settingsToMove = { + Settings.Secure.ADB_ENABLED, + Settings.Secure.BLUETOOTH_ON, + Settings.Secure.DATA_ROAMING, + Settings.Secure.DEVICE_PROVISIONED, + Settings.Secure.INSTALL_NON_MARKET_APPS, + Settings.Secure.USB_MASS_STORAGE_ENABLED + }; + moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + if (stmt != null) stmt.close(); + } } upgradeVersion = 85; } if (upgradeVersion == 85) { - db.beginTransaction(); - try { - // Fix up the migration, ignoring already-migrated elements, to snap up to - // date with new changes to the set of global versus system/secure settings - String[] settingsToMove = { Settings.System.STAY_ON_WHILE_PLUGGED_IN }; - moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, true); + if (mUserHandle == UserHandle.USER_OWNER) { + db.beginTransaction(); + try { + // Fix up the migration, ignoring already-migrated elements, to snap up to + // date with new changes to the set of global versus system/secure settings + String[] settingsToMove = { Settings.System.STAY_ON_WHILE_PLUGGED_IN }; + moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, true); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } } upgradeVersion = 86; } if (upgradeVersion == 86) { - db.beginTransaction(); - try { - String[] settingsToMove = { - Settings.Secure.PACKAGE_VERIFIER_ENABLE, - Settings.Secure.PACKAGE_VERIFIER_TIMEOUT, - Settings.Secure.PACKAGE_VERIFIER_DEFAULT_RESPONSE - }; - moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true); + if (mUserHandle == UserHandle.USER_OWNER) { + db.beginTransaction(); + try { + String[] settingsToMove = { + Settings.Secure.PACKAGE_VERIFIER_ENABLE, + Settings.Secure.PACKAGE_VERIFIER_TIMEOUT, + Settings.Secure.PACKAGE_VERIFIER_DEFAULT_RESPONSE + }; + moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } } upgradeVersion = 87; } if (upgradeVersion == 87) { - db.beginTransaction(); - try { - String[] settingsToMove = { - Settings.Secure.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS, - Settings.Secure.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS, - Settings.Secure.GPRS_REGISTER_CHECK_PERIOD_MS - }; - moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true); + if (mUserHandle == UserHandle.USER_OWNER) { + db.beginTransaction(); + try { + String[] settingsToMove = { + Settings.Secure.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS, + Settings.Secure.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS, + Settings.Secure.GPRS_REGISTER_CHECK_PERIOD_MS + }; + moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } } upgradeVersion = 88; } diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index c26448f81618..197f6ab63860 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -588,7 +588,17 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } throw new SecurityException("Location requires either ACCESS_COARSE_LOCATION or" + - "ACCESS_FINE_LOCATION permission"); + " ACCESS_FINE_LOCATION permission"); + } + + /** + * Throw SecurityException if caller lacks permission to use Geofences. + */ + private void checkGeofencePermission() { + if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) != + PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission"); + } } /** @@ -1096,6 +1106,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, String packageName) { if (request == null) request = DEFAULT_LOCATION_REQUEST; + checkGeofencePermission(); checkPermissionAndRequest(request); checkPendingIntent(intent); checkPackageName(packageName); @@ -1114,7 +1125,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run @Override public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) { - checkPermission(); + checkGeofencePermission(); checkPendingIntent(intent); checkPackageName(packageName); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 6da84034ee22..1c5a8a5d9859 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -2008,9 +2008,10 @@ public final class ActivityManagerService extends ActivityManagerNative int[] gids = null; int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; if (!app.isolated) { + int[] permGids = null; try { final PackageManager pm = mContext.getPackageManager(); - gids = pm.getPackageGids(app.info.packageName); + permGids = pm.getPackageGids(app.info.packageName); if (Environment.isExternalStorageEmulated()) { if (pm.checkPermission( @@ -2024,6 +2025,18 @@ public final class ActivityManagerService extends ActivityManagerNative } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Unable to retrieve gids", e); } + + /* + * Add shared application GID so applications can share some + * resources like shared libraries + */ + if (permGids == null) { + gids = new int[1]; + } else { + gids = new int[permGids.length + 1]; + System.arraycopy(permGids, 0, gids, 1, permGids.length); + } + gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid)); } if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) { if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java index 7c57694042a5..1420a506c8b4 100644 --- a/services/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/java/com/android/server/display/DisplayDeviceInfo.java @@ -31,16 +31,16 @@ final class DisplayDeviceInfo { public static final int FLAG_DEFAULT_DISPLAY = 1 << 0; /** - * Flag: Indicates that this display device can show secure surfaces. - */ - public static final int FLAG_SECURE = 1 << 1; - - /** * Flag: Indicates that this display device can rotate to show contents in a * different orientation. Otherwise the rotation is assumed to be fixed in the * natural orientation and the display manager should transform the content to fit. */ - public static final int FLAG_SUPPORTS_ROTATION = 1 << 2; + public static final int FLAG_SUPPORTS_ROTATION = 1 << 1; + + /** + * Flag: Indicates that this display device can show secure surfaces. + */ + public static final int FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT = 1 << 2; /** * Touch attachment: Display does not receive touch. @@ -179,8 +179,11 @@ final class DisplayDeviceInfo { if ((flags & FLAG_DEFAULT_DISPLAY) != 0) { msg.append(", FLAG_DEFAULT_DISPLAY"); } - if ((flags & FLAG_SECURE) != 0) { - msg.append(", FLAG_SECURE"); + if ((flags & FLAG_SUPPORTS_ROTATION) != 0) { + msg.append(", FLAG_DEFAULT_DISPLAY"); + } + if ((flags & FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT) != 0) { + msg.append(", FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT"); } return msg.toString(); } diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java index 7629db61371c..f3bec1d56213 100644 --- a/services/java/com/android/server/display/HeadlessDisplayAdapter.java +++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java @@ -60,7 +60,7 @@ final class HeadlessDisplayAdapter extends DisplayAdapter { mInfo.xDpi = 160; mInfo.yDpi = 160; mInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY - | DisplayDeviceInfo.FLAG_SECURE; + | DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT; mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; } return mInfo; diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java index 80c860ba88f4..eab4c9a20089 100644 --- a/services/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/java/com/android/server/display/LocalDisplayAdapter.java @@ -124,7 +124,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { mInfo.name = getContext().getResources().getString( com.android.internal.R.string.display_manager_built_in_display_name); mInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY - | DisplayDeviceInfo.FLAG_SECURE + | DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT | DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION; mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f); mInfo.xDpi = mPhys.xDpi; @@ -133,7 +133,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { } else { mInfo.name = getContext().getResources().getString( com.android.internal.R.string.display_manager_hdmi_display_name); - mInfo.flags = DisplayDeviceInfo.FLAG_SECURE; + mInfo.flags = DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT; mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height); } diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/java/com/android/server/display/LogicalDisplay.java index 2e752603360f..3607de15dd50 100644 --- a/services/java/com/android/server/display/LogicalDisplay.java +++ b/services/java/com/android/server/display/LogicalDisplay.java @@ -17,6 +17,7 @@ package com.android.server.display; import android.graphics.Rect; +import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; @@ -177,6 +178,10 @@ final class LogicalDisplay { DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked(); if (!Objects.equal(mPrimaryDisplayDeviceInfo, deviceInfo)) { mBaseDisplayInfo.layerStack = mLayerStack; + mBaseDisplayInfo.flags = 0; + if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT) != 0) { + mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT; + } mBaseDisplayInfo.name = deviceInfo.name; mBaseDisplayInfo.appWidth = deviceInfo.width; mBaseDisplayInfo.appHeight = deviceInfo.height; diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/java/com/android/server/display/OverlayDisplayAdapter.java index 9b0e534c5ed1..75ddd244d9c2 100644 --- a/services/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java @@ -227,7 +227,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { mInfo.densityDpi = mDensityDpi; mInfo.xDpi = mDensityDpi; mInfo.yDpi = mDensityDpi; - mInfo.flags = DisplayDeviceInfo.FLAG_SECURE; + mInfo.flags = DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT; mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; } return mInfo; diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java index b75940e36982..b57d3dc8125c 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/java/com/android/server/display/WifiDisplayAdapter.java @@ -149,7 +149,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { int deviceFlags = 0; if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) { - deviceFlags |= DisplayDeviceInfo.FLAG_SECURE; + deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT; } float refreshRate = 60.0f; // TODO: get this for real diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java index 6e0be5526fbd..141cbd702077 100644 --- a/services/java/com/android/server/display/WifiDisplayController.java +++ b/services/java/com/android/server/display/WifiDisplayController.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.display.WifiDisplay; +import android.media.AudioManager; import android.media.RemoteDisplay; import android.net.NetworkInfo; import android.net.wifi.p2p.WifiP2pConfig; @@ -61,7 +62,7 @@ import java.util.Enumeration; */ final class WifiDisplayController implements DumpUtils.Dump { private static final String TAG = "WifiDisplayController"; - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; private static final int DEFAULT_CONTROL_PORT = 7236; private static final int MAX_THROUGHPUT = 50; @@ -74,12 +75,20 @@ final class WifiDisplayController implements DumpUtils.Dump { private static final int CONNECT_MAX_RETRIES = 3; private static final int CONNECT_RETRY_DELAY_MILLIS = 500; + // A unique token to identify the remote submix that is managed by Wifi display. + // It must match what the media server uses when it starts recording the submix + // for transmission. We use 0 although the actual value is currently ignored. + private static final int REMOTE_SUBMIX_ADDRESS = 0; + private final Context mContext; private final Handler mHandler; private final Listener mListener; + private final WifiP2pManager mWifiP2pManager; private final Channel mWifiP2pChannel; + private final AudioManager mAudioManager; + private boolean mWifiP2pEnabled; private boolean mWfdEnabled; private boolean mWfdEnabling; @@ -128,6 +137,8 @@ final class WifiDisplayController implements DumpUtils.Dump { mWifiP2pManager = (WifiP2pManager)context.getSystemService(Context.WIFI_P2P_SERVICE); mWifiP2pChannel = mWifiP2pManager.initialize(context, handler.getLooper(), null); + mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); + IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); @@ -379,6 +390,10 @@ final class WifiDisplayController implements DumpUtils.Dump { Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface + " from Wifi display: " + mConnectedDevice.deviceName); + if (mRemoteDisplayConnected) { + mAudioManager.setRemoteSubmixOn(false, REMOTE_SUBMIX_ADDRESS); + } + mRemoteDisplay.dispose(); mRemoteDisplay = null; mRemoteDisplayInterface = null; @@ -530,6 +545,8 @@ final class WifiDisplayController implements DumpUtils.Dump { mRemoteDisplayConnected = true; mHandler.removeCallbacks(mRtspTimeout); + mAudioManager.setRemoteSubmixOn(true, REMOTE_SUBMIX_ADDRESS); + final WifiDisplay display = createWifiDisplay(mConnectedDevice); mHandler.post(new Runnable() { @Override diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index c7300b6d5e10..fe5889ded097 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -7289,7 +7289,7 @@ public class PackageManagerService extends IPackageManager.Stub { final int groupOwner; final String protectedFile; if (isFwdLocked()) { - groupOwner = uid; + groupOwner = UserHandle.getSharedAppGid(uid); protectedFile = RES_FILE_NAME; } else { groupOwner = -1; @@ -7371,7 +7371,8 @@ public class PackageManagerService extends IPackageManager.Stub { int doPostCopy(int uid) { if (isFwdLocked()) { if (uid < Process.FIRST_APPLICATION_UID - || !PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME)) { + || !PackageHelper.fixSdPermissions(cid, UserHandle.getSharedAppGid(uid), + RES_FILE_NAME)) { Slog.e(TAG, "Failed to finalize " + cid); PackageHelper.destroySdDir(cid); return PackageManager.INSTALL_FAILED_CONTAINER_ERROR; diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs index 7d9d3acf7875..783bc4a29cc0 100644 --- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs @@ -43,9 +43,9 @@ int32_t gHeight; rs_allocation gBlendSource; void blend9(uchar *out, uint32_t x, uint32_t y) { - uint32_t x1 = min((int32_t)x+1, (int32_t)gWidth); + uint32_t x1 = min((int32_t)x+1, (int32_t)(gWidth -1)); uint32_t x2 = max((int32_t)x-1, (int32_t)0); - uint32_t y1 = min((int32_t)y+1, (int32_t)gHeight); + uint32_t y1 = min((int32_t)y+1, (int32_t)(gHeight -1)); uint32_t y2 = max((int32_t)y-1, (int32_t)0); uint p00 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0]; @@ -69,7 +69,8 @@ void blend9(uchar *out, uint32_t x, uint32_t y) { p20 += p22; p20 += p02; - *out = (uchar)(p20 >> 10); + p20 = min(p20 >> 10, (uint)255); + *out = (uchar)p20; } float gNoiseStrength; |