diff options
116 files changed, 1988 insertions, 1306 deletions
diff --git a/api/current.txt b/api/current.txt index d7359f8519aa..8f9641c5d18a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -156,7 +156,6 @@ package android { field public static final java.lang.String WRITE_PROFILE = "android.permission.WRITE_PROFILE"; field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS"; field public static final java.lang.String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS"; - field public static final java.lang.String WRITE_SMS = "android.permission.WRITE_SMS"; field public static final deprecated java.lang.String WRITE_SOCIAL_STREAM = "android.permission.WRITE_SOCIAL_STREAM"; field public static final java.lang.String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS"; field public static final java.lang.String WRITE_USER_DICTIONARY = "android.permission.WRITE_USER_DICTIONARY"; @@ -2026,6 +2025,7 @@ package android { field public static final int ThemeOverlay_Material_Dark = 16974411; // 0x103024b field public static final int ThemeOverlay_Material_Dark_ActionBar = 16974412; // 0x103024c field public static final int ThemeOverlay_Material_Dialog = 16974564; // 0x10302e4 + field public static final int ThemeOverlay_Material_Dialog_Alert = 16974566; // 0x10302e6 field public static final int ThemeOverlay_Material_Light = 16974410; // 0x103024a field public static final int Theme_Black = 16973832; // 0x1030008 field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009 @@ -13177,6 +13177,7 @@ package android.hardware.camera2 { field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AE; field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF; field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB; + field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> DEPTH_DEPTH_IS_EXCLUSIVE; field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> EDGE_AVAILABLE_EDGE_MODES; field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> FLASH_INFO_AVAILABLE; field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES; @@ -13405,6 +13406,7 @@ package android.hardware.camera2 { field public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2; // 0x2 field public static final int HOT_PIXEL_MODE_OFF = 0; // 0x0 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1 + field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; // 0x3 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0 field public static final int LENS_FACING_BACK = 1; // 0x1 @@ -13423,6 +13425,7 @@ package android.hardware.camera2 { field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0 field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0 field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6 + field public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8; // 0x8 field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2 field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1 field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4 @@ -14910,9 +14913,12 @@ package android.media { method public int getSampleRate(); method public int getState(); method public int read(byte[], int, int); + method public int read(byte[], int, int, int); method public int read(short[], int, int); + method public int read(short[], int, int, int); method public int read(float[], int, int, int); method public int read(java.nio.ByteBuffer, int); + method public int read(java.nio.ByteBuffer, int, int); method public void release(); method public int setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); @@ -14995,7 +15001,9 @@ package android.media { method public int setVolume(float); method public void stop() throws java.lang.IllegalStateException; method public int write(byte[], int, int); + method public int write(byte[], int, int, int); method public int write(short[], int, int); + method public int write(short[], int, int, int); method public int write(float[], int, int, int); method public int write(java.nio.ByteBuffer, int, int); field public static final int ERROR = -1; // 0xffffffff @@ -36561,7 +36569,6 @@ package android.view { ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int); ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int, int); method public boolean addStatesFromChildren(); - method public void addTransientView(android.view.View, int); method public void addView(android.view.View); method public void addView(android.view.View, int); method public void addView(android.view.View, int, int); @@ -36613,9 +36620,6 @@ package android.view { method public int getNestedScrollAxes(); method public int getPersistentDrawingCache(); method public boolean getTouchscreenBlocksFocus(); - method public android.view.View getTransientView(int); - method public int getTransientViewCount(); - method public int getTransientViewIndex(int); method public int indexOfChild(android.view.View); method public final void invalidateChild(android.view.View, android.graphics.Rect); method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect); @@ -36649,7 +36653,6 @@ package android.view { method public void removeAllViews(); method public void removeAllViewsInLayout(); method protected void removeDetachedView(android.view.View, boolean); - method public void removeTransientView(android.view.View); method public void removeView(android.view.View); method public void removeViewAt(int); method public void removeViewInLayout(android.view.View); diff --git a/api/system-current.txt b/api/system-current.txt index 02842a5f2094..0f837c244c2b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -228,7 +228,6 @@ package android { field public static final java.lang.String WRITE_PROFILE = "android.permission.WRITE_PROFILE"; field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS"; field public static final java.lang.String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS"; - field public static final java.lang.String WRITE_SMS = "android.permission.WRITE_SMS"; field public static final deprecated java.lang.String WRITE_SOCIAL_STREAM = "android.permission.WRITE_SOCIAL_STREAM"; field public static final java.lang.String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS"; field public static final java.lang.String WRITE_USER_DICTIONARY = "android.permission.WRITE_USER_DICTIONARY"; @@ -2105,6 +2104,7 @@ package android { field public static final int ThemeOverlay_Material_Dark = 16974411; // 0x103024b field public static final int ThemeOverlay_Material_Dark_ActionBar = 16974412; // 0x103024c field public static final int ThemeOverlay_Material_Dialog = 16974564; // 0x10302e4 + field public static final int ThemeOverlay_Material_Dialog_Alert = 16974566; // 0x10302e6 field public static final int ThemeOverlay_Material_Light = 16974410; // 0x103024a field public static final int Theme_Black = 16973832; // 0x1030008 field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009 @@ -13473,6 +13473,7 @@ package android.hardware.camera2 { field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AE; field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF; field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB; + field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> DEPTH_DEPTH_IS_EXCLUSIVE; field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> EDGE_AVAILABLE_EDGE_MODES; field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> FLASH_INFO_AVAILABLE; field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES; @@ -13701,6 +13702,7 @@ package android.hardware.camera2 { field public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2; // 0x2 field public static final int HOT_PIXEL_MODE_OFF = 0; // 0x0 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1 + field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; // 0x3 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2 field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0 field public static final int LENS_FACING_BACK = 1; // 0x1 @@ -13719,6 +13721,7 @@ package android.hardware.camera2 { field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0 field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0 field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6 + field public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8; // 0x8 field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2 field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1 field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4 @@ -16120,9 +16123,12 @@ package android.media { method public int getSampleRate(); method public int getState(); method public int read(byte[], int, int); + method public int read(byte[], int, int, int); method public int read(short[], int, int); + method public int read(short[], int, int, int); method public int read(float[], int, int, int); method public int read(java.nio.ByteBuffer, int); + method public int read(java.nio.ByteBuffer, int, int); method public void release(); method public int setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); @@ -16207,7 +16213,9 @@ package android.media { method public int setVolume(float); method public void stop() throws java.lang.IllegalStateException; method public int write(byte[], int, int); + method public int write(byte[], int, int, int); method public int write(short[], int, int); + method public int write(short[], int, int, int); method public int write(float[], int, int, int); method public int write(java.nio.ByteBuffer, int, int); field public static final int ERROR = -1; // 0xffffffff @@ -32712,10 +32720,6 @@ package android.telephony { field public static final java.lang.String BOOL_CARRIER_VOLTE_TTY_SUPPORTED = "bool_carrier_volte_tty_supported"; field public static final java.lang.String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma"; field public static final java.lang.String INT_VOLTE_REPLACEMENT_RAT = "int_volte_replacement_rat"; - field public static final java.lang.String SHORT_VVM_PORT_NUMBER = "string_vvm_port_number"; - field public static final java.lang.String STRING_VVM_DESTINATION_NUMBER = "string_vvm_destination_number"; - field public static final java.lang.String STRING_VVM_TYPE = "string_vvm_type"; - field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp"; } public final class CellIdentityCdma implements android.os.Parcelable { @@ -38763,7 +38767,6 @@ package android.view { ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int); ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int, int); method public boolean addStatesFromChildren(); - method public void addTransientView(android.view.View, int); method public void addView(android.view.View); method public void addView(android.view.View, int); method public void addView(android.view.View, int, int); @@ -38815,9 +38818,6 @@ package android.view { method public int getNestedScrollAxes(); method public int getPersistentDrawingCache(); method public boolean getTouchscreenBlocksFocus(); - method public android.view.View getTransientView(int); - method public int getTransientViewCount(); - method public int getTransientViewIndex(int); method public int indexOfChild(android.view.View); method public final void invalidateChild(android.view.View, android.graphics.Rect); method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect); @@ -38851,7 +38851,6 @@ package android.view { method public void removeAllViews(); method public void removeAllViewsInLayout(); method protected void removeDetachedView(android.view.View, boolean); - method public void removeTransientView(android.view.View); method public void removeView(android.view.View); method public void removeViewAt(int); method public void removeViewInLayout(android.view.View); diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk index dd5e0ea51bb1..ce6d7b518349 100644 --- a/cmds/app_process/Android.mk +++ b/cmds/app_process/Android.mk @@ -56,6 +56,7 @@ LOCAL_MODULE_TAGS := eng LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan LOCAL_MODULE_STEM := app_process LOCAL_ADDRESS_SANITIZER := true +LOCAL_CLANG := true LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 256d87dbf61d..add7af228cd6 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -93,15 +93,20 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM } static boolean sSystemReady = false; + static public void broadcastStickyIntent(Intent intent, String permission, int userId) { + broadcastStickyIntent(intent, permission, AppOpsManager.OP_NONE, userId); + } + /** * Convenience for sending a sticky broadcast. For internal use only. * If you don't care about permission, use null. */ - static public void broadcastStickyIntent(Intent intent, String permission, int userId) { + static public void broadcastStickyIntent(Intent intent, String permission, int appOp, + int userId) { try { getDefault().broadcastIntent( null, intent, null, null, Activity.RESULT_OK, null, null, - null /*permission*/, AppOpsManager.OP_NONE, false, true, userId); + null /*permission*/, appOp, false, true, userId); } catch (RemoteException ex) { } } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 381c20c136f4..24ebb33a7cda 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -16,6 +16,7 @@ package android.app; +import android.Manifest; import android.annotation.SystemApi; import android.app.usage.UsageStatsManager; import android.content.Context; @@ -212,8 +213,10 @@ public class AppOpsManager { public static final int OP_ASSIST_STRUCTURE = 49; /** @hide Received a screenshot from assist. */ public static final int OP_ASSIST_SCREENSHOT = 50; + /** @hide Read the phone state. */ + public static final int OP_READ_PHONE_STATE = 51; /** @hide */ - public static final int _NUM_OP = 51; + public static final int _NUM_OP = 52; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = @@ -294,6 +297,7 @@ public class AppOpsManager { OP_WRITE_WALLPAPER, OP_ASSIST_STRUCTURE, OP_ASSIST_SCREENSHOT, + OP_READ_PHONE_STATE }; /** @@ -352,6 +356,7 @@ public class AppOpsManager { null, null, null, + null }; /** @@ -409,7 +414,8 @@ public class AppOpsManager { "ACTIVATE_VPN", "WRITE_WALLPAPER", "ASSIST_STRUCTURE", - "ASSIST_SCREENSHOT" + "ASSIST_SCREENSHOT", + "OP_READ_PHONE_STATE" }; /** @@ -432,14 +438,14 @@ public class AppOpsManager { null, // neighboring cells shares the coarse location perm android.Manifest.permission.CALL_PHONE, android.Manifest.permission.READ_SMS, - android.Manifest.permission.WRITE_SMS, + null, // no permission required for writing sms android.Manifest.permission.RECEIVE_SMS, android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, android.Manifest.permission.RECEIVE_MMS, android.Manifest.permission.RECEIVE_WAP_PUSH, android.Manifest.permission.SEND_SMS, android.Manifest.permission.READ_SMS, - android.Manifest.permission.WRITE_SMS, + null, // no permission required for writing icc sms android.Manifest.permission.WRITE_SETTINGS, android.Manifest.permission.SYSTEM_ALERT_WINDOW, android.Manifest.permission.ACCESS_NOTIFICATIONS, @@ -468,6 +474,7 @@ public class AppOpsManager { null, // no permission for supporting wallpaper null, // no permission for receiving assist structure null, // no permission for receiving assist screenshot + Manifest.permission.READ_PHONE_STATE }; /** @@ -527,6 +534,7 @@ public class AppOpsManager { UserManager.DISALLOW_WALLPAPER, // WRITE_WALLPAPER null, // ASSIST_STRUCTURE null, // ASSIST_SCREENSHOT + null // READ_PHONE_STATE }; /** @@ -585,6 +593,7 @@ public class AppOpsManager { false, //WALLPAPER false, //ASSIST_STRUCTURE false, //ASSIST_SCREENSHOT + false, //READ_PHONE_STATE }; /** @@ -642,6 +651,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED }; /** @@ -703,6 +713,7 @@ public class AppOpsManager { false, false, false, + false }; private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4ccd69fa5088..81a78f6cb256 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -860,13 +860,19 @@ class ContextImpl extends Context { @Override public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) { + sendBroadcastAsUser(intent, user, receiverPermission, AppOpsManager.OP_NONE); + } + + @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( - mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, false, false, - user.getIdentifier()); + mMainThread.getApplicationThread(), intent, resolvedType, null, + Activity.RESULT_OK, null, null, receiverPermission, appOp, false, false, + user.getIdentifier()); } catch (RemoteException e) { } } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index e446700317ab..46da025e8ec2 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -332,10 +332,10 @@ final class SystemServiceRegistry { }}); registerService(Context.NETWORK_POLICY_SERVICE, NetworkPolicyManager.class, - new StaticServiceFetcher<NetworkPolicyManager>() { + new CachedServiceFetcher<NetworkPolicyManager>() { @Override - public NetworkPolicyManager createService() { - return new NetworkPolicyManager(INetworkPolicyManager.Stub.asInterface( + public NetworkPolicyManager createService(ContextImpl ctx) { + return new NetworkPolicyManager(ctx, INetworkPolicyManager.Stub.asInterface( ServiceManager.getService(Context.NETWORK_POLICY_SERVICE))); }}); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 370f61cd7b30..3bf3f855ac0c 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1608,6 +1608,28 @@ public abstract class Context { public abstract void sendBroadcastAsUser(Intent intent, UserHandle user, @Nullable String receiverPermission); + + /** + * Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the + * user the broadcast will be sent to. This is not available to applications + * that are not pre-installed on the system image. Using it requires holding + * the INTERACT_ACROSS_USERS permission. + * + * @param intent The Intent to broadcast; all receivers matching this + * Intent will receive the broadcast. + * @param user UserHandle to send the intent to. + * @param receiverPermission (optional) String naming a permission that + * a receiver must hold in order to receive your broadcast. + * If null, no permission is required. + * @param appOp The app op associated with the broadcast. + * + * @see #sendBroadcast(Intent, String) + * + * @hide + */ + public abstract void sendBroadcastAsUser(Intent intent, UserHandle user, + @Nullable String receiverPermission, int appOp); + /** * Version of * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)} diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 92f0079b95e7..fb9e19490eb3 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -444,6 +444,13 @@ public class ContextWrapper extends Context { mBase.sendBroadcastAsUser(intent, user, receiverPermission); } + /** @hide */ + @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp) { + mBase.sendBroadcastAsUser(intent, user, receiverPermission, appOp); + } + @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 88fa339a53cb..7ad3a683cd6f 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -26,6 +26,7 @@ import android.util.SparseBooleanArray; import android.util.SparseIntArray; import dalvik.system.CloseGuard; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -224,8 +225,8 @@ public class SystemSensorManager extends SensorManager { * the queues and the listeners. */ private static abstract class BaseEventQueue { - private native long nativeInitBaseEventQueue(BaseEventQueue eventQ, MessageQueue msgQ, - float[] scratch, String packageName); + private native long nativeInitBaseEventQueue(WeakReference<BaseEventQueue> eventQWeak, + MessageQueue msgQ, float[] scratch, String packageName); private static native int nativeEnableSensor(long eventQ, int handle, int rateUs, int maxBatchReportLatencyUs); private static native int nativeDisableSensor(long eventQ, int handle); @@ -240,7 +241,8 @@ public class SystemSensorManager extends SensorManager { protected final SystemSensorManager mManager; BaseEventQueue(Looper looper, SystemSensorManager manager) { - nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch, + nSensorEventQueue = nativeInitBaseEventQueue(new WeakReference<BaseEventQueue>(this), + looper.getQueue(), mScratch, manager.mPackageName); mCloseGuard.open("dispose"); mManager = manager; diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 8f7aed4f5919..87a1ca962545 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1030,12 +1030,13 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity * (depth) in pixel coordinates.</p> * <p><b>Units</b>: - * Pixels in the android.sensor.activeArraySize coordinate + * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate * system.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * * @see CameraCharacteristics#LENS_POSE_ROTATION * @see CameraCharacteristics#LENS_POSE_TRANSLATION + * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE */ @PublicKey public static final Key<float[]> LENS_INTRINSIC_CALIBRATION = @@ -1330,6 +1331,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS READ_SENSOR_SETTINGS}</li> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}</li> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING}</li> + * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT DEPTH_OUTPUT}</li> * </ul></p> * <p>This key is available on all devices.</p> * @@ -1342,6 +1344,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * @see #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS * @see #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE * @see #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING + * @see #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT */ @PublicKey public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES = @@ -2542,11 +2545,23 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * post-processing, arbitrary cropping regions, and has relaxed performance constraints.</p> * <p>Each higher level supports everything the lower level supports * in this order: FULL <code>></code> LIMITED <code>></code> LEGACY.</p> + * <p>A HIGH_RESOLUTION device is equivalent to a FULL device, except that:</p> + * <ul> + * <li>At least one output resolution of 8 megapixels or higher in uncompressed YUV is + * supported at <code>>=</code> 20 fps.</li> + * <li>Maximum-size (sensor resolution) uncompressed YUV is supported at <code>>=</code> 10 + * fps.</li> + * <li>For devices that list the RAW capability and support either RAW10 or RAW12 output, + * maximum-resolution RAW10 or RAW12 capture will operate at least at the rate of + * maximum-resolution YUV capture, and at least one supported output resolution of + * 8 megapixels or higher in RAW10 or RAW12 is supported <code>>=</code> 20 fps.</li> + * </ul> * <p><b>Possible values:</b> * <ul> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}</li> + * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION HIGH_RESOLUTION}</li> * </ul></p> * <p>This key is available on all devices.</p> * @@ -2564,6 +2579,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY + * @see #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION */ @PublicKey public static final Key<Integer> INFO_SUPPORTED_HARDWARE_LEVEL = @@ -2694,6 +2710,29 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS = new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.depth.availableDepthStallDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class); + /** + * <p>Indicates whether a capture request may target both a + * DEPTH16 / DEPTH_POINT_CLOUD output, and normal color outputs (such as + * YUV_420_888, JPEG, or RAW) simultaneously.</p> + * <p>If TRUE, including both depth and color outputs in a single + * capture request is not supported. An application must interleave color + * and depth requests. If FALSE, a single request can target both types + * of output.</p> + * <p>Typically, this restriction exists on camera devices that + * need to emit a specific pattern or wavelength of light to + * measure depth values, which causes the color image to be + * corrupted during depth measurement.</p> + * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> + * + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + */ + @PublicKey + public static final Key<Boolean> DEPTH_DEPTH_IS_EXCLUSIVE = + new Key<Boolean>("android.depth.depthIsExclusive", boolean.class); + /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ * End generated code *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/ diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 4a5bd08372b6..e3f1d7366e4c 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -303,10 +303,13 @@ public abstract class CameraMetadata<TKey> { * <p>The minimal set of capabilities that every camera * device (regardless of {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel}) * supports.</p> - * <p>This capability is listed by all devices, and + * <p>This capability is listed by all normal devices, and * indicates that the camera device has a feature set * that's comparable to the baseline requirements for the * older android.hardware.Camera API.</p> + * <p>Devices with the DEPTH_OUTPUT capability might not list this + * capability, indicating that they support only depth measurement, + * not standard color output.</p> * * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES @@ -545,6 +548,11 @@ public abstract class CameraMetadata<TKey> { * {@link CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE android.control.awbLockAvailable} are also guaranteed * to be <code>true</code> so burst capture with these two locks ON * yields consistent image output.</p> + * <p>On a camera device that reports the HIGH_RESOLUTION hardware + * level, meaning the device supports very large capture sizes, + * BURST_CAPTURE means that at least 8-megapixel images can be + * captured at <code>>=</code> 20 fps, and maximum-resolution images can be + * captured at <code>>=</code> 10 fps.</p> * * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES * @see CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE @@ -596,6 +604,42 @@ public abstract class CameraMetadata<TKey> { */ public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7; + /** + * <p>The camera device can produce depth measurements from its field of view.</p> + * <p>This capability requires the camera device to support the following:</p> + * <ul> + * <li>DEPTH16 is supported as an output format.</li> + * <li>DEPTH_POINT_CLOUD is optionally supported as an output format.</li> + * <li>This camera device, and all camera devices with the same android.lens.info.facing, + * will list the following calibration entries in both CameraCharacteristics and + * CaptureResults:<ul> + * <li>{@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}</li> + * <li>{@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}</li> + * <li>android.lens.intrinsicCalibration</li> + * <li>android.lens.radialDistortion</li> + * </ul> + * </li> + * <li>The {@link CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE android.depth.depthIsExclusive} entry is listed by this device.</li> + * <li>A LIMITED camera with only the DEPTH_OUTPUT capability does not have to support + * normal YUV_420_888, JPEG, and PRIV-format outputs. It only has to support the DEPTH16 + * format.</li> + * </ul> + * <p>Generally, depth output operates at a slower frame rate than standard color capture, + * so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that + * should be accounted for (see + * android.hardware.camera2.StreamConfigurationMap#getOutputStallDuration). On a device + * that supports both depth and color-based output, to enable smooth preview, using a + * repeating burst is recommended, where a depth-output target is only included once + * every N frames, where N is the ratio between preview output rate and depth output + * rate, including depth stall time.</p> + * + * @see CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE + * @see CameraCharacteristics#LENS_POSE_ROTATION + * @see CameraCharacteristics#LENS_POSE_TRANSLATION + * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES + */ + public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8; + // // Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE // @@ -808,6 +852,13 @@ public abstract class CameraMetadata<TKey> { */ public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; + /** + * <p>This camera device is capable of supporting advanced imaging applications at full rate, + * and additional high-resolution outputs at lower rates.</p> + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + */ + public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; + // // Enumeration values for CameraCharacteristics#SYNC_MAX_LATENCY // diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 4134d28c4391..ef5d75c7fc8e 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -2628,12 +2628,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity * (depth) in pixel coordinates.</p> * <p><b>Units</b>: - * Pixels in the android.sensor.activeArraySize coordinate + * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate * system.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * * @see CameraCharacteristics#LENS_POSE_ROTATION * @see CameraCharacteristics#LENS_POSE_TRANSLATION + * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE */ @PublicKey public static final Key<float[]> LENS_INTRINSIC_CALIBRATION = diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index 7e92de2c353b..db7c35cd047b 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -45,7 +45,7 @@ interface INetworkPolicyManager { /** Control network policies atomically. */ void setNetworkPolicies(in NetworkPolicy[] policies); - NetworkPolicy[] getNetworkPolicies(); + NetworkPolicy[] getNetworkPolicies(String callingPackage); /** Snooze limit on policy matching given template. */ void snoozeLimit(in NetworkTemplate template); diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index a7ffee924bbf..25ad92853b48 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -61,12 +61,14 @@ public class NetworkPolicyManager { */ public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE"; + private final Context mContext; private INetworkPolicyManager mService; - public NetworkPolicyManager(INetworkPolicyManager service) { + public NetworkPolicyManager(Context context, INetworkPolicyManager service) { if (service == null) { throw new IllegalArgumentException("missing INetworkPolicyManager"); } + mContext = context; mService = service; } @@ -158,7 +160,7 @@ public class NetworkPolicyManager { public NetworkPolicy[] getNetworkPolicies() { try { - return mService.getNetworkPolicies(); + return mService.getNetworkPolicies(mContext.getOpPackageName()); } catch (RemoteException e) { return null; } diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java index 2c60d41acd94..2f63988c4e44 100644 --- a/core/java/android/os/storage/DiskInfo.java +++ b/core/java/android/os/storage/DiskInfo.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.content.res.Resources; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import android.util.DebugUtils; import com.android.internal.util.IndentingPrintWriter; @@ -46,7 +47,6 @@ public class DiskInfo implements Parcelable { public final int flags; public long size; public String label; - public String[] volumeIds; public DiskInfo(String id, int flags) { this.id = Preconditions.checkNotNull(id); @@ -58,7 +58,6 @@ public class DiskInfo implements Parcelable { flags = parcel.readInt(); size = parcel.readLong(); label = parcel.readString(); - volumeIds = parcel.readStringArray(); } public @NonNull String getId() { @@ -66,11 +65,19 @@ public class DiskInfo implements Parcelable { } public String getDescription() { - // TODO: splice vendor label into these strings + final Resources res = Resources.getSystem(); if ((flags & FLAG_SD) != 0) { - return Resources.getSystem().getString(com.android.internal.R.string.storage_sd_card); + if (TextUtils.isEmpty(label)) { + return res.getString(com.android.internal.R.string.storage_sd_card); + } else { + return res.getString(com.android.internal.R.string.storage_sd_card_label, label); + } } else if ((flags & FLAG_USB) != 0) { - return Resources.getSystem().getString(com.android.internal.R.string.storage_usb); + if (TextUtils.isEmpty(label)) { + return res.getString(com.android.internal.R.string.storage_usb_drive); + } else { + return res.getString(com.android.internal.R.string.storage_usb_drive_label, label); + } } else { return null; } @@ -96,13 +103,11 @@ public class DiskInfo implements Parcelable { } public void dump(IndentingPrintWriter pw) { - pw.println("DiskInfo:"); + pw.println("DiskInfo{" + id + "}:"); pw.increaseIndent(); - pw.printPair("id", id); pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags)); pw.printPair("size", size); pw.printPair("label", label); - pw.printPair("volumeIds", volumeIds); pw.decreaseIndent(); pw.println(); } @@ -156,6 +161,5 @@ public class DiskInfo implements Parcelable { parcel.writeInt(this.flags); parcel.writeLong(size); parcel.writeString(label); - parcel.writeStringArray(volumeIds); } } diff --git a/core/java/android/os/storage/IMountServiceListener.java b/core/java/android/os/storage/IMountServiceListener.java index fd914bc843ab..8e878a4753af 100644 --- a/core/java/android/os/storage/IMountServiceListener.java +++ b/core/java/android/os/storage/IMountServiceListener.java @@ -98,6 +98,13 @@ public interface IMountServiceListener extends IInterface { reply.writeNoException(); return true; } + case TRANSACTION_onDiskUnsupported: { + data.enforceInterface(DESCRIPTOR); + final DiskInfo disk = (DiskInfo) data.readParcelable(null); + onDiskUnsupported(disk); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -198,6 +205,22 @@ public interface IMountServiceListener extends IInterface { _data.recycle(); } } + + @Override + public void onDiskUnsupported(DiskInfo disk) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeParcelable(disk, 0); + mRemote.transact(Stub.TRANSACTION_onDiskUnsupported, _data, _reply, + android.os.IBinder.FLAG_ONEWAY); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + } } static final int TRANSACTION_onUsbMassStorageConnectionChanged = (IBinder.FIRST_CALL_TRANSACTION + 0); @@ -206,6 +229,7 @@ public interface IMountServiceListener extends IInterface { static final int TRANSACTION_onVolumeStateChanged = (IBinder.FIRST_CALL_TRANSACTION + 2); static final int TRANSACTION_onVolumeMetadataChanged = (IBinder.FIRST_CALL_TRANSACTION + 3); + static final int TRANSACTION_onDiskUnsupported = (IBinder.FIRST_CALL_TRANSACTION + 4); } /** @@ -230,4 +254,6 @@ public interface IMountServiceListener extends IInterface { throws RemoteException; public void onVolumeMetadataChanged(VolumeInfo vol) throws RemoteException; + + public void onDiskUnsupported(DiskInfo disk) throws RemoteException; } diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java index 28a187d02911..ad2fae0b7600 100644 --- a/core/java/android/os/storage/StorageEventListener.java +++ b/core/java/android/os/storage/StorageEventListener.java @@ -43,4 +43,7 @@ public class StorageEventListener { public void onVolumeMetadataChanged(VolumeInfo vol) { } + + public void onDiskUnsupported(DiskInfo disk) { + } } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 0e977ff6f1b7..b49c14e98ef2 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -87,6 +87,7 @@ public class StorageManager { private static final int MSG_STORAGE_STATE_CHANGED = 1; private static final int MSG_VOLUME_STATE_CHANGED = 2; private static final int MSG_VOLUME_METADATA_CHANGED = 3; + private static final int MSG_DISK_UNSUPPORTED = 4; final StorageEventListener mCallback; final Handler mHandler; @@ -113,6 +114,10 @@ public class StorageManager { mCallback.onVolumeMetadataChanged((VolumeInfo) args.arg1); args.recycle(); return true; + case MSG_DISK_UNSUPPORTED: + mCallback.onDiskUnsupported((DiskInfo) args.arg1); + args.recycle(); + return true; } args.recycle(); return false; @@ -147,6 +152,13 @@ public class StorageManager { args.arg1 = vol; mHandler.obtainMessage(MSG_VOLUME_METADATA_CHANGED, args).sendToTarget(); } + + @Override + public void onDiskUnsupported(DiskInfo disk) { + final SomeArgs args = SomeArgs.obtain(); + args.arg1 = disk; + mHandler.obtainMessage(MSG_DISK_UNSUPPORTED, args).sendToTarget(); + } } /** diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index a241728557f5..4177380c80bb 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -63,15 +63,17 @@ public class VolumeInfo implements Parcelable { public static final int TYPE_OBB = 4; public static final int STATE_UNMOUNTED = 0; - public static final int STATE_MOUNTING = 1; + public static final int STATE_CHECKING = 1; public static final int STATE_MOUNTED = 2; - public static final int STATE_FORMATTING = 3; - public static final int STATE_UNMOUNTING = 4; - public static final int STATE_UNMOUNTABLE = 5; - public static final int STATE_REMOVED = 6; + public static final int STATE_MOUNTED_READ_ONLY = 3; + public static final int STATE_FORMATTING = 4; + public static final int STATE_EJECTING = 5; + public static final int STATE_UNMOUNTABLE = 6; + public static final int STATE_REMOVED = 7; + public static final int STATE_BAD_REMOVAL = 8; - public static final int FLAG_PRIMARY = 1 << 0; - public static final int FLAG_VISIBLE = 1 << 1; + public static final int MOUNT_FLAG_PRIMARY = 1 << 0; + public static final int MOUNT_FLAG_VISIBLE = 1 << 1; public static final int USER_FLAG_INITED = 1 << 0; public static final int USER_FLAG_SNOOZED = 1 << 1; @@ -97,10 +99,10 @@ public class VolumeInfo implements Parcelable { static { sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTED, Environment.MEDIA_UNMOUNTED); - sStateToEnvironment.put(VolumeInfo.STATE_MOUNTING, Environment.MEDIA_CHECKING); + sStateToEnvironment.put(VolumeInfo.STATE_CHECKING, Environment.MEDIA_CHECKING); sStateToEnvironment.put(VolumeInfo.STATE_MOUNTED, Environment.MEDIA_MOUNTED); sStateToEnvironment.put(VolumeInfo.STATE_FORMATTING, Environment.MEDIA_UNMOUNTED); - sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTING, Environment.MEDIA_EJECTING); + sStateToEnvironment.put(VolumeInfo.STATE_EJECTING, Environment.MEDIA_EJECTING); sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTABLE, Environment.MEDIA_UNMOUNTABLE); sStateToEnvironment.put(VolumeInfo.STATE_REMOVED, Environment.MEDIA_REMOVED); @@ -115,8 +117,9 @@ public class VolumeInfo implements Parcelable { /** vold state */ public final String id; public final int type; - public int flags = 0; - public int userId = -1; + public final String diskId; + public int mountFlags = 0; + public int mountUserId = -1; public int state = STATE_UNMOUNTED; public String fsType; public String fsUuid; @@ -125,28 +128,28 @@ public class VolumeInfo implements Parcelable { /** Framework state */ public final int mtpIndex; - public String diskId; public String nickname; public int userFlags = 0; - public VolumeInfo(String id, int type, int mtpIndex) { + public VolumeInfo(String id, int type, String diskId, int mtpIndex) { this.id = Preconditions.checkNotNull(id); this.type = type; + this.diskId = diskId; this.mtpIndex = mtpIndex; } public VolumeInfo(Parcel parcel) { id = parcel.readString(); type = parcel.readInt(); - flags = parcel.readInt(); - userId = parcel.readInt(); + diskId = parcel.readString(); + mountFlags = parcel.readInt(); + mountUserId = parcel.readInt(); state = parcel.readInt(); fsType = parcel.readString(); fsUuid = parcel.readString(); fsLabel = parcel.readString(); path = parcel.readString(); mtpIndex = parcel.readInt(); - diskId = parcel.readString(); nickname = parcel.readString(); userFlags = parcel.readInt(); } @@ -209,11 +212,11 @@ public class VolumeInfo implements Parcelable { } public boolean isPrimary() { - return (flags & FLAG_PRIMARY) != 0; + return (mountFlags & MOUNT_FLAG_PRIMARY) != 0; } public boolean isVisible() { - return (flags & FLAG_VISIBLE) != 0; + return (mountFlags & MOUNT_FLAG_VISIBLE) != 0; } public boolean isInited() { @@ -225,7 +228,7 @@ public class VolumeInfo implements Parcelable { } public boolean isVisibleToUser(int userId) { - if (type == TYPE_PUBLIC && userId == this.userId) { + if (type == TYPE_PUBLIC && userId == this.mountUserId) { return isVisible(); } else if (type == TYPE_EMULATED) { return isVisible(); @@ -241,7 +244,7 @@ public class VolumeInfo implements Parcelable { public File getPathForUser(int userId) { if (path == null) { return null; - } else if (type == TYPE_PUBLIC && userId == this.userId) { + } else if (type == TYPE_PUBLIC && userId == this.mountUserId) { return new File(path); } else if (type == TYPE_EMULATED) { return new File(path, Integer.toString(userId)); @@ -333,12 +336,12 @@ public class VolumeInfo implements Parcelable { } public void dump(IndentingPrintWriter pw) { - pw.println("VolumeInfo:"); + pw.println("VolumeInfo{" + id + "}:"); pw.increaseIndent(); - pw.printPair("id", id); pw.printPair("type", DebugUtils.valueToString(getClass(), "TYPE_", type)); - pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags)); - pw.printPair("userId", userId); + pw.printPair("diskId", diskId); + pw.printPair("mountFlags", DebugUtils.flagsToString(getClass(), "MOUNT_FLAG_", mountFlags)); + pw.printPair("mountUserId", mountUserId); pw.printPair("state", DebugUtils.valueToString(getClass(), "STATE_", state)); pw.println(); pw.printPair("fsType", fsType); @@ -347,7 +350,6 @@ public class VolumeInfo implements Parcelable { pw.println(); pw.printPair("path", path); pw.printPair("mtpIndex", mtpIndex); - pw.printPair("diskId", diskId); pw.printPair("nickname", nickname); pw.printPair("userFlags", DebugUtils.flagsToString(getClass(), "USER_FLAG_", userFlags)); pw.decreaseIndent(); @@ -401,15 +403,15 @@ public class VolumeInfo implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(id); parcel.writeInt(type); - parcel.writeInt(this.flags); - parcel.writeInt(userId); + parcel.writeString(diskId); + parcel.writeInt(mountFlags); + parcel.writeInt(mountUserId); parcel.writeInt(state); parcel.writeString(fsType); parcel.writeString(fsUuid); parcel.writeString(fsLabel); parcel.writeString(path); parcel.writeInt(mtpIndex); - parcel.writeString(diskId); parcel.writeString(nickname); parcel.writeInt(userFlags); } diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java index de46a4a8f642..5a9a1eacbef6 100644 --- a/core/java/android/view/DisplayEventReceiver.java +++ b/core/java/android/view/DisplayEventReceiver.java @@ -22,6 +22,8 @@ import android.os.Looper; import android.os.MessageQueue; import android.util.Log; +import java.lang.ref.WeakReference; + /** * Provides a low-level mechanism for an application to receive display events * such as vertical sync. @@ -42,7 +44,7 @@ public abstract class DisplayEventReceiver { // GC'd while the native peer of the receiver is using them. private MessageQueue mMessageQueue; - private static native long nativeInit(DisplayEventReceiver receiver, + private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver, MessageQueue messageQueue); private static native void nativeDispose(long receiverPtr); private static native void nativeScheduleVsync(long receiverPtr); @@ -58,7 +60,7 @@ public abstract class DisplayEventReceiver { } mMessageQueue = looper.getQueue(); - mReceiverPtr = nativeInit(this, mMessageQueue); + mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue); mCloseGuard.open("dispose"); } diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java index e9f23536489d..ec8f802a179f 100644 --- a/core/java/android/view/DisplayListCanvas.java +++ b/core/java/android/view/DisplayListCanvas.java @@ -283,7 +283,7 @@ public class DisplayListCanvas extends Canvas { Bitmap bitmap = patch.getBitmap(); throwIfCannotDraw(bitmap); final long nativePaint = paint == null ? 0 : paint.getNativeInstance(); - nDrawPatch(mNativeCanvasWrapper, bitmap, patch.mNativeChunk, + nDrawPatch(mNativeCanvasWrapper, bitmap.getSkBitmap(), patch.mNativeChunk, dst.left, dst.top, dst.right, dst.bottom, nativePaint); } @@ -293,11 +293,11 @@ public class DisplayListCanvas extends Canvas { Bitmap bitmap = patch.getBitmap(); throwIfCannotDraw(bitmap); final long nativePaint = paint == null ? 0 : paint.getNativeInstance(); - nDrawPatch(mNativeCanvasWrapper, bitmap, patch.mNativeChunk, + nDrawPatch(mNativeCanvasWrapper, bitmap.getSkBitmap(), patch.mNativeChunk, dst.left, dst.top, dst.right, dst.bottom, nativePaint); } - private static native void nDrawPatch(long renderer, Bitmap bitmap, long chunk, + private static native void nDrawPatch(long renderer, long bitmap, long chunk, float left, float top, float right, float bottom, long paint); public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy, diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 25c51279fc06..87d5d9a4b1aa 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -360,7 +360,7 @@ public class ThreadedRenderer extends HardwareRenderer { @Override boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) { return nCopyLayerInto(mNativeProxy, - layer.getDeferredLayerUpdater(), bitmap); + layer.getDeferredLayerUpdater(), bitmap.getSkBitmap()); } @Override @@ -460,6 +460,8 @@ public class ThreadedRenderer extends HardwareRenderer { if (buffer != null) { long[] map = atlas.getMap(); if (map != null) { + // TODO Remove after fixing b/15425820 + validateMap(context, map); nSetAtlas(renderProxy, buffer, map); } // If IAssetAtlas is not the same class as the IBinder @@ -474,6 +476,32 @@ public class ThreadedRenderer extends HardwareRenderer { Log.w(LOG_TAG, "Could not acquire atlas", e); } } + + private static void validateMap(Context context, long[] map) { + Log.d("Atlas", "Validating map..."); + HashSet<Long> preloadedPointers = new HashSet<Long>(); + + // We only care about drawables that hold bitmaps + final Resources resources = context.getResources(); + final LongSparseArray<Drawable.ConstantState> drawables = resources.getPreloadedDrawables(); + + final int count = drawables.size(); + ArrayList<Bitmap> tmpList = new ArrayList<Bitmap>(); + for (int i = 0; i < count; i++) { + drawables.valueAt(i).addAtlasableBitmaps(tmpList); + for (int j = 0; j < tmpList.size(); j++) { + preloadedPointers.add(tmpList.get(j).getSkBitmap()); + } + tmpList.clear(); + } + + for (int i = 0; i < map.length; i += 4) { + if (!preloadedPointers.contains(map[i])) { + Log.w("Atlas", String.format("Pointer 0x%X, not in getPreloadedDrawables?", map[i])); + map[i] = 0; + } + } + } } static native void setupShadersDiskCache(String cacheFile); @@ -503,7 +531,7 @@ public class ThreadedRenderer extends HardwareRenderer { private static native long nCreateTextureLayer(long nativeProxy); private static native void nBuildLayer(long nativeProxy, long node); - private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap); + private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap); private static native void nPushLayerUpdate(long nativeProxy, long layer); private static native void nCancelLayerUpdate(long nativeProxy, long layer); private static native void nDetachSurfaceTexture(long nativeProxy, long layer); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index afc0eeef91eb..8f2be990e460 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3858,6 +3858,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * This value is relative to the {@link #getChildAt(int) index} values in the normal * child list of this container, where any transient view at a particular index will * be drawn before any normal child at that same index. + * + * @hide */ public void addTransientView(View view, int index) { if (index < 0) { @@ -3891,6 +3893,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * such transient view, this method does nothing. * * @param view The transient view to be removed + * + * @hide */ public void removeTransientView(View view) { if (mTransientViews == null) { @@ -3916,6 +3920,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * * @see #addTransientView(View, int) * @return The number of transient views in this container + * + * @hide */ public int getTransientViewCount() { return mTransientIndices == null ? 0 : mTransientIndices.size(); @@ -3929,6 +3935,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * and less than the value returned by {@link #getTransientViewCount()}. * @return The index of the transient view stored in the given position if the * position is valid, otherwise -1 + * + * @hide */ public int getTransientViewIndex(int position) { if (position < 0 || mTransientIndices == null || position >= mTransientIndices.size()) { @@ -3945,6 +3953,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * and less than the value returned by {@link #getTransientViewCount()}. * @return The transient view stored in the given position if the * position is valid, otherwise null + * + * @hide */ public View getTransientView(int position) { if (mTransientViews == null || position >= mTransientViews.size()) { diff --git a/core/java/android/widget/CalendarViewMaterialDelegate.java b/core/java/android/widget/CalendarViewMaterialDelegate.java index 7bce7568585f..0ed75d5f7a42 100644 --- a/core/java/android/widget/CalendarViewMaterialDelegate.java +++ b/core/java/android/widget/CalendarViewMaterialDelegate.java @@ -19,6 +19,7 @@ package android.widget; import android.annotation.StyleRes; import android.content.Context; import android.util.AttributeSet; +import android.widget.DayPickerView.OnDaySelectedListener; import java.util.Calendar; @@ -109,8 +110,7 @@ class CalendarViewMaterialDelegate extends CalendarView.AbstractCalendarViewDele mOnDateChangeListener = listener; } - private final DayPickerView.OnDaySelectedListener mOnDaySelectedListener = - new DayPickerView.OnDaySelectedListener() { + private final OnDaySelectedListener mOnDaySelectedListener = new OnDaySelectedListener() { @Override public void onDaySelected(DayPickerView view, Calendar day) { if (mOnDateChangeListener != null) { diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java index 06a5bd28c92e..d38a225ae209 100755 --- a/core/java/android/widget/DatePickerCalendarDelegate.java +++ b/core/java/android/widget/DatePickerCalendarDelegate.java @@ -34,8 +34,6 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; import android.widget.DayPickerView.OnDaySelectedListener; import android.widget.YearPickerView.OnYearSelectedListener; @@ -549,7 +547,7 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { final int listPosition = ss.getListPosition(); if (listPosition != -1) { if (currentView == VIEW_MONTH_DAY) { - mDayPickerView.setCurrentItem(listPosition); + mDayPickerView.setPosition(listPosition); } else if (currentView == VIEW_YEAR) { final int listPositionOffset = ss.getListPositionOffset(); mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset); diff --git a/core/java/android/widget/DayPickerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java index 9a4b6f55f617..478fa00d4607 100644 --- a/core/java/android/widget/DayPickerAdapter.java +++ b/core/java/android/widget/DayPickerPagerAdapter.java @@ -36,7 +36,7 @@ import java.util.Calendar; /** * An adapter for a list of {@link android.widget.SimpleMonthView} items. */ -class DayPickerAdapter extends PagerAdapter { +class DayPickerPagerAdapter extends PagerAdapter { private static final int MONTHS_IN_YEAR = 12; private final Calendar mMinDate = Calendar.getInstance(); @@ -63,7 +63,7 @@ class DayPickerAdapter extends PagerAdapter { private int mCount; private int mFirstDayOfWeek; - public DayPickerAdapter(@NonNull Context context, @LayoutRes int layoutResId, + public DayPickerPagerAdapter(@NonNull Context context, @LayoutRes int layoutResId, @IdRes int calendarViewId) { mInflater = LayoutInflater.from(context); mLayoutResId = layoutResId; @@ -200,7 +200,8 @@ class DayPickerAdapter extends PagerAdapter { final int yearOffset = (day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR)); final int monthOffset = (day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH)); - return yearOffset * MONTHS_IN_YEAR + monthOffset; + final int position = yearOffset * MONTHS_IN_YEAR + monthOffset; + return position; } @Override @@ -253,8 +254,6 @@ class DayPickerAdapter extends PagerAdapter { v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek, enabledDayRangeStart, enabledDayRangeEnd); - v.setPrevEnabled(position > 0); - v.setNextEnabled(position < mCount - 1); final ViewHolder holder = new ViewHolder(position, itemView, v); mItems.put(position, holder); @@ -298,17 +297,10 @@ class DayPickerAdapter extends PagerAdapter { setSelectedDay(day); if (mOnDaySelectedListener != null) { - mOnDaySelectedListener.onDaySelected(DayPickerAdapter.this, day); + mOnDaySelectedListener.onDaySelected(DayPickerPagerAdapter.this, day); } } } - - @Override - public void onNavigationClick(SimpleMonthView view, int direction, boolean animate) { - if (mOnDaySelectedListener != null) { - mOnDaySelectedListener.onNavigationClick(DayPickerAdapter.this, direction, animate); - } - } }; private static class ViewHolder { @@ -324,7 +316,6 @@ class DayPickerAdapter extends PagerAdapter { } public interface OnDaySelectedListener { - public void onDaySelected(DayPickerAdapter view, Calendar day); - public void onNavigationClick(DayPickerAdapter view, int direction, boolean animate); + public void onDaySelected(DayPickerPagerAdapter view, Calendar day); } } diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java index 0e0b2d38d4fe..c6b4d7e3aaf3 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,37 +16,44 @@ package android.widget; -import com.android.internal.widget.ViewPager; import com.android.internal.R; +import com.android.internal.widget.ViewPager; +import com.android.internal.widget.ViewPager.OnPageChangeListener; +import android.annotation.Nullable; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.MathUtils; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; -import java.util.ArrayList; import java.util.Calendar; import java.util.Locale; import libcore.icu.LocaleData; -/** - * This displays a list of months in a calendar format with selectable days. - */ -class DayPickerView extends ViewPager { +class DayPickerView extends ViewGroup { + private static final int DEFAULT_LAYOUT = R.layout.day_picker_content_material; private static final int DEFAULT_START_YEAR = 1900; private static final int DEFAULT_END_YEAR = 2100; + private static final int[] ATTRS_TEXT_COLOR = new int[] { R.attr.textColor }; + private final Calendar mSelectedDay = Calendar.getInstance(); private final Calendar mMinDate = Calendar.getInstance(); private final Calendar mMaxDate = Calendar.getInstance(); - private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1); + private final AccessibilityManager mAccessibilityManager; + + private final ViewPager mViewPager; + private final ImageButton mPrevButton; + private final ImageButton mNextButton; - private final DayPickerAdapter mAdapter; + private final DayPickerPagerAdapter mAdapter; /** Temporary calendar used for date calculations. */ private Calendar mTempCalendar; @@ -57,17 +64,21 @@ class DayPickerView extends ViewPager { this(context, null); } - public DayPickerView(Context context, AttributeSet attrs) { + public DayPickerView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, R.attr.calendarViewStyle); } - public DayPickerView(Context context, AttributeSet attrs, int defStyleAttr) { + public DayPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } - public DayPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + public DayPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, + int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + mAccessibilityManager = (AccessibilityManager) context.getSystemService( + Context.ACCESSIBILITY_SERVICE); + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CalendarView, defStyleAttr, defStyleRes); @@ -93,14 +104,44 @@ class DayPickerView extends ViewPager { a.recycle(); // Set up adapter. - mAdapter = new DayPickerAdapter(context, + mAdapter = new DayPickerPagerAdapter(context, R.layout.date_picker_month_item_material, R.id.month_view); mAdapter.setMonthTextAppearance(monthTextAppearanceResId); mAdapter.setDayOfWeekTextAppearance(dayOfWeekTextAppearanceResId); mAdapter.setDayTextAppearance(dayTextAppearanceResId); mAdapter.setDaySelectorColor(daySelectorColor); - setAdapter(mAdapter); + final LayoutInflater inflater = LayoutInflater.from(context); + final ViewGroup content = (ViewGroup) inflater.inflate(DEFAULT_LAYOUT, this, false); + + // Transfer all children from content to here. + while (content.getChildCount() > 0) { + final View child = content.getChildAt(0); + content.removeViewAt(0); + addView(child); + } + + mPrevButton = (ImageButton) findViewById(R.id.prev); + mPrevButton.setOnClickListener(mOnClickListener); + + mNextButton = (ImageButton) findViewById(R.id.next); + mNextButton.setOnClickListener(mOnClickListener); + + mViewPager = (ViewPager) findViewById(R.id.day_picker_view_pager); + mViewPager.setAdapter(mAdapter); + mViewPager.setOnPageChangeListener(mOnPageChangedListener); + + // Proxy the month text color into the previous and next buttons. + if (monthTextAppearanceResId != 0) { + final TypedArray ta = mContext.obtainStyledAttributes(null, + ATTRS_TEXT_COLOR, 0, monthTextAppearanceResId); + final ColorStateList monthColor = ta.getColorStateList(0); + if (monthColor != null) { + mPrevButton.setImageTintList(monthColor); + mNextButton.setImageTintList(monthColor); + } + ta.recycle(); + } // Set up min and max dates. final Calendar tempDate = Calendar.getInstance(); @@ -127,109 +168,68 @@ class DayPickerView extends ViewPager { setDate(setDateMillis, false); // Proxy selection callbacks to our own listener. - mAdapter.setOnDaySelectedListener(new DayPickerAdapter.OnDaySelectedListener() { + mAdapter.setOnDaySelectedListener(new DayPickerPagerAdapter.OnDaySelectedListener() { @Override - public void onDaySelected(DayPickerAdapter adapter, Calendar day) { + public void onDaySelected(DayPickerPagerAdapter adapter, Calendar day) { if (mOnDaySelectedListener != null) { mOnDaySelectedListener.onDaySelected(DayPickerView.this, day); } } - - @Override - public void onNavigationClick(DayPickerAdapter view, int direction, boolean animate) { - // ViewPager clamps input values, so we don't need to worry - // about passing invalid indices. - final int nextItem = getCurrentItem() + direction; - setCurrentItem(nextItem, animate); - } }); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - populate(); - - // Everything below is mostly copied from FrameLayout. - int count = getChildCount(); - - final boolean measureMatchParentChildren = - MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || - MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY; - - int maxHeight = 0; - int maxWidth = 0; - int childState = 0; - - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() != GONE) { - measureChild(child, widthMeasureSpec, heightMeasureSpec); - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - maxWidth = Math.max(maxWidth, child.getMeasuredWidth()); - maxHeight = Math.max(maxHeight, child.getMeasuredHeight()); - childState = combineMeasuredStates(childState, child.getMeasuredState()); - if (measureMatchParentChildren) { - if (lp.width == LayoutParams.MATCH_PARENT || - lp.height == LayoutParams.MATCH_PARENT) { - mMatchParentChildren.add(child); - } - } - } - } - - // Account for padding too - maxWidth += getPaddingLeft() + getPaddingRight(); - maxHeight += getPaddingTop() + getPaddingBottom(); - - // Check against our minimum height and width - maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); - maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); - - // Check against our foreground's minimum height and width - final Drawable drawable = getForeground(); - if (drawable != null) { - maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); - maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); - } - - setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), - resolveSizeAndState(maxHeight, heightMeasureSpec, - childState << MEASURED_HEIGHT_STATE_SHIFT)); - - count = mMatchParentChildren.size(); - if (count > 1) { - for (int i = 0; i < count; i++) { - final View child = mMatchParentChildren.get(i); - - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - final int childWidthMeasureSpec; - final int childHeightMeasureSpec; - - if (lp.width == LayoutParams.MATCH_PARENT) { - childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( - getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), - MeasureSpec.EXACTLY); - } else { - childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, - getPaddingLeft() + getPaddingRight(), - lp.width); - } - - if (lp.height == LayoutParams.MATCH_PARENT) { - childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( - getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), - MeasureSpec.EXACTLY); - } else { - childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, - getPaddingTop() + getPaddingBottom(), - lp.height); - } + final ViewPager viewPager = mViewPager; + measureChild(viewPager, widthMeasureSpec, heightMeasureSpec); + + final int measuredWidthAndState = viewPager.getMeasuredWidthAndState(); + final int measuredHeightAndState = viewPager.getMeasuredHeightAndState(); + setMeasuredDimension(measuredWidthAndState, measuredHeightAndState); + + final int pagerWidth = viewPager.getMeasuredWidth(); + final int pagerHeight = viewPager.getMeasuredHeight(); + final int buttonWidthSpec = MeasureSpec.makeMeasureSpec(pagerWidth, MeasureSpec.AT_MOST); + final int buttonHeightSpec = MeasureSpec.makeMeasureSpec(pagerHeight, MeasureSpec.AT_MOST); + mPrevButton.measure(buttonWidthSpec, buttonHeightSpec); + mNextButton.measure(buttonWidthSpec, buttonHeightSpec); + } - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); - } + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + final ImageButton leftButton = mPrevButton; + final ImageButton rightButton = mNextButton; + + final int width = right - left; + final int height = bottom - top; + mViewPager.layout(0, 0, width, height); + + if (mViewPager.getChildCount() < 1) { + leftButton.setVisibility(View.INVISIBLE); + rightButton.setVisibility(View.INVISIBLE); + return; } - mMatchParentChildren.clear(); + final SimpleMonthView monthView = (SimpleMonthView) mViewPager.getChildAt(0); + final int monthHeight = monthView.getMonthHeight(); + final int cellWidth = monthView.getCellWidth(); + + // Vertically center the previous/next buttons within the month + // header, horizontally center within the day cell. + final int leftDW = leftButton.getMeasuredWidth(); + final int leftDH = leftButton.getMeasuredHeight(); + final int leftIconTop = monthView.getPaddingTop() + (monthHeight - leftDH) / 2; + final int leftIconLeft = monthView.getPaddingLeft() + (cellWidth - leftDW) / 2; + leftButton.layout(leftIconLeft, leftIconTop, leftIconLeft + leftDW, leftIconTop + leftDH); + leftButton.setVisibility(View.VISIBLE); + + final int rightDW = rightButton.getMeasuredWidth(); + final int rightDH = rightButton.getMeasuredHeight(); + final int rightIconTop = monthView.getPaddingTop() + (monthHeight - rightDH) / 2; + final int rightIconRight = width - monthView.getPaddingRight() - (cellWidth - rightDW) / 2; + rightButton.layout(rightIconRight - rightDW, rightIconTop, + rightIconRight, rightIconTop + rightDH); + rightButton.setVisibility(View.VISIBLE); } public void setDayOfWeekTextAppearance(int resId) { @@ -284,8 +284,8 @@ class DayPickerView extends ViewPager { } final int position = getPositionFromDay(timeInMillis); - if (position != getCurrentItem()) { - setCurrentItem(position, animate); + if (position != mViewPager.getCurrentItem()) { + mViewPager.setCurrentItem(position, animate); } mTempCalendar.setTimeInMillis(timeInMillis); @@ -365,10 +365,57 @@ class DayPickerView extends ViewPager { * Gets the position of the view that is most prominently displayed within the list view. */ public int getMostVisiblePosition() { - return getCurrentItem(); + return mViewPager.getCurrentItem(); } + public void setPosition(int position) { + mViewPager.setCurrentItem(position, false); + } + + private final OnPageChangeListener mOnPageChangedListener = new OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + final float alpha = Math.abs(0.5f - positionOffset) * 2.0f; + mPrevButton.setAlpha(alpha); + mNextButton.setAlpha(alpha); + } + + @Override + public void onPageScrollStateChanged(int state) {} + + @Override + public void onPageSelected(int position) { + mPrevButton.setVisibility( + position > 0 ? View.VISIBLE : View.INVISIBLE); + mNextButton.setVisibility( + position < (mAdapter.getCount() - 1) ? View.VISIBLE : View.INVISIBLE); + } + }; + + private final OnClickListener mOnClickListener = new OnClickListener() { + @Override + public void onClick(View v) { + final int direction; + if (v == mPrevButton) { + direction = -1; + } else if (v == mNextButton) { + direction = 1; + } else { + return; + } + + // Animation is expensive for accessibility services since it sends + // lots of scroll and content change events. + final boolean animate = !mAccessibilityManager.isEnabled(); + + // ViewPager clamps input values, so we don't need to worry + // about passing invalid indices. + final int nextItem = mViewPager.getCurrentItem() + direction; + mViewPager.setCurrentItem(nextItem, animate); + } + }; + public interface OnDaySelectedListener { - public void onDaySelected(DayPickerView view, Calendar day); + void onDaySelected(DayPickerView view, Calendar day); } } diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java new file mode 100644 index 000000000000..bb6e3a42ae43 --- /dev/null +++ b/core/java/android/widget/DayPickerViewPager.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.widget; + +import com.android.internal.widget.ViewPager; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; + +import java.util.ArrayList; + +/** + * This displays a list of months in a calendar format with selectable days. + */ +class DayPickerViewPager extends ViewPager { + private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1); + + public DayPickerViewPager(Context context) { + this(context, null); + } + + public DayPickerViewPager(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + populate(); + + // Everything below is mostly copied from FrameLayout. + int count = getChildCount(); + + final boolean measureMatchParentChildren = + MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || + MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY; + + int maxHeight = 0; + int maxWidth = 0; + int childState = 0; + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + measureChild(child, widthMeasureSpec, heightMeasureSpec); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + maxWidth = Math.max(maxWidth, child.getMeasuredWidth()); + maxHeight = Math.max(maxHeight, child.getMeasuredHeight()); + childState = combineMeasuredStates(childState, child.getMeasuredState()); + if (measureMatchParentChildren) { + if (lp.width == LayoutParams.MATCH_PARENT || + lp.height == LayoutParams.MATCH_PARENT) { + mMatchParentChildren.add(child); + } + } + } + } + + // Account for padding too + maxWidth += getPaddingLeft() + getPaddingRight(); + maxHeight += getPaddingTop() + getPaddingBottom(); + + // Check against our minimum height and width + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + + // Check against our foreground's minimum height and width + final Drawable drawable = getForeground(); + if (drawable != null) { + maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); + maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); + } + + setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), + resolveSizeAndState(maxHeight, heightMeasureSpec, + childState << MEASURED_HEIGHT_STATE_SHIFT)); + + count = mMatchParentChildren.size(); + if (count > 1) { + for (int i = 0; i < count; i++) { + final View child = mMatchParentChildren.get(i); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final int childWidthMeasureSpec; + final int childHeightMeasureSpec; + + if (lp.width == LayoutParams.MATCH_PARENT) { + childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), + MeasureSpec.EXACTLY); + } else { + childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, + getPaddingLeft() + getPaddingRight(), + lp.width); + } + + if (lp.height == LayoutParams.MATCH_PARENT) { + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), + MeasureSpec.EXACTLY); + } else { + childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, + getPaddingTop() + getPaddingBottom(), + lp.height); + } + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + } + + mMatchParentChildren.clear(); + } +} diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java index aa7f0b689065..0249c222d969 100644 --- a/core/java/android/widget/SimpleMonthView.java +++ b/core/java/android/widget/SimpleMonthView.java @@ -26,7 +26,6 @@ import android.graphics.Paint.Align; import android.graphics.Paint.Style; import android.graphics.Rect; import android.graphics.Typeface; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.TextPaint; import android.text.format.DateFormat; @@ -60,12 +59,6 @@ class SimpleMonthView extends View { private static final String DEFAULT_TITLE_FORMAT = "MMMMy"; private static final String DAY_OF_WEEK_FORMAT = "EEEEE"; - /** Virtual view ID for previous button. */ - private static final int ITEM_ID_PREV = 0x101; - - /** Virtual view ID for next button. */ - private static final int ITEM_ID_NEXT = 0x100; - private final TextPaint mMonthPaint = new TextPaint(); private final TextPaint mDayOfWeekPaint = new TextPaint(); private final TextPaint mDayPaint = new TextPaint(); @@ -87,14 +80,6 @@ class SimpleMonthView extends View { private final int mDesiredCellWidth; private final int mDesiredDaySelectorRadius; - // Next/previous drawables. - private final Drawable mPrevDrawable; - private final Drawable mNextDrawable; - private final Rect mPrevHitArea; - private final Rect mNextHitArea; - private final CharSequence mPrevContentDesc; - private final CharSequence mNextContentDesc; - private CharSequence mTitle; private int mMonth; @@ -137,9 +122,6 @@ class SimpleMonthView extends View { /** The day of month for the last (inclusive) enabled day. */ private int mEnabledDayEnd = 31; - /** The number of week rows needed to display the current month. */ - private int mNumWeeks = MAX_WEEKS_IN_MONTH; - /** Optional listener for handling day click actions. */ private OnDayClickListener mOnDayClickListener; @@ -147,9 +129,6 @@ class SimpleMonthView extends View { private int mTouchedItem = -1; - private boolean mPrevEnabled; - private boolean mNextEnabled; - public SimpleMonthView(Context context) { this(context, null); } @@ -170,14 +149,8 @@ class SimpleMonthView extends View { mDesiredDayOfWeekHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_of_week_height); mDesiredDayHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_height); mDesiredCellWidth = res.getDimensionPixelSize(R.dimen.date_picker_day_width); - mDesiredDaySelectorRadius = res.getDimensionPixelSize(R.dimen.date_picker_day_selector_radius); - - mPrevDrawable = context.getDrawable(R.drawable.ic_chevron_left); - mNextDrawable = context.getDrawable(R.drawable.ic_chevron_right); - mPrevHitArea = mPrevDrawable != null ? new Rect() : null; - mNextHitArea = mNextDrawable != null ? new Rect() : null; - mPrevContentDesc = res.getText(R.string.date_picker_prev_month_button); - mNextContentDesc = res.getText(R.string.date_picker_next_month_button); + mDesiredDaySelectorRadius = res.getDimensionPixelSize( + R.dimen.date_picker_day_selector_radius); // Set up accessibility components. mTouchHelper = new MonthViewTouchHelper(this); @@ -193,18 +166,6 @@ class SimpleMonthView extends View { initPaints(res); } - public void setNextEnabled(boolean enabled) { - mNextEnabled = enabled; - mTouchHelper.invalidateRoot(); - invalidate(); - } - - public void setPrevEnabled(boolean enabled) { - mPrevEnabled = enabled; - mTouchHelper.invalidateRoot(); - invalidate(); - } - /** * Applies the specified text appearance resource to a paint, returning the * text color if one is set in the text appearance. @@ -236,16 +197,16 @@ class SimpleMonthView extends View { return textColor; } + public int getMonthHeight() { + return mMonthHeight; + } + + public int getCellWidth() { + return mCellWidth; + } + public void setMonthTextAppearance(int resId) { - final ColorStateList monthColor = applyTextAppearance(mMonthPaint, resId); - if (monthColor != null) { - if (mPrevDrawable != null) { - mPrevDrawable.setTintList(monthColor); - } - if (mNextDrawable != null) { - mNextDrawable.setTintList(monthColor); - } - } + applyTextAppearance(mMonthPaint, resId); invalidate(); } @@ -360,7 +321,7 @@ class SimpleMonthView extends View { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: - final int touchedItem = getItemAtLocation(x, y); + final int touchedItem = getDayAtLocation(x, y); if (mTouchedItem != touchedItem) { mTouchedItem = touchedItem; invalidate(); @@ -368,8 +329,8 @@ class SimpleMonthView extends View { break; case MotionEvent.ACTION_UP: - final int clickedItem = getItemAtLocation(x, y); - onItemClicked(clickedItem, true); + final int clickedDay = getDayAtLocation(x, y); + onDayClicked(clickedDay); // Fall through. case MotionEvent.ACTION_CANCEL: // Reset touched day on stream end. @@ -389,7 +350,6 @@ class SimpleMonthView extends View { drawMonth(canvas); drawDaysOfWeek(canvas); drawDays(canvas); - drawButtons(canvas); canvas.translate(-paddingLeft, -paddingTop); } @@ -482,16 +442,6 @@ class SimpleMonthView extends View { } } - private void drawButtons(Canvas canvas) { - if (mPrevEnabled && mPrevDrawable != null) { - mPrevDrawable.draw(canvas); - } - - if (mNextEnabled && mNextDrawable != null) { - mNextDrawable.draw(canvas); - } - } - private static boolean isValidDayOfWeek(int day) { return day >= Calendar.SUNDAY && day <= Calendar.SATURDAY; } @@ -674,33 +624,6 @@ class SimpleMonthView extends View { mDaySelectorRadius = Math.min(mDesiredDaySelectorRadius, Math.min(maxSelectorWidth, maxSelectorHeight)); - // Vertically center the previous/next drawables within the month - // header, horizontally center within the day cell, then expand the - // hit area to ensure it's at least 48x48dp. - final Drawable prevDrawable = mPrevDrawable; - if (prevDrawable != null) { - final int dW = prevDrawable.getIntrinsicWidth(); - final int dH = prevDrawable.getIntrinsicHeight(); - final int iconTop = (monthHeight - dH) / 2; - final int iconLeft = (cellWidth - dW) / 2; - - // Button bounds don't include padding, but hit area does. - prevDrawable.setBounds(iconLeft, iconTop, iconLeft + dW, iconTop + dH); - mPrevHitArea.set(0, 0, paddingLeft + cellWidth, paddingTop + monthHeight); - } - - final Drawable nextDrawable = mNextDrawable; - if (nextDrawable != null) { - final int dW = nextDrawable.getIntrinsicWidth(); - final int dH = nextDrawable.getIntrinsicHeight(); - final int iconTop = (monthHeight - dH) / 2; - final int iconRight = paddedWidth - (cellWidth - dW) / 2; - - // Button bounds don't include padding, but hit area does. - nextDrawable.setBounds(iconRight - dW, iconTop, iconRight, iconTop + dH); - mNextHitArea.set(paddedRight - cellWidth, 0, w, paddingTop + monthHeight); - } - // Invalidate cached accessibility information. mTouchHelper.invalidateRoot(); } @@ -714,22 +637,15 @@ class SimpleMonthView extends View { } /** - * Calculates the day of the month or item identifier at the specified - * touch position. Returns the day of the month or -1 if the position - * wasn't in a valid day. + * Calculates the day of the month at the specified touch position. Returns + * the day of the month or -1 if the position wasn't in a valid day. * * @param x the x position of the touch event * @param y the y position of the touch event - * @return the day of the month at (x, y), an item identifier, or -1 if the - * position wasn't in a valid day or item + * @return the day of the month at (x, y), or -1 if the position wasn't in + * a valid day */ - private int getItemAtLocation(int x, int y) { - if (mNextEnabled && mNextDrawable != null && mNextHitArea.contains(x, y)) { - return ITEM_ID_NEXT; - } else if (mPrevEnabled && mPrevDrawable != null && mPrevHitArea.contains(x, y)) { - return ITEM_ID_PREV; - } - + private int getDayAtLocation(int x, int y) { final int paddedX = x - getPaddingLeft(); if (paddedX < 0 || paddedX >= mPaddedWidth) { return -1; @@ -755,22 +671,10 @@ class SimpleMonthView extends View { /** * Calculates the bounds of the specified day. * - * @param id the day of the month, or an item identifier + * @param id the day of the month * @param outBounds the rect to populate with bounds */ - private boolean getBoundsForItem(int id, Rect outBounds) { - if (mNextEnabled && id == ITEM_ID_NEXT) { - if (mNextDrawable != null) { - outBounds.set(mNextHitArea); - return true; - } - } else if (mPrevEnabled && id == ITEM_ID_PREV) { - if (mPrevDrawable != null) { - outBounds.set(mPrevHitArea); - return true; - } - } - + private boolean getBoundsForDay(int id, Rect outBounds) { if (id < 1 || id > mDaysInMonth) { return false; } @@ -789,16 +693,8 @@ class SimpleMonthView extends View { final int top = getPaddingTop() + headerHeight + row * rowHeight; outBounds.set(left, top, left + colWidth, top + rowHeight); - return true; - } - /** - * Called when an item is clicked. - * - * @param id the day number or item identifier - */ - private boolean onItemClicked(int id, boolean animate) { - return onNavigationClicked(id, animate) || onDayClicked(id); + return true; } /** @@ -824,31 +720,6 @@ class SimpleMonthView extends View { } /** - * Called when the user clicks on a navigation button. Handles callbacks to - * the {@link OnDayClickListener} if one is set. - * - * @param id the item identifier - */ - private boolean onNavigationClicked(int id, boolean animate) { - final int direction; - if (id == ITEM_ID_NEXT) { - direction = 1; - } else if (id == ITEM_ID_PREV) { - direction = -1; - } else { - return false; - } - - if (mOnDayClickListener != null) { - mOnDayClickListener.onNavigationClick(this, direction, animate); - } - - // This is a no-op if accessibility is turned off. - mTouchHelper.sendEventForVirtualView(id, AccessibilityEvent.TYPE_VIEW_CLICKED); - return true; - } - - /** * Provides a virtual view hierarchy for interfacing with an accessibility * service. */ @@ -864,7 +735,7 @@ class SimpleMonthView extends View { @Override protected int getVirtualViewAt(float x, float y) { - final int day = getItemAtLocation((int) (x + 0.5f), (int) (y + 0.5f)); + final int day = getDayAtLocation((int) (x + 0.5f), (int) (y + 0.5f)); if (day >= 0) { return day; } @@ -873,14 +744,6 @@ class SimpleMonthView extends View { @Override protected void getVisibleVirtualViews(IntArray virtualViewIds) { - if (mNextEnabled && mNextDrawable != null) { - virtualViewIds.add(ITEM_ID_PREV); - } - - if (mPrevEnabled && mPrevDrawable != null) { - virtualViewIds.add(ITEM_ID_NEXT); - } - for (int day = 1; day <= mDaysInMonth; day++) { virtualViewIds.add(day); } @@ -888,12 +751,12 @@ class SimpleMonthView extends View { @Override protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) { - event.setContentDescription(getItemDescription(virtualViewId)); + event.setContentDescription(getDayDescription(virtualViewId)); } @Override protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfo node) { - final boolean hasBounds = getBoundsForItem(virtualViewId, mTempRect); + final boolean hasBounds = getBoundsForDay(virtualViewId, mTempRect); if (!hasBounds) { // The day is invalid, kill the node. @@ -904,8 +767,8 @@ class SimpleMonthView extends View { return; } - node.setText(getItemText(virtualViewId)); - node.setContentDescription(getItemDescription(virtualViewId)); + node.setText(getDayText(virtualViewId)); + node.setContentDescription(getDayDescription(virtualViewId)); node.setBoundsInParent(mTempRect); node.addAction(AccessibilityAction.ACTION_CLICK); @@ -921,7 +784,7 @@ class SimpleMonthView extends View { Bundle arguments) { switch (action) { case AccessibilityNodeInfo.ACTION_CLICK: - return onItemClicked(virtualViewId, false); + return onDayClicked(virtualViewId); } return false; @@ -930,15 +793,11 @@ class SimpleMonthView extends View { /** * Generates a description for a given virtual view. * - * @param id the day or item identifier to generate a description for + * @param id the day to generate a description for * @return a description of the virtual view */ - private CharSequence getItemDescription(int id) { - if (id == ITEM_ID_NEXT) { - return mNextContentDesc; - } else if (id == ITEM_ID_PREV) { - return mPrevContentDesc; - } else if (id >= 1 && id <= mDaysInMonth) { + private CharSequence getDayDescription(int id) { + if (id >= 1 && id <= mDaysInMonth) { mTempCalendar.set(mYear, mMonth, id); return DateFormat.format(DATE_FORMAT, mTempCalendar.getTimeInMillis()); } @@ -949,13 +808,11 @@ class SimpleMonthView extends View { /** * Generates displayed text for a given virtual view. * - * @param id the day or item identifier to generate text for + * @param id the day to generate text for * @return the visible text of the virtual view */ - private CharSequence getItemText(int id) { - if (id == ITEM_ID_NEXT || id == ITEM_ID_PREV) { - return null; - } else if (id >= 1 && id <= mDaysInMonth) { + private CharSequence getDayText(int id) { + if (id >= 1 && id <= mDaysInMonth) { return Integer.toString(id); } @@ -967,7 +824,6 @@ class SimpleMonthView extends View { * Handles callbacks when the user clicks on a time object. */ public interface OnDayClickListener { - public void onDayClick(SimpleMonthView view, Calendar day); - public void onNavigationClick(SimpleMonthView view, int direction, boolean animate); + void onDayClick(SimpleMonthView view, Calendar day); } } diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 5c95f8a9a9ae..7a934bde7834 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -857,13 +857,6 @@ static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapHandle) { bitmap->unlockPixels(); } -static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) { - SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); - SkPixelRef* pixelRef = bitmap ? bitmap->pixelRef() : nullptr; - SkSafeRef(pixelRef); - return reinterpret_cast<jlong>(pixelRef); -} - /////////////////////////////////////////////////////////////////////////////// static JNINativeMethod gBitmapMethods[] = { @@ -903,7 +896,6 @@ static JNINativeMethod gBitmapMethods[] = { (void*)Bitmap_copyPixelsFromBuffer }, { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs }, { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw }, - { "nativeRefPixelRef", "(J)J", (void*)Bitmap_refPixelRef }, }; int register_android_graphics_Bitmap(JNIEnv* env) diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index f0bd8d1e85b9..f0bd5ddf29a0 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -373,7 +373,7 @@ SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) return legacyBitmapConfigToColorType(c); } -android::Canvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) { +SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) { SkASSERT(env); SkASSERT(canvas); SkASSERT(env->IsInstanceOf(canvas, gCanvas_class)); @@ -381,7 +381,9 @@ android::Canvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) { if (!canvasHandle) { return NULL; } - return reinterpret_cast<android::Canvas*>(canvasHandle); + SkCanvas* c = reinterpret_cast<android::Canvas*>(canvasHandle)->asSkCanvas(); + SkASSERT(c); + return c; } SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region) diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index 8eb43f8a5989..49def13e48f0 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -8,7 +8,6 @@ #include "SkPoint.h" #include "SkRect.h" #include "SkImageDecoder.h" -#include <Canvas.h> #include <jni.h> class SkBitmapRegionDecoder; @@ -48,7 +47,7 @@ public: static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point); static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf); - static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas); + static SkCanvas* getNativeCanvas(JNIEnv*, jobject canvas); static SkBitmap* getSkBitmapDeprecated(JNIEnv*, jobject bitmap); static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap); static SkPixelRef* getSkPixelRef(JNIEnv*, jobject bitmap); diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp index 348b0ec083b7..3f8bfe291013 100644 --- a/core/jni/android/graphics/NinePatch.cpp +++ b/core/jni/android/graphics/NinePatch.cpp @@ -64,7 +64,7 @@ public: return JNI_FALSE; } - static jlong validateNinePatchChunk(JNIEnv* env, jobject, jbyteArray obj) { + static jlong validateNinePatchChunk(JNIEnv* env, jobject, jlong, jbyteArray obj) { size_t chunkSize = env->GetArrayLength(obj); if (chunkSize < (int) (sizeof(Res_png_9patch))) { jniThrowRuntimeException(env, "Array too small for chunk."); @@ -88,13 +88,13 @@ public: } } - static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds, const SkBitmap& bitmap, + static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds, const SkBitmap* bitmap, Res_png_9patch* chunk, const SkPaint* paint, jint destDensity, jint srcDensity) { if (destDensity == srcDensity || destDensity == 0 || srcDensity == 0) { ALOGV("Drawing unscaled 9-patch: (%g,%g)-(%g,%g)", SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop), SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom)); - NinePatch_Draw(canvas, bounds, bitmap, *chunk, paint, NULL); + NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL); } else { canvas->save(); @@ -111,25 +111,25 @@ public: SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom), srcDensity, destDensity); - NinePatch_Draw(canvas, bounds, bitmap, *chunk, paint, NULL); + NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL); canvas->restore(); } } static void drawF(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRectF, - jobject jbitmap, jlong chunkHandle, jlong paintHandle, + jlong bitmapHandle, jlong chunkHandle, jlong paintHandle, jint destDensity, jint srcDensity) { SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas(); + const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); SkASSERT(canvas); SkASSERT(boundsRectF); + SkASSERT(bitmap); SkASSERT(chunk); // paint is optional - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); SkRect bounds; GraphicsJNI::jrectf_to_rect(env, boundsRectF, &bounds); @@ -137,36 +137,36 @@ public: } static void drawI(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRect, - jobject jbitmap, jlong chunkHandle, jlong paintHandle, + jlong bitmapHandle, jlong chunkHandle, jlong paintHandle, jint destDensity, jint srcDensity) { SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas(); + const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); SkASSERT(canvas); SkASSERT(boundsRect); + SkASSERT(bitmap); SkASSERT(chunk); // paint is optional - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); SkRect bounds; GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds); draw(env, canvas, bounds, bitmap, chunk, paint, destDensity, srcDensity); } - static jlong getTransparentRegion(JNIEnv* env, jobject, jobject jbitmap, + static jlong getTransparentRegion(JNIEnv* env, jobject, jlong bitmapHandle, jlong chunkHandle, jobject boundsRect) { + const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle); + SkASSERT(bitmap); SkASSERT(chunk); SkASSERT(boundsRect); - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); SkRect bounds; GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds); SkRegion* region = NULL; - NinePatch_Draw(NULL, bounds, bitmap, *chunk, NULL, ®ion); + NinePatch_Draw(NULL, bounds, *bitmap, *chunk, NULL, ®ion); return reinterpret_cast<jlong>(region); } @@ -176,16 +176,13 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// static JNINativeMethod gNinePatchMethods[] = { - { "isNinePatchChunk", "([B)Z", (void*) SkNinePatchGlue::isNinePatchChunk }, - { "validateNinePatchChunk", "([B)J", - (void*) SkNinePatchGlue::validateNinePatchChunk }, - { "nativeFinalize", "(J)V", (void*) SkNinePatchGlue::finalize }, - { "nativeDraw", "(JLandroid/graphics/RectF;Landroid/graphics/Bitmap;JJII)V", - (void*) SkNinePatchGlue::drawF }, - { "nativeDraw", "(JLandroid/graphics/Rect;Landroid/graphics/Bitmap;JJII)V", - (void*) SkNinePatchGlue::drawI }, - { "nativeGetTransparentRegion", "(Landroid/graphics/Bitmap;JLandroid/graphics/Rect;)J", - (void*) SkNinePatchGlue::getTransparentRegion } + { "isNinePatchChunk", "([B)Z", (void*) SkNinePatchGlue::isNinePatchChunk }, + { "validateNinePatchChunk", "(J[B)J", (void*) SkNinePatchGlue::validateNinePatchChunk }, + { "nativeFinalize", "(J)V", (void*) SkNinePatchGlue::finalize }, + { "nativeDraw", "(JLandroid/graphics/RectF;JJJII)V", (void*) SkNinePatchGlue::drawF }, + { "nativeDraw", "(JLandroid/graphics/Rect;JJJII)V", (void*) SkNinePatchGlue::drawI }, + { "nativeGetTransparentRegion", "(JJLandroid/graphics/Rect;)J", + (void*) SkNinePatchGlue::getTransparentRegion } }; int register_android_graphics_NinePatch(JNIEnv* env) { diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index d0f75917106a..6591d293cd34 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -80,12 +80,11 @@ static jlong Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, j /////////////////////////////////////////////////////////////////////////////////////////////// -static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jobject jbitmap, +static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong bitmapHandle, jint tileModeX, jint tileModeY) { - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); - SkShader* s = SkShader::CreateBitmapShader(bitmap, + const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); + SkShader* s = SkShader::CreateBitmapShader(*bitmap, (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY); @@ -250,7 +249,7 @@ static JNINativeMethod gShaderMethods[] = { }; static JNINativeMethod gBitmapShaderMethods[] = { - { "nativeCreate", "(Landroid/graphics/Bitmap;II)J", (void*)BitmapShader_constructor }, + { "nativeCreate", "(JII)J", (void*)BitmapShader_constructor }, }; static JNINativeMethod gLinearGradientMethods[] = { diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp index 9b5fb3a60119..a2c16097b2bf 100644 --- a/core/jni/android_graphics_Canvas.cpp +++ b/core/jni/android_graphics_Canvas.cpp @@ -39,22 +39,17 @@ static void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) { } // Native wrapper constructor used by Canvas(Bitmap) -static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) { - SkBitmap bitmap; - if (jbitmap != NULL) { - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); - } +static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) { + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap)); } // Set the given bitmap as the new draw target (wrapped in a new SkCanvas), // optionally copying canvas matrix & clip state. -static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) { - SkBitmap bitmap; - if (jbitmap != NULL) { - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); - } - get_canvas(canvasHandle)->setBitmap(bitmap); +static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle, + jboolean copyState) { + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); + get_canvas(canvasHandle)->setBitmap(bitmap, copyState); } static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) { @@ -318,12 +313,11 @@ static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle, indices, indexCount, *paint); } -static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap, +static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jlong bitmapHandle, jfloat left, jfloat top, jlong paintHandle, jint canvasDensity, jint screenDensity, jint bitmapDensity) { Canvas* canvas = get_canvas(canvasHandle); - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) { @@ -333,9 +327,9 @@ static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject filteredPaint = *paint; } filteredPaint.setFilterQuality(kLow_SkFilterQuality); - canvas->drawBitmap(bitmap, left, top, &filteredPaint); + canvas->drawBitmap(*bitmap, left, top, &filteredPaint); } else { - canvas->drawBitmap(bitmap, left, top, paint); + canvas->drawBitmap(*bitmap, left, top, paint); } } else { canvas->save(SkCanvas::kMatrixClip_SaveFlag); @@ -349,39 +343,37 @@ static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject } filteredPaint.setFilterQuality(kLow_SkFilterQuality); - canvas->drawBitmap(bitmap, 0, 0, &filteredPaint); + canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint); canvas->restore(); } } -static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, +static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle, jlong matrixHandle, jlong paintHandle) { + const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); - get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint); + get_canvas(canvasHandle)->drawBitmap(*bitmap, *matrix, paint); } -static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, +static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, jlong paintHandle, jint screenDensity, jint bitmapDensity) { Canvas* canvas = get_canvas(canvasHandle); + const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); if (screenDensity != 0 && screenDensity != bitmapDensity) { Paint filteredPaint; if (paint) { filteredPaint = *paint; } filteredPaint.setFilterQuality(kLow_SkFilterQuality); - canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, + canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom, dstLeft, dstTop, dstRight, dstBottom, &filteredPaint); } else { - canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, + canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom, dstLeft, dstTop, dstRight, dstBottom, paint); } } @@ -409,17 +401,16 @@ static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle, get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint); } -static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, +static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle, jint meshWidth, jint meshHeight, jfloatArray jverts, jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) { const int ptCount = (meshWidth + 1) * (meshHeight + 1); AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1)); AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount); + const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); - get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight, + get_canvas(canvasHandle)->drawBitmapMesh(*bitmap, meshWidth, meshHeight, vertA.ptr(), colorA.ptr(), paint); } @@ -667,8 +658,8 @@ static void freeTextLayoutCaches(JNIEnv* env, jobject) { static JNINativeMethod gMethods[] = { {"finalizer", "(J)V", (void*) CanvasJNI::finalizer}, - {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster}, - {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap}, + {"initRaster", "(J)J", (void*) CanvasJNI::initRaster}, + {"native_setBitmap", "(JJZ)V", (void*) CanvasJNI::setBitmap}, {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque}, {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth}, {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight}, @@ -704,11 +695,11 @@ static JNINativeMethod gMethods[] = { {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc}, {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath}, {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices}, - {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap}, - {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix}, - {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, + {"native_drawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap}, + {"nativeDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix}, + {"native_drawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray}, - {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh}, + {"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh}, {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars}, {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString}, {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars}, diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp index 7d122303e1fa..16e5b3cf27df 100644 --- a/core/jni/android_hardware_SensorManager.cpp +++ b/core/jni/android_hardware_SensorManager.cpp @@ -19,6 +19,7 @@ #include <map> #include <ScopedUtfChars.h> +#include <ScopedLocalRef.h> #include <utils/Log.h> #include <utils/Looper.h> @@ -178,21 +179,21 @@ nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next) class Receiver : public LooperCallback { sp<SensorEventQueue> mSensorQueue; sp<MessageQueue> mMessageQueue; - jobject mReceiverObject; + jobject mReceiverWeakGlobal; jfloatArray mScratch; public: Receiver(const sp<SensorEventQueue>& sensorQueue, const sp<MessageQueue>& messageQueue, - jobject receiverObject, jfloatArray scratch) { + jobject receiverWeak, jfloatArray scratch) { JNIEnv* env = AndroidRuntime::getJNIEnv(); mSensorQueue = sensorQueue; mMessageQueue = messageQueue; - mReceiverObject = env->NewGlobalRef(receiverObject); + mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak); mScratch = (jfloatArray)env->NewGlobalRef(scratch); } ~Receiver() { JNIEnv* env = AndroidRuntime::getJNIEnv(); - env->DeleteGlobalRef(mReceiverObject); + env->DeleteGlobalRef(mReceiverWeakGlobal); env->DeleteGlobalRef(mScratch); } sp<SensorEventQueue> getSensorEventQueue() const { @@ -213,6 +214,8 @@ private: virtual int handleEvent(int fd, int events, void* data) { JNIEnv* env = AndroidRuntime::getJNIEnv(); sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data); + ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); + ssize_t n; ASensorEvent buffer[16]; while ((n = q->read(buffer, 16)) > 0) { @@ -228,9 +231,11 @@ private: if (buffer[i].type == SENSOR_TYPE_META_DATA) { // This is a flush complete sensor event. Call dispatchFlushCompleteEvent // method. - env->CallVoidMethod(mReceiverObject, - gBaseEventQueueClassInfo.dispatchFlushCompleteEvent, - buffer[i].meta_data.sensor); + if (receiverObj.get()) { + env->CallVoidMethod(receiverObj.get(), + gBaseEventQueueClassInfo.dispatchFlushCompleteEvent, + buffer[i].meta_data.sensor); + } } else { int8_t status; switch (buffer[i].type) { @@ -247,12 +252,14 @@ private: status = SENSOR_STATUS_ACCURACY_HIGH; break; } - env->CallVoidMethod(mReceiverObject, - gBaseEventQueueClassInfo.dispatchSensorEvent, - buffer[i].sensor, - mScratch, - status, - buffer[i].timestamp); + if (receiverObj.get()) { + env->CallVoidMethod(receiverObj.get(), + gBaseEventQueueClassInfo.dispatchSensorEvent, + buffer[i].sensor, + mScratch, + status, + buffer[i].timestamp); + } } if (env->ExceptionCheck()) { mSensorQueue->sendAck(buffer, n); @@ -269,7 +276,7 @@ private: } }; -static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, +static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQWeak, jobject msgQ, jfloatArray scratch, jstring packageName) { SensorManager& mgr(SensorManager::getInstance()); ScopedUtfChars packageUtf(env, packageName); @@ -282,7 +289,7 @@ static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject event return 0; } - sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQ, scratch); + sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak, scratch); receiver->incStrong((void*)nativeInitSensorEventQueue); return jlong(receiver.get()); } @@ -325,7 +332,7 @@ static JNINativeMethod gSystemSensorManagerMethods[] = { static JNINativeMethod gBaseEventQueueMethods[] = { {"nativeInitBaseEventQueue", - "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[FLjava/lang/String;)J", + "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;[FLjava/lang/String;)J", (void*)nativeInitSensorEventQueue }, {"nativeEnableSensor", diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index c9b0e7688801..33db4a85f289 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -356,95 +356,58 @@ static void android_media_AudioRecord_finalize(JNIEnv *env, jobject thiz) { android_media_AudioRecord_release(env, thiz); } - -// ---------------------------------------------------------------------------- -static jint android_media_AudioRecord_readInByteArray(JNIEnv *env, jobject thiz, - jbyteArray javaAudioData, - jint offsetInBytes, jint sizeInBytes) { - jbyte* recordBuff = NULL; - // get the audio recorder from which we'll read new audio samples - sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); - if (lpRecorder == NULL) { - ALOGE("Unable to retrieve AudioRecord object, can't record"); - return 0; - } - - if (!javaAudioData) { - ALOGE("Invalid Java array to store recorded audio, can't record"); - return 0; - } - - // get the pointer to where we'll record the audio - // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such - // a way that it becomes much more efficient. When doing so, we will have to prevent the - // AudioSystem callback to be called while in critical section (in case of media server - // process crash for instance) - recordBuff = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL); - - if (recordBuff == NULL) { - ALOGE("Error retrieving destination for recorded audio data, can't record"); - return 0; - } - - // read the new audio data from the native AudioRecord object - ssize_t readSize = lpRecorder->read(recordBuff + offsetInBytes, sizeInBytes); - env->ReleaseByteArrayElements(javaAudioData, recordBuff, 0); - - if (readSize < 0) { - readSize = (jint)AUDIO_JAVA_INVALID_OPERATION; - } - return (jint) readSize; +// overloaded JNI array helper functions +static inline +jbyte *envGetArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) { + return env->GetByteArrayElements(array, isCopy); } -// ---------------------------------------------------------------------------- -static jint android_media_AudioRecord_readInShortArray(JNIEnv *env, jobject thiz, - jshortArray javaAudioData, - jint offsetInShorts, jint sizeInShorts) { - - jshort* recordBuff = NULL; - // get the audio recorder from which we'll read new audio samples - sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); - if (lpRecorder == NULL) { - ALOGE("Unable to retrieve AudioRecord object, can't record"); - return 0; - } - - if (!javaAudioData) { - ALOGE("Invalid Java array to store recorded audio, can't record"); - return 0; - } +static inline +void envReleaseArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode) { + env->ReleaseByteArrayElements(array, elems, mode); +} - // get the pointer to where we'll record the audio - // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such - // a way that it becomes much more efficient. When doing so, we will have to prevent the - // AudioSystem callback to be called while in critical section (in case of media server - // process crash for instance) - recordBuff = (jshort *)env->GetShortArrayElements(javaAudioData, NULL); +static inline +jshort *envGetArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy) { + return env->GetShortArrayElements(array, isCopy); +} - if (recordBuff == NULL) { - ALOGE("Error retrieving destination for recorded audio data, can't record"); - return 0; - } +static inline +void envReleaseArrayElements(JNIEnv *env, jshortArray array, jshort *elems, jint mode) { + env->ReleaseShortArrayElements(array, elems, mode); +} - // read the new audio data from the native AudioRecord object - const size_t sizeInBytes = sizeInShorts * sizeof(short); - ssize_t readSize = lpRecorder->read(recordBuff + offsetInShorts, sizeInBytes); +static inline +jfloat *envGetArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy) { + return env->GetFloatArrayElements(array, isCopy); +} - env->ReleaseShortArrayElements(javaAudioData, recordBuff, 0); +static inline +void envReleaseArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, jint mode) { + env->ReleaseFloatArrayElements(array, elems, mode); +} - if (readSize < 0) { - readSize = (jint)AUDIO_JAVA_INVALID_OPERATION; - } else { - readSize /= sizeof(short); +static inline +jint interpretReadSizeError(ssize_t readSize) { + ALOGE_IF(readSize != WOULD_BLOCK, "Error %zd during AudioRecord native read", readSize); + switch (readSize) { + case WOULD_BLOCK: + return (jint)0; + case BAD_VALUE: + return (jint)AUDIO_JAVA_BAD_VALUE; + default: + // may be possible for other errors such as + // NO_INIT to happen if restoreRecord_l fails. + case INVALID_OPERATION: + return (jint)AUDIO_JAVA_INVALID_OPERATION; } - return (jint) readSize; } -// ---------------------------------------------------------------------------- -static jint android_media_AudioRecord_readInFloatArray(JNIEnv *env, jobject thiz, - jfloatArray javaAudioData, - jint offsetInFloats, jint sizeInFloats, - jboolean isReadBlocking) { +template <typename T> +static jint android_media_AudioRecord_readInArray(JNIEnv *env, jobject thiz, + T javaAudioData, + jint offsetInSamples, jint sizeInSamples, + jboolean isReadBlocking) { // get the audio recorder from which we'll read new audio samples sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); if (lpRecorder == NULL) { @@ -453,76 +416,68 @@ static jint android_media_AudioRecord_readInFloatArray(JNIEnv *env, jobject thi } if (javaAudioData == NULL) { - ALOGE("Invalid Java array to store recorded audio"); - return (jint)AUDIO_JAVA_BAD_VALUE; - } + ALOGE("Invalid Java array to store recorded audio"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } - // get the pointer to where we'll record the audio // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such // a way that it becomes much more efficient. When doing so, we will have to prevent the // AudioSystem callback to be called while in critical section (in case of media server // process crash for instance) - jfloat *recordBuff = (jfloat *)env->GetFloatArrayElements(javaAudioData, NULL); + + // get the pointer to where we'll record the audio + auto *recordBuff = envGetArrayElements(env, javaAudioData, NULL); if (recordBuff == NULL) { ALOGE("Error retrieving destination for recorded audio data"); return (jint)AUDIO_JAVA_BAD_VALUE; } // read the new audio data from the native AudioRecord object - const size_t sizeInBytes = sizeInFloats * sizeof(float); - ssize_t readSize = lpRecorder->read(recordBuff + offsetInFloats, sizeInBytes); + const size_t sizeInBytes = sizeInSamples * sizeof(*recordBuff); + ssize_t readSize = lpRecorder->read( + recordBuff + offsetInSamples, sizeInBytes, isReadBlocking == JNI_TRUE /* blocking */); - env->ReleaseFloatArrayElements(javaAudioData, recordBuff, 0); + envReleaseArrayElements(env, javaAudioData, recordBuff, 0); if (readSize < 0) { - ALOGE_IF(readSize != WOULD_BLOCK, "Error %zd during AudioRecord native read", readSize); - switch (readSize) { - case WOULD_BLOCK: - return (jint)0; - case BAD_VALUE: - return (jint)AUDIO_JAVA_BAD_VALUE; - default: - // may be possible for other errors such as - // NO_INIT to happen if restoreRecord_l fails. - case INVALID_OPERATION: - return (jint)AUDIO_JAVA_INVALID_OPERATION; - } + return interpretReadSizeError(readSize); } - return (jint)(readSize / sizeof(float)); + return (jint)(readSize / sizeof(*recordBuff)); } // ---------------------------------------------------------------------------- static jint android_media_AudioRecord_readInDirectBuffer(JNIEnv *env, jobject thiz, - jobject jBuffer, jint sizeInBytes) { + jobject jBuffer, jint sizeInBytes, + jboolean isReadBlocking) { // get the audio recorder from which we'll read new audio samples sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); if (lpRecorder==NULL) - return 0; + return (jint)AUDIO_JAVA_INVALID_OPERATION; // direct buffer and direct access supported? long capacity = env->GetDirectBufferCapacity(jBuffer); if (capacity == -1) { // buffer direct access is not supported ALOGE("Buffer direct access is not supported, can't record"); - return 0; + return (jint)AUDIO_JAVA_BAD_VALUE; } //ALOGV("capacity = %ld", capacity); jbyte* nativeFromJavaBuf = (jbyte*) env->GetDirectBufferAddress(jBuffer); if (nativeFromJavaBuf==NULL) { ALOGE("Buffer direct access is not supported, can't record"); - return 0; + return (jint)AUDIO_JAVA_BAD_VALUE; } // read new data from the recorder ssize_t readSize = lpRecorder->read(nativeFromJavaBuf, - capacity < sizeInBytes ? capacity : sizeInBytes); + capacity < sizeInBytes ? capacity : sizeInBytes, + isReadBlocking == JNI_TRUE /* blocking */); if (readSize < 0) { - readSize = (jint)AUDIO_JAVA_INVALID_OPERATION; + return interpretReadSizeError(readSize); } return (jint)readSize; } - // ---------------------------------------------------------------------------- static jint android_media_AudioRecord_get_native_frame_count(JNIEnv *env, jobject thiz) { sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); @@ -633,12 +588,15 @@ static JNINativeMethod gMethods[] = { {"native_finalize", "()V", (void *)android_media_AudioRecord_finalize}, {"native_release", "()V", (void *)android_media_AudioRecord_release}, {"native_read_in_byte_array", - "([BII)I", (void *)android_media_AudioRecord_readInByteArray}, + "([BIIZ)I", + (void *)android_media_AudioRecord_readInArray<jbyteArray>}, {"native_read_in_short_array", - "([SII)I", (void *)android_media_AudioRecord_readInShortArray}, + "([SIIZ)I", + (void *)android_media_AudioRecord_readInArray<jshortArray>}, {"native_read_in_float_array", - "([FIIZ)I", (void *)android_media_AudioRecord_readInFloatArray}, - {"native_read_in_direct_buffer","(Ljava/lang/Object;I)I", + "([FIIZ)I", + (void *)android_media_AudioRecord_readInArray<jfloatArray>}, + {"native_read_in_direct_buffer","(Ljava/lang/Object;IZ)I", (void *)android_media_AudioRecord_readInDirectBuffer}, {"native_get_native_frame_count", "()I", (void *)android_media_AudioRecord_get_native_frame_count}, diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index 610c7ed83335..8d3a9aab80e5 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -510,14 +510,47 @@ static void android_media_AudioTrack_finalize(JNIEnv *env, jobject thiz) { android_media_AudioTrack_release(env, thiz); } +// overloaded JNI array helper functions (same as in android_media_AudioRecord) +static inline +jbyte *envGetArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) { + return env->GetByteArrayElements(array, isCopy); +} + +static inline +void envReleaseArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode) { + env->ReleaseByteArrayElements(array, elems, mode); +} + +static inline +jshort *envGetArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy) { + return env->GetShortArrayElements(array, isCopy); +} + +static inline +void envReleaseArrayElements(JNIEnv *env, jshortArray array, jshort *elems, jint mode) { + env->ReleaseShortArrayElements(array, elems, mode); +} + +static inline +jfloat *envGetArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy) { + return env->GetFloatArrayElements(array, isCopy); +} + +static inline +void envReleaseArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, jint mode) { + env->ReleaseFloatArrayElements(array, elems, mode); +} + // ---------------------------------------------------------------------------- -jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* data, - jint offsetInBytes, jint sizeInBytes, bool blocking = true) { +template <typename T> +static jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const T *data, + jint offsetInSamples, jint sizeInSamples, bool blocking) { // give the data to the native AudioTrack object (the data starts at the offset) ssize_t written = 0; // regular write() or copy the data to the AudioTrack's shared memory? + size_t sizeInBytes = sizeInSamples * sizeof(T); if (track->sharedBuffer() == 0) { - written = track->write(data + offsetInBytes, sizeInBytes, blocking); + written = track->write(data + offsetInSamples, sizeInBytes, blocking); // for compatibility with earlier behavior of write(), return 0 in this case if (written == (ssize_t) WOULD_BLOCK) { written = 0; @@ -527,55 +560,59 @@ jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* da if ((size_t)sizeInBytes > track->sharedBuffer()->size()) { sizeInBytes = track->sharedBuffer()->size(); } - memcpy(track->sharedBuffer()->pointer(), data + offsetInBytes, sizeInBytes); + memcpy(track->sharedBuffer()->pointer(), data + offsetInSamples, sizeInBytes); written = sizeInBytes; } + if (written > 0) { + return written / sizeof(T); + } + // for compatibility, error codes pass through unchanged return written; } // ---------------------------------------------------------------------------- -static jint android_media_AudioTrack_write_byte(JNIEnv *env, jobject thiz, - jbyteArray javaAudioData, - jint offsetInBytes, jint sizeInBytes, - jint javaAudioFormat, - jboolean isWriteBlocking) { - //ALOGV("android_media_AudioTrack_write_byte(offset=%d, sizeInBytes=%d) called", - // offsetInBytes, sizeInBytes); +template <typename T> +static jint android_media_AudioTrack_writeArray(JNIEnv *env, jobject thiz, + T javaAudioData, + jint offsetInSamples, jint sizeInSamples, + jint javaAudioFormat, + jboolean isWriteBlocking) { + //ALOGV("android_media_AudioTrack_writeArray(offset=%d, sizeInSamples=%d) called", + // offsetInSamples, sizeInSamples); sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); if (lpTrack == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "Unable to retrieve AudioTrack pointer for write()"); - return 0; + return (jint)AUDIO_JAVA_INVALID_OPERATION; + } + + if (javaAudioData == NULL) { + ALOGE("NULL java array of audio data to play"); + return (jint)AUDIO_JAVA_BAD_VALUE; } - // get the pointer for the audio data from the java array // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such // a way that it becomes much more efficient. When doing so, we will have to prevent the // AudioSystem callback to be called while in critical section (in case of media server // process crash for instance) - jbyte* cAudioData = NULL; - if (javaAudioData) { - cAudioData = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL); - if (cAudioData == NULL) { - ALOGE("Error retrieving source of audio data to play, can't play"); - return 0; // out of memory or no data to load - } - } else { - ALOGE("NULL java array of audio data to play, can't play"); - return 0; + + // get the pointer for the audio data from the java array + auto cAudioData = envGetArrayElements(env, javaAudioData, NULL); + if (cAudioData == NULL) { + ALOGE("Error retrieving source of audio data to play"); + return (jint)AUDIO_JAVA_BAD_VALUE; // out of memory or no data to load } - jint written = writeToTrack(lpTrack, javaAudioFormat, cAudioData, offsetInBytes, sizeInBytes, - isWriteBlocking == JNI_TRUE /* blocking */); + jint samplesWritten = writeToTrack(lpTrack, javaAudioFormat, cAudioData, + offsetInSamples, sizeInSamples, isWriteBlocking == JNI_TRUE /* blocking */); - env->ReleaseByteArrayElements(javaAudioData, cAudioData, 0); + envReleaseArrayElements(env, javaAudioData, cAudioData, 0); - //ALOGV("write wrote %d (tried %d) bytes in the native AudioTrack with offset %d", - // (int)written, (int)(sizeInBytes), (int)offsetInBytes); - return written; + //ALOGV("write wrote %d (tried %d) samples in the native AudioTrack with offset %d", + // (int)samplesWritten, (int)(sizeInSamples), (int)offsetInSamples); + return samplesWritten; } - // ---------------------------------------------------------------------------- static jint android_media_AudioTrack_write_native_bytes(JNIEnv *env, jobject thiz, jbyteArray javaBytes, jint byteOffset, jint sizeInBytes, @@ -586,7 +623,7 @@ static jint android_media_AudioTrack_write_native_bytes(JNIEnv *env, jobject th if (lpTrack == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "Unable to retrieve AudioTrack pointer for write()"); - return 0; + return (jint)AUDIO_JAVA_INVALID_OPERATION; } ScopedBytesRO bytes(env, javaBytes); @@ -602,90 +639,6 @@ static jint android_media_AudioTrack_write_native_bytes(JNIEnv *env, jobject th } // ---------------------------------------------------------------------------- -static jint android_media_AudioTrack_write_short(JNIEnv *env, jobject thiz, - jshortArray javaAudioData, - jint offsetInShorts, jint sizeInShorts, - jint javaAudioFormat) { - - //ALOGV("android_media_AudioTrack_write_short(offset=%d, sizeInShorts=%d) called", - // offsetInShorts, sizeInShorts); - sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); - if (lpTrack == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "Unable to retrieve AudioTrack pointer for write()"); - return 0; - } - - // get the pointer for the audio data from the java array - // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such - // a way that it becomes much more efficient. When doing so, we will have to prevent the - // AudioSystem callback to be called while in critical section (in case of media server - // process crash for instance) - jshort* cAudioData = NULL; - if (javaAudioData) { - cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL); - if (cAudioData == NULL) { - ALOGE("Error retrieving source of audio data to play, can't play"); - return 0; // out of memory or no data to load - } - } else { - ALOGE("NULL java array of audio data to play, can't play"); - return 0; - } - jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData, - offsetInShorts * sizeof(short), sizeInShorts * sizeof(short), - true /*blocking write, legacy behavior*/); - env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0); - - if (written > 0) { - written /= sizeof(short); - } - //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d", - // (int)written, (int)(sizeInShorts), (int)offsetInShorts); - - return written; -} - - -// ---------------------------------------------------------------------------- -static jint android_media_AudioTrack_write_float(JNIEnv *env, jobject thiz, - jfloatArray javaAudioData, - jint offsetInFloats, jint sizeInFloats, - jint javaAudioFormat, - jboolean isWriteBlocking) { - - sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); - if (lpTrack == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "Unable to retrieve AudioTrack pointer for write()"); - return 0; - } - - jfloat* cAudioData = NULL; - if (javaAudioData) { - cAudioData = (jfloat *)env->GetFloatArrayElements(javaAudioData, NULL); - if (cAudioData == NULL) { - ALOGE("Error retrieving source of audio data to play, can't play"); - return 0; // out of memory or no data to load - } - } else { - ALOGE("NULL java array of audio data to play, can't play"); - return 0; - } - jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData, - offsetInFloats * sizeof(float), sizeInFloats * sizeof(float), - isWriteBlocking == JNI_TRUE /* blocking */); - env->ReleaseFloatArrayElements(javaAudioData, cAudioData, 0); - - if (written > 0) { - written /= sizeof(float); - } - - return written; -} - - -// ---------------------------------------------------------------------------- static jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env, jobject thiz) { sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); if (lpTrack == NULL) { @@ -976,12 +929,12 @@ static JNINativeMethod gMethods[] = { (void *)android_media_AudioTrack_setup}, {"native_finalize", "()V", (void *)android_media_AudioTrack_finalize}, {"native_release", "()V", (void *)android_media_AudioTrack_release}, - {"native_write_byte", "([BIIIZ)I",(void *)android_media_AudioTrack_write_byte}, + {"native_write_byte", "([BIIIZ)I",(void *)android_media_AudioTrack_writeArray<jbyteArray>}, {"native_write_native_bytes", "(Ljava/lang/Object;IIIZ)I", (void *)android_media_AudioTrack_write_native_bytes}, - {"native_write_short", "([SIII)I", (void *)android_media_AudioTrack_write_short}, - {"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_write_float}, + {"native_write_short", "([SIIIZ)I",(void *)android_media_AudioTrack_writeArray<jshortArray>}, + {"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_writeArray<jfloatArray>}, {"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume}, {"native_get_native_frame_count", "()I", (void *)android_media_AudioTrack_get_native_frame_count}, diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp index 0d5495356fad..91a3c7e6891f 100644 --- a/core/jni/android_view_DisplayEventReceiver.cpp +++ b/core/jni/android_view_DisplayEventReceiver.cpp @@ -29,6 +29,8 @@ #include <gui/DisplayEventReceiver.h> #include "android_os_MessageQueue.h" +#include <ScopedLocalRef.h> + #include "core_jni_helpers.h" namespace android { @@ -49,7 +51,7 @@ static struct { class NativeDisplayEventReceiver : public LooperCallback { public: NativeDisplayEventReceiver(JNIEnv* env, - jobject receiverObj, const sp<MessageQueue>& messageQueue); + jobject receiverWeak, const sp<MessageQueue>& messageQueue); status_t initialize(); void dispose(); @@ -59,7 +61,7 @@ protected: virtual ~NativeDisplayEventReceiver(); private: - jobject mReceiverObjGlobal; + jobject mReceiverWeakGlobal; sp<MessageQueue> mMessageQueue; DisplayEventReceiver mReceiver; bool mWaitingForVsync; @@ -72,15 +74,15 @@ private: NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, - jobject receiverObj, const sp<MessageQueue>& messageQueue) : - mReceiverObjGlobal(env->NewGlobalRef(receiverObj)), + jobject receiverWeak, const sp<MessageQueue>& messageQueue) : + mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)), mMessageQueue(messageQueue), mWaitingForVsync(false) { ALOGV("receiver %p ~ Initializing input event receiver.", this); } NativeDisplayEventReceiver::~NativeDisplayEventReceiver() { JNIEnv* env = AndroidRuntime::getJNIEnv(); - env->DeleteGlobalRef(mReceiverObjGlobal); + env->DeleteGlobalRef(mReceiverWeakGlobal); } status_t NativeDisplayEventReceiver::initialize() { @@ -190,10 +192,13 @@ bool NativeDisplayEventReceiver::processPendingEvents( void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) { JNIEnv* env = AndroidRuntime::getJNIEnv(); - ALOGV("receiver %p ~ Invoking vsync handler.", this); - env->CallVoidMethod(mReceiverObjGlobal, - gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count); - ALOGV("receiver %p ~ Returned from vsync handler.", this); + ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); + if (receiverObj.get()) { + ALOGV("receiver %p ~ Invoking vsync handler.", this); + env->CallVoidMethod(receiverObj.get(), + gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count); + ALOGV("receiver %p ~ Returned from vsync handler.", this); + } mMessageQueue->raiseAndClearException(env, "dispatchVsync"); } @@ -201,16 +206,19 @@ void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, ui void NativeDisplayEventReceiver::dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected) { JNIEnv* env = AndroidRuntime::getJNIEnv(); - ALOGV("receiver %p ~ Invoking hotplug handler.", this); - env->CallVoidMethod(mReceiverObjGlobal, - gDisplayEventReceiverClassInfo.dispatchHotplug, timestamp, id, connected); - ALOGV("receiver %p ~ Returned from hotplug handler.", this); + ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); + if (receiverObj.get()) { + ALOGV("receiver %p ~ Invoking hotplug handler.", this); + env->CallVoidMethod(receiverObj.get(), + gDisplayEventReceiverClassInfo.dispatchHotplug, timestamp, id, connected); + ALOGV("receiver %p ~ Returned from hotplug handler.", this); + } mMessageQueue->raiseAndClearException(env, "dispatchHotplug"); } -static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj, +static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj) { sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); if (messageQueue == NULL) { @@ -219,7 +227,7 @@ static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj, } sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env, - receiverObj, messageQueue); + receiverWeak, messageQueue); status_t status = receiver->initialize(); if (status) { String8 message; @@ -254,7 +262,7 @@ static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) { static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ { "nativeInit", - "(Landroid/view/DisplayEventReceiver;Landroid/os/MessageQueue;)J", + "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;)J", (void*)nativeInit }, { "nativeDispose", "(J)V", diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp index f42c89c12aa8..f2e6c4b5a8fd 100644 --- a/core/jni/android_view_DisplayListCanvas.cpp +++ b/core/jni/android_view_DisplayListCanvas.cpp @@ -133,10 +133,10 @@ static jint android_view_DisplayListCanvas_getMaxTextureHeight(JNIEnv* env, jobj // ---------------------------------------------------------------------------- static void android_view_DisplayListCanvas_drawPatch(JNIEnv* env, jobject clazz, - jlong rendererPtr, jobject jbitmap, jlong patchPtr, + jlong rendererPtr, jlong bitmapPtr, jlong patchPtr, float left, float top, float right, float bottom, jlong paintPtr) { - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr); Paint* paint = reinterpret_cast<Paint*>(paintPtr); @@ -276,7 +276,7 @@ static JNINativeMethod gMethods[] = { { "nCallDrawGLFunction", "(JJ)V", (void*) android_view_DisplayListCanvas_callDrawGLFunction }, - { "nDrawPatch", "(JLandroid/graphics/Bitmap;JFFFFJ)V", (void*) android_view_DisplayListCanvas_drawPatch }, + { "nDrawPatch", "(JJJFFFFJ)V", (void*) android_view_DisplayListCanvas_drawPatch }, { "nDrawRects", "(JJJ)V", (void*) android_view_DisplayListCanvas_drawRegionAsRects }, { "nDrawRoundRect", "(JJJJJJJJ)V", (void*) android_view_DisplayListCanvas_drawRoundRectProps }, diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp index aa79d705e8b4..a12629f7d9ba 100644 --- a/core/jni/android_view_GraphicBuffer.cpp +++ b/core/jni/android_view_GraphicBuffer.cpp @@ -67,6 +67,11 @@ static struct { jfieldID bottom; } gRectClassInfo; +static struct { + jfieldID mSurfaceFormat; + jmethodID setNativeBitmap; +} gCanvasClassInfo; + #define GET_INT(object, field) \ env->GetIntField(object, field) @@ -191,9 +196,13 @@ static jboolean android_view_GraphicBuffer_lockCanvas(JNIEnv* env, jobject, bitmap.setPixels(NULL); } - Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas); - nativeCanvas->setBitmap(bitmap); - nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom); + SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer->getPixelFormat()); + INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(&bitmap)); + + SkRect clipRect; + clipRect.set(rect.left, rect.top, rect.right, rect.bottom); + SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas); + nativeCanvas->clipRect(clipRect); if (dirtyRect) { INVOKEV(dirtyRect, gRectClassInfo.set, @@ -208,8 +217,7 @@ static jboolean android_view_GraphicBuffer_unlockCanvasAndPost(JNIEnv* env, jobj GraphicBufferWrapper* wrapper = reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle); - Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas); - nativeCanvas->setBitmap(SkBitmap()); + INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0); if (wrapper) { status_t status = wrapper->buffer->unlock(); @@ -294,6 +302,10 @@ int register_android_view_GraphicBuffer(JNIEnv* env) { gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I"); gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I"); + clazz = FindClassOrDie(env, "android/graphics/Canvas"); + gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I"); + gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V"); + return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); } diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 06d1e85b55a0..f1c90eab9eb7 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -74,6 +74,11 @@ static struct { jfieldID bottom; } gRectClassInfo; +static struct { + jfieldID mSurfaceFormat; + jmethodID setNativeBitmap; +} gCanvasClassInfo; + // ---------------------------------------------------------------------------- // this is just a pointer we use to pass to inc/decStrong @@ -314,6 +319,9 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, return 0; } + // Associate a SkCanvas object to this surface + env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format); + SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height, convertPixelFormat(outBuffer.format), kPremul_SkAlphaType); @@ -331,12 +339,12 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, bitmap.setPixels(NULL); } - Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj); - nativeCanvas->setBitmap(bitmap); + env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap, + reinterpret_cast<jlong>(&bitmap)); if (dirtyRectPtr) { - nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top, - dirtyRect.right, dirtyRect.bottom); + SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj); + nativeCanvas->clipRect( SkRect::Make(reinterpret_cast<const SkIRect&>(dirtyRect)) ); } if (dirtyRectObj) { @@ -362,8 +370,7 @@ static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz, } // detach the canvas from the surface - Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj); - nativeCanvas->setBitmap(SkBitmap()); + env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap, (jlong)0); // unlock surface status_t err = surface->unlockAndPost(); @@ -558,6 +565,10 @@ int register_android_view_Surface(JNIEnv* env) gSurfaceClassInfo.clazz, "mLock", "Ljava/lang/Object;"); gSurfaceClassInfo.ctor = GetMethodIDOrDie(env, gSurfaceClassInfo.clazz, "<init>", "(J)V"); + clazz = FindClassOrDie(env, "android/graphics/Canvas"); + gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I"); + gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V"); + clazz = FindClassOrDie(env, "android/graphics/Rect"); gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I"); gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I"); diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp index 7e05793a5233..c2bd0b3c428a 100644 --- a/core/jni/android_view_TextureView.cpp +++ b/core/jni/android_view_TextureView.cpp @@ -48,6 +48,11 @@ static struct { } gRectClassInfo; static struct { + jfieldID mSurfaceFormat; + jmethodID setNativeBitmap; +} gCanvasClassInfo; + +static struct { jfieldID nativeWindow; } gTextureViewClassInfo; @@ -167,9 +172,13 @@ static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject, bitmap.setPixels(NULL); } - Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas); - nativeCanvas->setBitmap(bitmap); - nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom); + SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer.format); + INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(&bitmap)); + + SkRect clipRect; + clipRect.set(rect.left, rect.top, rect.right, rect.bottom); + SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas); + nativeCanvas->clipRect(clipRect); if (dirtyRect) { INVOKEV(dirtyRect, gRectClassInfo.set, @@ -182,8 +191,7 @@ static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject, static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject, jlong nativeWindow, jobject canvas) { - Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas); - nativeCanvas->setBitmap(SkBitmap()); + INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0); if (nativeWindow) { sp<ANativeWindow> window((ANativeWindow*) nativeWindow); @@ -217,6 +225,10 @@ int register_android_view_TextureView(JNIEnv* env) { gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I"); gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I"); + clazz = FindClassOrDie(env, "android/graphics/Canvas"); + gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I"); + gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V"); + clazz = FindClassOrDie(env, "android/view/TextureView"); gTextureViewClassInfo.nativeWindow = GetFieldIDOrDie(env, clazz, "mNativeWindow", "J"); diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 4ccbb412eb15..11b38054433d 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -21,7 +21,6 @@ #include "jni.h" #include <nativehelper/JNIHelp.h> #include "core_jni_helpers.h" -#include <GraphicsJNI.h> #include <ScopedPrimitiveArray.h> #include <EGL/egl.h> @@ -348,11 +347,10 @@ static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz, } static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz, - jlong proxyPtr, jlong layerPtr, jobject jbitmap) { + jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr); return proxy->copyLayerInto(layer, bitmap); } @@ -460,7 +458,7 @@ static JNINativeMethod gMethods[] = { { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer }, - { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, + { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate }, { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate }, { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture }, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index ec57eba5d4da..e11c4a73e60b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -417,13 +417,6 @@ android:description="@string/permdesc_readSms" android:protectionLevel="dangerous" /> - <!-- Allows an application to write SMS messages. --> - <permission android:name="android.permission.WRITE_SMS" - android:permissionGroup="android.permission-group.SMS" - android:label="@string/permlab_writeSms" - android:description="@string/permdesc_writeSms" - android:protectionLevel="dangerous" /> - <!-- Allows an application to receive WAP push messages. --> <permission android:name="android.permission.RECEIVE_WAP_PUSH" android:permissionGroup="android.permission-group.SMS" diff --git a/core/res/res/drawable/scrubber_control_selector_material.xml b/core/res/res/color/seekbar_track_progress_material.xml index 989267607531..3597c0053a3c 100644 --- a/core/res/res/drawable/scrubber_control_selector_material.xml +++ b/core/res/res/color/seekbar_track_progress_material.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 The Android Open Source Project +<!-- Copyright (C) 2015 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,12 +15,7 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_enabled="false"> - <bitmap android:src="@drawable/scrubber_control_off_mtrl_alpha" - android:tint="?attr/colorControlNormal" /> - </item> - <item> - <bitmap android:src="@drawable/scrubber_control_on_mtrl_alpha" - android:tint="?attr/colorControlActivated" /> - </item> + <item android:state_enabled="false" + android:color="?attr/colorControlNormal" /> + <item android:color="?attr/colorControlActivated" /> </selector> diff --git a/core/res/res/drawable/scrubber_control_material_anim.xml b/core/res/res/drawable/seekbar_thumb_material_anim.xml index 4b132598142e..4b132598142e 100644 --- a/core/res/res/drawable/scrubber_control_material_anim.xml +++ b/core/res/res/drawable/seekbar_thumb_material_anim.xml diff --git a/core/res/res/drawable/scrubber_progress_horizontal_material.xml b/core/res/res/drawable/seekbar_track_material.xml index 86a85c3da695..01eb243304c6 100644 --- a/core/res/res/drawable/scrubber_progress_horizontal_material.xml +++ b/core/res/res/drawable/seekbar_track_material.xml @@ -19,7 +19,7 @@ android:gravity="center_vertical|fill_horizontal"> <shape android:shape="rectangle" android:tint="?attr/colorControlNormal"> - <size android:height="@dimen/scrubber_track_height_material" /> + <size android:height="@dimen/seekbar_track_background_height_material" /> <solid android:color="@color/white_disabled_material" /> </shape> </item> @@ -32,7 +32,7 @@ <item> <shape android:shape="rectangle" android:tint="?attr/colorControlActivated"> - <size android:height="@dimen/scrubber_track_height_material" /> + <size android:height="@dimen/seekbar_track_progress_height_material" /> <solid android:color="@color/white_disabled_material" /> </shape> </item> @@ -48,7 +48,7 @@ <item> <shape android:shape="rectangle" android:tint="?attr/colorControlActivated"> - <size android:height="@dimen/progress_bar_height_material" /> + <size android:height="@dimen/seekbar_track_progress_height_material" /> <solid android:color="@color/white" /> </shape> </item> diff --git a/core/res/res/layout/date_picker_header_material.xml b/core/res/res/layout/date_picker_header_material.xml index bda7de93001c..8125544cc2c1 100644 --- a/core/res/res/layout/date_picker_header_material.xml +++ b/core/res/res/layout/date_picker_header_material.xml @@ -45,6 +45,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Material.DatePicker.DateLabel" + android:gravity="start" android:maxLines="2" android:ellipsize="none" tools:text="Thu, Sep 30" diff --git a/core/res/res/layout/day_picker_content_material.xml b/core/res/res/layout/day_picker_content_material.xml new file mode 100644 index 000000000000..1852bfa58731 --- /dev/null +++ b/core/res/res/layout/day_picker_content_material.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <android.widget.DayPickerViewPager + android:id="@+id/day_picker_view_pager" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <ImageButton + android:id="@+id/prev" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minWidth="48dp" + android:minHeight="48dp" + android:src="@drawable/ic_chevron_left" + android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/date_picker_prev_month_button" + android:visibility="invisible" /> + + <ImageButton + android:id="@+id/next" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minWidth="48dp" + android:minHeight="48dp" + android:src="@drawable/ic_chevron_right" + android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/date_picker_next_month_button" + android:visibility="invisible" /> + +</FrameLayout> diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml index f6df01fc02e1..5bc0e037e950 100644 --- a/core/res/res/values/arrays.xml +++ b/core/res/res/values/arrays.xml @@ -352,9 +352,8 @@ <item>@drawable/ratingbar_small_material</item> <item>@drawable/ratingbar_indicator_material</item> <item>@drawable/scrollbar_handle_material</item> - <item>@drawable/scrubber_control_material_anim</item> - <item>@drawable/scrubber_control_selector_material</item> - <item>@drawable/scrubber_progress_horizontal_material</item> + <item>@drawable/seekbar_thumb_material_anim</item> + <item>@drawable/seekbar_track_material</item> <item>@drawable/spinner_background_material</item> <item>@drawable/spinner_textfield_background_material</item> <item>@drawable/switch_thumb_material_anim</item> diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml index 92d5aa1633ca..b9807770f9fb 100644 --- a/core/res/res/values/dimens_material.xml +++ b/core/res/res/values/dimens_material.xml @@ -118,7 +118,9 @@ <!-- Padding above and below selection dialog lists. --> <dimen name="dialog_list_padding_vertical_material">8dp</dimen> - <dimen name="scrubber_track_height_material">2dp</dimen> + <dimen name="seekbar_track_background_height_material">2dp</dimen> + <dimen name="seekbar_track_progress_height_material">2dp</dimen> + <dimen name="progress_bar_height_material">4dp</dimen> <!-- Material time picker dimensions. --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 208afb7d96c9..c157d4c357c2 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2642,6 +2642,7 @@ <public type="style" name="Theme.Material.Light.LightStatusBar" /> <public type="style" name="ThemeOverlay.Material.Dialog" /> <public type="style" name="TextAppearance.Material.Widget.Button.Inverse" /> + <public type="style" name="ThemeOverlay.Material.Dialog.Alert" /> <public type="id" name="pasteAsPlainText" /> <public type="id" name="undo" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 59366cc934dc..7123cc016180 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -685,21 +685,6 @@ SMS messages, regardless of content or confidentiality.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_writeSms">edit your text messages (SMS or MMS)</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_writeSms" product="tablet">Allows the app to write - to SMS messages stored on your tablet or SIM card. Malicious apps - may delete your messages.</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_writeSms" product="tv">Allows the app to write - to SMS messages stored on your TV or SIM card. Malicious apps - may delete your messages.</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_writeSms" product="default">Allows the app to write - to SMS messages stored on your phone or SIM card. Malicious apps - may delete your messages.</string> - - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_receiveWapPush">receive text messages (WAP)</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_receiveWapPush">Allows the app to receive and process @@ -3356,8 +3341,15 @@ <!-- Storage description for internal storage. [CHAR LIMIT=NONE] --> <string name="storage_internal">Internal storage</string> - <!-- Storage description for the SD card. [CHAR LIMIT=NONE] --> + <!-- Storage description for a generic SD card. [CHAR LIMIT=NONE] --> <string name="storage_sd_card">SD card</string> + <!-- Storage description for a SD card from a specific manufacturer. [CHAR LIMIT=NONE] --> + <string name="storage_sd_card_label"><xliff:g id="manufacturer" example="SanDisk">%s</xliff:g> SD card</string> + + <!-- Storage description for a generic USB drive. [CHAR LIMIT=NONE] --> + <string name="storage_usb_drive">USB drive</string> + <!-- Storage description for a USB drive from a specific manufacturer. [CHAR LIMIT=NONE] --> + <string name="storage_usb_drive_label"><xliff:g id="manufacturer" example="Seagate">%s</xliff:g> USB drive</string> <!-- Storage description for USB storage. [CHAR LIMIT=NONE] --> <string name="storage_usb">USB storage</string> diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index b874f6379e16..29b4ecc7d904 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -719,9 +719,9 @@ please see styles_device_defaults.xml. <style name="Widget.Material.SeekBar"> <item name="indeterminateOnly">false</item> - <item name="progressDrawable">@drawable/scrubber_progress_horizontal_material</item> - <item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_material</item> - <item name="thumb">@drawable/scrubber_control_material_anim</item> + <item name="progressDrawable">@drawable/seekbar_track_material</item> + <item name="indeterminateDrawable">@drawable/seekbar_track_material</item> + <item name="thumb">@drawable/seekbar_thumb_material_anim</item> <item name="splitTrack">true</item> <item name="focusable">true</item> <item name="paddingStart">16dip</item> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 180b4158f5f4..7e2415088600 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2214,6 +2214,9 @@ <java-symbol type="string" name="storage_internal" /> <java-symbol type="string" name="storage_sd_card" /> + <java-symbol type="string" name="storage_sd_card_label" /> + <java-symbol type="string" name="storage_usb_drive" /> + <java-symbol type="string" name="storage_usb_drive_label" /> <java-symbol type="string" name="storage_usb" /> <!-- Floating toolbar --> @@ -2242,4 +2245,6 @@ <java-symbol type="layout" name="chooser_grid" /> <java-symbol type="layout" name="resolve_grid_item" /> <java-symbol type="id" name="title_icon" /> + <java-symbol type="id" name="day_picker_view_pager" /> + <java-symbol type="layout" name="day_picker_content_material" /> </resources> diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index 9931d00ef90c..a413d917cf62 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -182,7 +182,7 @@ please see themes_device_defaults.xml. <item name="dialogPreferredPadding">@dimen/dialog_padding_material</item> <!-- AlertDialog attributes --> - <item name="alertDialogTheme">@style/ThemeOverlay.Material.Dialog</item> + <item name="alertDialogTheme">@style/ThemeOverlay.Material.Dialog.Alert</item> <item name="alertDialogStyle">@style/AlertDialog.Material</item> <item name="alertDialogCenterButtons">false</item> <item name="alertDialogIcon">@drawable/ic_dialog_alert_material</item> @@ -538,7 +538,7 @@ please see themes_device_defaults.xml. <item name="dialogPreferredPadding">@dimen/dialog_padding_material</item> <!-- AlertDialog attributes --> - <item name="alertDialogTheme">@style/ThemeOverlay.Material.Dialog</item> + <item name="alertDialogTheme">@style/ThemeOverlay.Material.Dialog.Alert</item> <item name="alertDialogStyle">@style/AlertDialog.Material.Light</item> <item name="alertDialogCenterButtons">false</item> <item name="alertDialogIcon">@drawable/ic_dialog_alert_material</item> @@ -882,6 +882,11 @@ please see themes_device_defaults.xml. <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item> </style> + <style name="ThemeOverlay.Material.Dialog.Alert"> + <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item> + <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item> + </style> + <!-- Variant of the material (dark) theme with no action bar. --> <style name="Theme.Material.NoActionBar"> <item name="windowActionBar">false</item> diff --git a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk index 5fa24055d9a8..6ee6ffab234c 100644 --- a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk +++ b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk @@ -5,7 +5,6 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := install_jni_lib_open_from_apk -LOCAL_JNI_SHARED_LIBRARIES_ZIP_OPTIONS := -0 LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES := true include $(FrameworkCoreTests_BUILD_PACKAGE) diff --git a/docs/html/images/tools/hierarchicalviewer-icon.png b/docs/html/images/tools/hierarchicalviewer-icon.png Binary files differnew file mode 100644 index 000000000000..061f95248401 --- /dev/null +++ b/docs/html/images/tools/hierarchicalviewer-icon.png diff --git a/docs/html/images/tools/studio-DDMS-open-perspective-icon.png b/docs/html/images/tools/studio-DDMS-open-perspective-icon.png Binary files differnew file mode 100644 index 000000000000..f8e6d1ad57b0 --- /dev/null +++ b/docs/html/images/tools/studio-DDMS-open-perspective-icon.png diff --git a/docs/html/images/tools/studio-gradle-panel.png b/docs/html/images/tools/studio-gradle-panel.png Binary files differdeleted file mode 100644 index 4a76a8dccd93..000000000000 --- a/docs/html/images/tools/studio-gradle-panel.png +++ /dev/null diff --git a/docs/html/images/tools/studio-gradle-tab.png b/docs/html/images/tools/studio-gradle-tab.png Binary files differdeleted file mode 100644 index b0f302ccd0f4..000000000000 --- a/docs/html/images/tools/studio-gradle-tab.png +++ /dev/null diff --git a/docs/html/tools/building/building-studio.jd b/docs/html/tools/building/building-studio.jd index 68800da30763..443119412090 100644 --- a/docs/html/tools/building/building-studio.jd +++ b/docs/html/tools/building/building-studio.jd @@ -67,26 +67,13 @@ selected build variant. For more information, see the <a href="{@docRoot}sdk/installing/studio-build.html">Build System</a> guide.</p> <p>To view the list of all available build tasks in Android Studio, click <strong>Gradle</strong> -on the right side of the IDE window. The <em>Gradle tasks</em> panel appears as shown in -figure 2. Double-click any build task to run it in Android Studio. To hide the <em>Gradle tasks</em> -panel, click <strong>Gradle</strong> again.</p> +on the right side of the IDE window. The <em>Gradle tasks</em> panel appears.</p> -<img src="{@docRoot}images/tools/studio-gradle-panel.png" alt="" /> -<p class="img-caption"><strong>Figure 2.</strong> The list of build tasks in Android Studio.</p> <h3 id="buildRelease">Build a release version</h3> -<p>You can now build the release version of your application for distribution. To build it from Android -Studio:</p> - -<ol> - <li>Click <strong>Gradle</strong> on the right side of the IDE window.</li> - <li>On the <em>All tasks</em> section of the sidebar that appears, expand - <strong>BuildSystemExample</strong>.</li> - <li>Expand <strong>:app</strong> and double-click <strong>assembleRelease</strong>.</li> -</ol> - -<p>You can use this procedure to invoke any build task from Android Studio.</p> +<p>You can now use the <strong>Build</strong> menu options to build the release version of your +application for distribution. </p> <p>The build generates an APK for each build variant: the <code>app/build/apk/</code> directory contains packages named diff --git a/docs/html/tools/building/configuring-gradle.jd b/docs/html/tools/building/configuring-gradle.jd index 83795085572c..7cca5b4809b9 100644 --- a/docs/html/tools/building/configuring-gradle.jd +++ b/docs/html/tools/building/configuring-gradle.jd @@ -470,7 +470,11 @@ applied to each build. </p> <li>fullRelease</li> </ul> -<p>To build this example, invoke the <code>assemble</code> task from Android Studio or from the -command line.</p> +<p>To build this example, click the <strong>Build</strong> menu option in Android Studio or invoke +the <code>assemble</code> task from the command line. </p> + +<p class="note"><strong>Note:</strong> The <strong>Build > Make Project</strong> option compiles +all the source files in the entire project that have been modified since the last compilation. The +<strong>Build > Rebuild Project</strong> option recomplies all the source files in the project.</p> <p>Separate output folders are created for each build variant. </p> diff --git a/docs/html/tools/building/plugin-for-gradle.jd b/docs/html/tools/building/plugin-for-gradle.jd index 54a03fd1761a..a497c1bbc186 100644 --- a/docs/html/tools/building/plugin-for-gradle.jd +++ b/docs/html/tools/building/plugin-for-gradle.jd @@ -15,7 +15,7 @@ page.title=Android Plug-in for Gradle <li><a href="{@docRoot}sdk/installing/studio-build.html"> Build System Overview</a></li> <li><a href="{@docRoot}tools/building/index.html"> -Buidling and Running</a></li> +Building and Running</a></li> <li><a href="{@docRoot}tools/building/building-studio.html"> Building and Running from Android Studio</a></li> </ul> @@ -273,16 +273,9 @@ tasks are:</p> <dd><p>Performs the clean.</p></dd> </dl> -<p>The Android plugin provides additional tasks for <em>connectedCheck</em> and <em>deviceCheck</em> +<p>The Android plugin provides the <em>connectedCheck</em> and <em>deviceCheck</em> tasks for checks run on connected, emulated, and remote devices. Gradle tasks can be viewed by clicking -the Gradle tab</a> in the right margin. -<img src="{@docRoot}images/tools/studio-gradle-tab.png"></p> -<p class="img-caption"><strong>Figure 1:</strong> Gradle tab</p> - -<p>Running a top-level task, runs all the dependent tasks. For example, the <em>assemble</em> task -has dependent tasks for <em>assembleDebug</em> and <em>assembleRelease</em> to make the debug and -release APKs. The <em>assemble</em> task depends on these tasks so calling it builds both APKs. -These tasks can also be called independently to build the debug or release APK separately. </p> +the Gradle tab</a> in the right margin.</p> <p>You can view the list of available tasks and invoke any task from Android Studio and from the command line, as described in diff --git a/docs/html/tools/help/hierarchy-viewer.jd b/docs/html/tools/help/hierarchy-viewer.jd index 4a346e00fc01..da4cc1e9b261 100644 --- a/docs/html/tools/help/hierarchy-viewer.jd +++ b/docs/html/tools/help/hierarchy-viewer.jd @@ -3,16 +3,27 @@ parent.title=Tools parent.link=index.html @jd:body -<p>Hierarchy Viewer allows you to debug and optimize your user -interface. It provides a visual representation of the layout's View hierarchy -(the Layout View) and a magnified inspector of the display (the Pixel Perfect View). -</p> +<p>The Hierarchy Viewer allows you to debug and optimize your user +interface. It provides a visual representation of the layout's View hierarchy +(the Layout View) and a magnified inspector of the display (the Pixel Perfect View). </p> + +<p>To start the Hierarchy Viewer, do one of the following: </p> -<p>To start Hierarchy Viewer, enter the following command from the SDK <code>tools/</code> directory:</p> - <pre>hierarchyviewer</pre> -</ol> +<ul> +<li> From Android Studio, choose <strong>Tools > Android Device Monitor</strong> or click the +Android Device Monitor icon +<img src="{@docRoot}images/tools/hierarchicalviewer-icon.png" alt=""/>. Click the Open Perspectives +icon <img src="{@docRoot}images/tools/studio-DDMS-open-perspective-icon.png" alt=""/> and select +<strong>Hierarchy View</strong>. </li> +<li>From the SDK <code>tools/</code> directory, enter: + <pre>monitor</pre> </li> +</ul> -<p>For more information on how to use Hierarchy Viewer, see -<a href="{@docRoot}tools/debugging/debugging-ui.html">Debugging and Profiling UIs</a> +<p>For more information on how to use the Hierarchy Viewer, see +<a href="{@docRoot}tools/debugging/debugging-ui.html">Optimizing Your UI</a>. </p> +<p class="note"><strong>Note:</strong> The command line version of Hierarchy Viewer has been +deprecated. </p> + + diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index be5c52b23fb5..e2f7799786a0 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -1568,13 +1568,9 @@ public final class Bitmap implements Parcelable { nativePrepareToDraw(mSkBitmapPtr); } - /** - * Refs the underlying SkPixelRef and returns a pointer to it. - * - * @hide - * */ - public final long refSkPixelRef() { - return nativeRefPixelRef(mSkBitmapPtr); + /** @hide */ + public final long getSkBitmap() { + return mSkBitmapPtr; } private static class BitmapFinalizer { @@ -1665,5 +1661,4 @@ public final class Bitmap implements Parcelable { private static native boolean nativeHasMipMap(long nativeBitmap); private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap); private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1); - private static native long nativeRefPixelRef(long nativeBitmap); } diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java index bd74bc88e33f..f2f890e0c5a7 100644 --- a/graphics/java/android/graphics/BitmapShader.java +++ b/graphics/java/android/graphics/BitmapShader.java @@ -42,7 +42,8 @@ public class BitmapShader extends Shader { mBitmap = bitmap; mTileX = tileX; mTileY = tileY; - init(nativeCreate(bitmap, tileX.nativeInt, tileY.nativeInt)); + final long b = bitmap.getSkBitmap(); + init(nativeCreate(b, tileX.nativeInt, tileY.nativeInt)); } /** @@ -55,6 +56,6 @@ public class BitmapShader extends Shader { return copy; } - private static native long nativeCreate(Bitmap bitmap, int shaderTileModeX, + private static native long nativeCreate(long native_bitmap, int shaderTileModeX, int shaderTileModeY); } diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 1c568844f5a5..48afcbfde5d0 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -81,6 +81,10 @@ public class Canvas { */ protected int mScreenDensity = Bitmap.DENSITY_NONE; + // Used by native code + @SuppressWarnings("UnusedDeclaration") + private int mSurfaceFormat; + /** * Flag for drawTextRun indicating left-to-right run direction. * @hide @@ -133,7 +137,7 @@ public class Canvas { public Canvas() { if (!isHardwareAccelerated()) { // 0 means no native bitmap - mNativeCanvasWrapper = initRaster(null); + mNativeCanvasWrapper = initRaster(0); mFinalizer = new CanvasFinalizer(mNativeCanvasWrapper); } else { mFinalizer = null; @@ -154,7 +158,7 @@ public class Canvas { throw new IllegalStateException("Immutable bitmap passed to Canvas constructor"); } throwIfCannotDraw(bitmap); - mNativeCanvasWrapper = initRaster(bitmap); + mNativeCanvasWrapper = initRaster(bitmap.getSkBitmap()); mFinalizer = new CanvasFinalizer(mNativeCanvasWrapper); mBitmap = bitmap; mDensity = bitmap.mDensity; @@ -211,7 +215,7 @@ public class Canvas { } if (bitmap == null) { - native_setBitmap(mNativeCanvasWrapper, null); + native_setBitmap(mNativeCanvasWrapper, 0, false); mDensity = Bitmap.DENSITY_NONE; } else { if (!bitmap.isMutable()) { @@ -219,7 +223,7 @@ public class Canvas { } throwIfCannotDraw(bitmap); - native_setBitmap(mNativeCanvasWrapper, bitmap); + native_setBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), true); mDensity = bitmap.mDensity; } @@ -227,6 +231,13 @@ public class Canvas { } /** + * setBitmap() variant for native callers with a raw bitmap handle. + */ + private void setNativeBitmap(long bitmapHandle) { + native_setBitmap(mNativeCanvasWrapper, bitmapHandle, false); + } + + /** * Set the viewport dimensions if this canvas is GL based. If it is not, * this method is ignored and no exception is thrown. * @@ -1335,7 +1346,7 @@ public class Canvas { */ public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) { throwIfCannotDraw(bitmap); - native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, + native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity); } @@ -1381,7 +1392,7 @@ public class Canvas { bottom = src.bottom; } - native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -1428,7 +1439,7 @@ public class Canvas { bottom = src.bottom; } - native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -1509,7 +1520,7 @@ public class Canvas { * @param paint May be null. The paint used to draw the bitmap */ public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) { - nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(), + nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getSkBitmap(), matrix.ni(), paint != null ? paint.getNativeInstance() : 0); } @@ -1564,7 +1575,7 @@ public class Canvas { // no mul by 2, since we need only 1 color per vertex checkRange(colors.length, colorOffset, count); } - nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight, + nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap.getSkBitmap(), meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint != null ? paint.getNativeInstance() : 0); } @@ -1965,9 +1976,10 @@ public class Canvas { */ public static native void freeTextLayoutCaches(); - private static native long initRaster(Bitmap bitmap); + private static native long initRaster(long nativeBitmapOrZero); private static native void native_setBitmap(long canvasHandle, - Bitmap bitmap); + long bitmapHandle, + boolean copyState); private static native boolean native_isOpaque(long canvasHandle); private static native int native_getWidth(long canvasHandle); private static native int native_getHeight(long canvasHandle); @@ -2052,13 +2064,13 @@ public class Canvas { private static native void native_drawPath(long nativeCanvas, long nativePath, long nativePaint); - private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap, + private native void native_drawBitmap(long nativeCanvas, long nativeBitmap, float left, float top, long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity); - private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap, + private native void native_drawBitmap(long nativeCanvas, long nativeBitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity); @@ -2068,11 +2080,11 @@ public class Canvas { boolean hasAlpha, long nativePaintOrZero); private static native void nativeDrawBitmapMatrix(long nativeCanvas, - Bitmap bitmap, + long nativeBitmap, long nativeMatrix, long nativePaint); private static native void nativeDrawBitmapMesh(long nativeCanvas, - Bitmap bitmap, + long nativeBitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java index 21a212a0ec42..9c4299aa5d70 100644 --- a/graphics/java/android/graphics/NinePatch.java +++ b/graphics/java/android/graphics/NinePatch.java @@ -98,7 +98,7 @@ public class NinePatch { public NinePatch(Bitmap bitmap, byte[] chunk, String srcName) { mBitmap = bitmap; mSrcName = srcName; - mNativeChunk = validateNinePatchChunk(chunk); + mNativeChunk = validateNinePatchChunk(mBitmap.getSkBitmap(), chunk); } /** @@ -199,12 +199,12 @@ public class NinePatch { } void drawSoftware(Canvas canvas, RectF location, Paint paint) { - nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap, mNativeChunk, + nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.getSkBitmap(), mNativeChunk, paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity); } void drawSoftware(Canvas canvas, Rect location, Paint paint) { - nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap, mNativeChunk, + nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.getSkBitmap(), mNativeChunk, paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity); } @@ -252,7 +252,7 @@ public class NinePatch { * that are transparent. */ public final Region getTransparentRegion(Rect bounds) { - long r = nativeGetTransparentRegion(mBitmap, mNativeChunk, bounds); + long r = nativeGetTransparentRegion(mBitmap.getSkBitmap(), mNativeChunk, bounds); return r != 0 ? new Region(r) : null; } @@ -271,11 +271,11 @@ public class NinePatch { * If validation is successful, this method returns a native Res_png_9patch* * object used by the renderers. */ - private static native long validateNinePatchChunk(byte[] chunk); + private static native long validateNinePatchChunk(long bitmap, byte[] chunk); private static native void nativeFinalize(long chunk); - private static native void nativeDraw(long canvas_instance, RectF loc, Bitmap bitmap_instance, + private static native void nativeDraw(long canvas_instance, RectF loc, long bitmap_instance, long c, long paint_instance_or_null, int destDensity, int srcDensity); - private static native void nativeDraw(long canvas_instance, Rect loc, Bitmap bitmap_instance, + private static native void nativeDraw(long canvas_instance, Rect loc, long bitmap_instance, long c, long paint_instance_or_null, int destDensity, int srcDensity); - private static native long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location); + private static native long nativeGetTransparentRegion(long bitmap, long chunk, Rect location); } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index e8b8c77ec477..22ff3e74f86c 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -572,7 +572,7 @@ public abstract class Drawable { * Specifies a tint blending mode for this drawable. * <p> * Defines how this drawable's tint color should be blended into the drawable - * before it is drawn to screen. Default tint mode is {@link PorterDuff.Mode#MULTIPLY}. + * before it is drawn to screen. Default tint mode is {@link PorterDuff.Mode#SRC_IN}. * </p> * <p class="note"><strong>Note:</strong> Setting a color filter via * {@link #setColorFilter(ColorFilter)} or diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp index 882826ead10e..4d2e3a097b55 100644 --- a/libs/hwui/AssetAtlas.cpp +++ b/libs/hwui/AssetAtlas.cpp @@ -82,12 +82,12 @@ void AssetAtlas::updateTextureId() { /////////////////////////////////////////////////////////////////////////////// AssetAtlas::Entry* AssetAtlas::getEntry(const SkBitmap* bitmap) const { - ssize_t index = mEntries.indexOfKey(bitmap->pixelRef()); + ssize_t index = mEntries.indexOfKey(bitmap); return index >= 0 ? mEntries.valueAt(index) : nullptr; } Texture* AssetAtlas::getEntryTexture(const SkBitmap* bitmap) const { - ssize_t index = mEntries.indexOfKey(bitmap->pixelRef()); + ssize_t index = mEntries.indexOfKey(bitmap); return index >= 0 ? mEntries.valueAt(index)->texture : nullptr; } @@ -120,7 +120,7 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { const float height = float(mTexture->height); for (int i = 0; i < count; ) { - SkPixelRef* pixelRef = reinterpret_cast<SkPixelRef*>(map[i++]); + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(map[i++]); // NOTE: We're converting from 64 bit signed values to 32 bit // signed values. This is guaranteed to be safe because the "x" // and "y" coordinate values are guaranteed to be representable @@ -131,21 +131,21 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { bool rotated = map[i++] > 0; // Bitmaps should never be null, we're just extra paranoid - if (!pixelRef) continue; + if (!bitmap) continue; const UvMapper mapper( - x / width, (x + pixelRef->info().width()) / width, - y / height, (y + pixelRef->info().height()) / height); + x / width, (x + bitmap->width()) / width, + y / height, (y + bitmap->height()) / height); Texture* texture = new DelegateTexture(caches, mTexture); - texture->blend = !SkAlphaTypeIsOpaque(pixelRef->info().alphaType()); - texture->width = pixelRef->info().width(); - texture->height = pixelRef->info().height(); + texture->blend = !bitmap->isOpaque(); + texture->width = bitmap->width(); + texture->height = bitmap->height(); - Entry* entry = new Entry(pixelRef, x, y, rotated, texture, mapper, *this); + Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this); texture->uvMapper = &entry->uvMapper; - mEntries.add(entry->pixelRef, entry); + mEntries.add(entry->bitmap, entry); } } diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h index 17c5281cb3de..1772effb911b 100644 --- a/libs/hwui/AssetAtlas.h +++ b/libs/hwui/AssetAtlas.h @@ -48,8 +48,24 @@ public: * Entry representing the position and rotation of a * bitmap inside the atlas. */ - class Entry { - public: + struct Entry { + /** + * The bitmap that generated this atlas entry. + */ + SkBitmap* bitmap; + + /** + * Location of the bitmap inside the atlas, in pixels. + */ + int x; + int y; + + /** + * If set, the bitmap is rotated 90 degrees (clockwise) + * inside the atlas. + */ + bool rotated; + /* * A "virtual texture" object that represents the texture * this entry belongs to. This texture should never be @@ -64,6 +80,11 @@ public: const UvMapper uvMapper; /** + * Atlas this entry belongs to. + */ + const AssetAtlas& atlas; + + /** * Unique identifier used to merge bitmaps and 9-patches stored * in the atlas. */ @@ -72,37 +93,10 @@ public: } private: - /** - * The pixel ref that generated this atlas entry. - */ - SkPixelRef* pixelRef; - - /** - * Location of the bitmap inside the atlas, in pixels. - */ - int x; - int y; - - /** - * If set, the bitmap is rotated 90 degrees (clockwise) - * inside the atlas. - */ - bool rotated; - - /** - * Atlas this entry belongs to. - */ - const AssetAtlas& atlas; - - Entry(SkPixelRef* pixelRef, int x, int y, bool rotated, - Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas) - : texture(texture) - , uvMapper(mapper) - , pixelRef(pixelRef) - , x(x) - , y(y) - , rotated(rotated) - , atlas(atlas) { + Entry(SkBitmap* bitmap, int x, int y, bool rotated, + Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas): + bitmap(bitmap), x(x), y(y), rotated(rotated), + texture(texture), uvMapper(mapper), atlas(atlas) { } ~Entry() { @@ -184,7 +178,7 @@ private: const bool mBlendKey; const bool mOpaqueKey; - KeyedVector<const SkPixelRef*, Entry*> mEntries; + KeyedVector<const SkBitmap*, Entry*> mEntries; }; // class AssetAtlas }; // namespace uirenderer diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h index aa24673c4e30..7ad0683d9248 100644 --- a/libs/hwui/Canvas.h +++ b/libs/hwui/Canvas.h @@ -29,7 +29,7 @@ class ANDROID_API Canvas { public: virtual ~Canvas() {}; - static Canvas* create_canvas(const SkBitmap& bitmap); + static Canvas* create_canvas(SkBitmap* bitmap); /** * Create a new Canvas object which delegates to an SkCanvas. @@ -52,7 +52,7 @@ public: */ virtual SkCanvas* asSkCanvas() = 0; - virtual void setBitmap(const SkBitmap& bitmap) = 0; + virtual void setBitmap(SkBitmap* bitmap, bool copyState) = 0; virtual bool isOpaque() = 0; virtual int width() = 0; @@ -87,8 +87,7 @@ public: virtual bool quickRejectRect(float left, float top, float right, float bottom) const = 0; virtual bool quickRejectPath(const SkPath& path) const = 0; - virtual bool clipRect(float left, float top, float right, float bottom, - SkRegion::Op op = SkRegion::kIntersect_Op) = 0; + virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) = 0; virtual bool clipPath(const SkPath* path, SkRegion::Op op) = 0; virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0; diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 4d596fee5fef..8757e15006b7 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -220,7 +220,7 @@ void DisplayListRenderer::drawLayer(DeferredLayerUpdater* layerHandle, float x, } void DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { - bitmap = refBitmap(*bitmap); + bitmap = refBitmap(bitmap); paint = refPaint(paint); addDrawOp(new (alloc()) DrawBitmapOp(bitmap, paint)); @@ -286,7 +286,7 @@ void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, float srcLeft, floa dstRight = srcRight - srcLeft; dstBottom = srcBottom - srcTop; - addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap), + addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(&bitmap), srcLeft, srcTop, srcRight, srcBottom, dstLeft, dstTop, dstRight, dstBottom, paint)); restore(); @@ -294,7 +294,7 @@ void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, float srcLeft, floa } } - addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap), + addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(&bitmap), srcLeft, srcTop, srcRight, srcBottom, dstLeft, dstTop, dstRight, dstBottom, paint)); } @@ -307,17 +307,17 @@ void DisplayListRenderer::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, paint = refPaint(paint); colors = refBuffer<int>(colors, vertexCount); // 1 color per vertex - addDrawOp(new (alloc()) DrawBitmapMeshOp(refBitmap(bitmap), meshWidth, meshHeight, + addDrawOp(new (alloc()) DrawBitmapMeshOp(refBitmap(&bitmap), meshWidth, meshHeight, vertices, colors, paint)); } -void DisplayListRenderer::drawPatch(const SkBitmap& bitmap, const Res_png_9patch* patch, +void DisplayListRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch, float left, float top, float right, float bottom, const SkPaint* paint) { - const SkBitmap* bitmapPtr = refBitmap(bitmap); + bitmap = refBitmap(bitmap); patch = refPatch(patch); paint = refPaint(paint); - addDrawOp(new (alloc()) DrawPatchOp(bitmapPtr, patch, left, top, right, bottom, paint)); + addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint)); } void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) { diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 44cf546244b3..53fd1adbeb14 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -100,7 +100,7 @@ public: // Bitmap-based void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint); // TODO: move drawPatch() to Canvas.h - void drawPatch(const SkBitmap& bitmap, const Res_png_9patch* patch, + void drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch, float left, float top, float right, float bottom, const SkPaint* paint); // Shapes @@ -138,7 +138,7 @@ public: // ---------------------------------------------------------------------------- virtual SkCanvas* asSkCanvas() override; - virtual void setBitmap(const SkBitmap& bitmap) override { + virtual void setBitmap(SkBitmap* bitmap, bool copyState) override { LOG_ALWAYS_FATAL("DisplayListRenderer is not backed by a bitmap."); } @@ -347,7 +347,7 @@ private: return cachedRegion; } - inline const SkBitmap* refBitmap(const SkBitmap& bitmap) { + inline const SkBitmap* refBitmap(const SkBitmap* bitmap) { // Note that this assumes the bitmap is immutable. There are cases this won't handle // correctly, such as creating the bitmap from scratch, drawing with it, changing its // contents, and drawing again. The only fix would be to always copy it the first time, diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index 454fedc2b179..d3b8d706e606 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -59,13 +59,13 @@ void ResourceCache::unlock() { mLock.unlock(); } -const SkBitmap* ResourceCache::insert(const SkBitmap& bitmapResource) { +const SkBitmap* ResourceCache::insert(const SkBitmap* bitmapResource) { Mutex::Autolock _l(mLock); BitmapKey bitmapKey(bitmapResource); ssize_t index = mBitmapCache.indexOfKey(bitmapKey); if (index == NAME_NOT_FOUND) { - SkBitmap* cachedBitmap = new SkBitmap(bitmapResource); + SkBitmap* cachedBitmap = new SkBitmap(*bitmapResource); index = mBitmapCache.add(bitmapKey, cachedBitmap); return cachedBitmap; } @@ -121,7 +121,7 @@ void ResourceCache::decrementRefcountLocked(void* resource) { } void ResourceCache::decrementRefcountLocked(const SkBitmap* bitmapResource) { - BitmapKey bitmapKey(*bitmapResource); + BitmapKey bitmapKey(bitmapResource); ssize_t index = mBitmapCache.indexOfKey(bitmapKey); LOG_ALWAYS_FATAL_IF(index == NAME_NOT_FOUND, diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h index 6c483faf3508..fae55d14fead 100644 --- a/libs/hwui/ResourceCache.h +++ b/libs/hwui/ResourceCache.h @@ -53,11 +53,11 @@ public: class BitmapKey { public: - BitmapKey(const SkBitmap& bitmap) + BitmapKey(const SkBitmap* bitmap) : mRefCount(1) - , mBitmapDimensions(bitmap.dimensions()) - , mPixelRefOrigin(bitmap.pixelRefOrigin()) - , mPixelRefStableID(bitmap.pixelRef()->getStableID()) { } + , mBitmapDimensions(bitmap->dimensions()) + , mPixelRefOrigin(bitmap->pixelRefOrigin()) + , mPixelRefStableID(bitmap->pixelRef()->getStableID()) { } void operator=(const BitmapKey& other); bool operator==(const BitmapKey& other) const; @@ -101,7 +101,7 @@ public: * The cache stores a copy of the provided resource or refs an existing resource * if the bitmap has previously been inserted and returns the cached copy. */ - const SkBitmap* insert(const SkBitmap& resource); + const SkBitmap* insert(const SkBitmap* resource); void incrementRefcount(const Res_png_9patch* resource); diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index a32306554699..8b1175707c81 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -31,7 +31,7 @@ namespace android { // Holds an SkCanvas reference plus additional native data. class SkiaCanvas : public Canvas { public: - explicit SkiaCanvas(const SkBitmap& bitmap); + explicit SkiaCanvas(SkBitmap* bitmap); /** * Create a new SkiaCanvas. @@ -49,7 +49,7 @@ public: return mCanvas.get(); } - virtual void setBitmap(const SkBitmap& bitmap) override; + virtual void setBitmap(SkBitmap* bitmap, bool copyState) override; virtual bool isOpaque() override; virtual int width() override; @@ -145,7 +145,19 @@ private: SkAutoTDelete<SkDeque> mSaveStack; // lazily allocated, tracks partial saves. }; -Canvas* Canvas::create_canvas(const SkBitmap& bitmap) { +// Construct an SkCanvas from the bitmap. +static SkCanvas* createCanvas(SkBitmap* bitmap) { + if (bitmap) { + return SkNEW_ARGS(SkCanvas, (*bitmap)); + } + + // Create an empty bitmap device to prevent callers from crashing + // if they attempt to draw into this canvas. + SkBitmap emptyBitmap; + return new SkCanvas(emptyBitmap); +} + +Canvas* Canvas::create_canvas(SkBitmap* bitmap) { return new SkiaCanvas(bitmap); } @@ -153,8 +165,8 @@ Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) { return new SkiaCanvas(skiaCanvas); } -SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) { - mCanvas.reset(new SkCanvas(bitmap)); +SkiaCanvas::SkiaCanvas(SkBitmap* bitmap) { + mCanvas.reset(createCanvas(bitmap)); } // ---------------------------------------------------------------------------- @@ -179,11 +191,11 @@ private: SkCanvas* m_dstCanvas; }; -void SkiaCanvas::setBitmap(const SkBitmap& bitmap) { - SkCanvas* newCanvas = new SkCanvas(bitmap); +void SkiaCanvas::setBitmap(SkBitmap* bitmap, bool copyState) { + SkCanvas* newCanvas = createCanvas(bitmap); SkASSERT(newCanvas); - if (!bitmap.isNull()) { + if (copyState) { // Copy the canvas matrix & clip state. newCanvas->setMatrix(mCanvas->getTotalMatrix()); if (NULL != mCanvas->getDevice() && NULL != newCanvas->getDevice()) { diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index d15fa3941766..cc872412251e 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -293,11 +293,11 @@ CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* laye return (void*) success; } -bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { +bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { SETUP_TASK(copyLayerInto); args->context = mContext; args->layer = layer; - args->bitmap = &bitmap; + args->bitmap = bitmap; return (bool) postAndWait(task); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index cc475faeddf3..29c6f0818cb0 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -83,7 +83,7 @@ public: ANDROID_API DeferredLayerUpdater* createTextureLayer(); ANDROID_API void buildLayer(RenderNode* node); - ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap); + ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer); ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer); ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer); diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 9e1e0558a0fd..3e771f48a35f 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -901,20 +901,63 @@ public class AudioRecord * the parameters don't resolve to valid data and indexes. * The number of bytes will not exceed sizeInBytes. */ - public int read(byte[] audioData, int offsetInBytes, int sizeInBytes) { - if (mState != STATE_INITIALIZED) { + public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) { + return read(audioData, offsetInBytes, sizeInBytes, READ_BLOCKING); + } + + /** + * Reads audio data from the audio hardware for recording into a byte array. + * The format specified in the AudioRecord constructor should be + * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array. + * @param audioData the array to which the recorded audio data is written. + * @param offsetInBytes index in audioData from which the data is written expressed in bytes. + * @param sizeInBytes the number of requested bytes. + * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}. + * <br>With {@link #READ_BLOCKING}, the read will block until all the requested data + * is read. + * <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after + * reading as much audio data as possible without blocking. + * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION} + * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if + * the parameters don't resolve to valid data and indexes. + * The number of bytes will not exceed sizeInBytes. + */ + public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes, + @ReadMode int readMode) { + if (mState != STATE_INITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { return ERROR_INVALID_OPERATION; } + if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) { + Log.e(TAG, "AudioRecord.read() called with invalid blocking mode"); + return ERROR_BAD_VALUE; + } + if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0) || (offsetInBytes + sizeInBytes < 0) // detect integer overflow || (offsetInBytes + sizeInBytes > audioData.length)) { return ERROR_BAD_VALUE; } - return native_read_in_byte_array(audioData, offsetInBytes, sizeInBytes); + return native_read_in_byte_array(audioData, offsetInBytes, sizeInBytes, + readMode == READ_BLOCKING); } + /** + * Reads audio data from the audio hardware for recording into a short array. + * The format specified in the AudioRecord constructor should be + * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array. + * @param audioData the array to which the recorded audio data is written. + * @param offsetInShorts index in audioData from which the data is written expressed in shorts. + * @param sizeInShorts the number of requested shorts. + * @return the number of shorts that were read or {@link #ERROR_INVALID_OPERATION} + * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if + * the parameters don't resolve to valid data and indexes. + * The number of shorts will not exceed sizeInShorts. + */ + public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) { + return read(audioData, offsetInShorts, sizeInShorts, READ_BLOCKING); + } /** * Reads audio data from the audio hardware for recording into a short array. @@ -923,23 +966,35 @@ public class AudioRecord * @param audioData the array to which the recorded audio data is written. * @param offsetInShorts index in audioData from which the data is written expressed in shorts. * @param sizeInShorts the number of requested shorts. + * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}. + * <br>With {@link #READ_BLOCKING}, the read will block until all the requested data + * is read. + * <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after + * reading as much audio data as possible without blocking. * @return the number of shorts that were read or {@link #ERROR_INVALID_OPERATION} * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if * the parameters don't resolve to valid data and indexes. * The number of shorts will not exceed sizeInShorts. */ - public int read(short[] audioData, int offsetInShorts, int sizeInShorts) { - if (mState != STATE_INITIALIZED) { + public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts, + @ReadMode int readMode) { + if (mState != STATE_INITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { return ERROR_INVALID_OPERATION; } + if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) { + Log.e(TAG, "AudioRecord.read() called with invalid blocking mode"); + return ERROR_BAD_VALUE; + } + if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0) || (offsetInShorts + sizeInShorts < 0) // detect integer overflow || (offsetInShorts + sizeInShorts > audioData.length)) { return ERROR_BAD_VALUE; } - return native_read_in_short_array(audioData, offsetInShorts, sizeInShorts); + return native_read_in_short_array(audioData, offsetInShorts, sizeInShorts, + readMode == READ_BLOCKING); } /** @@ -950,22 +1005,33 @@ public class AudioRecord * @param offsetInFloats index in audioData from which the data is written. * @param sizeInFloats the number of requested floats. * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}. - * <BR>With {@link #READ_BLOCKING}, the read will block until all the requested data + * <br>With {@link #READ_BLOCKING}, the read will block until all the requested data * is read. - * <BR>With {@link #READ_NON_BLOCKING}, the read will return immediately after + * <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after * reading as much audio data as possible without blocking. * @return the number of floats that were read or {@link #ERROR_INVALID_OPERATION} * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if * the parameters don't resolve to valid data and indexes. * The number of floats will not exceed sizeInFloats. */ - public int read(float[] audioData, int offsetInFloats, int sizeInFloats, + public int read(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats, @ReadMode int readMode) { - if (mState != STATE_INITIALIZED) { + if (mState == STATE_UNINITIALIZED) { + Log.e(TAG, "AudioRecord.read() called in invalid state STATE_UNINITIALIZED"); + return ERROR_INVALID_OPERATION; + } + + if (mAudioFormat != AudioFormat.ENCODING_PCM_FLOAT) { + Log.e(TAG, "AudioRecord.read(float[] ...) requires format ENCODING_PCM_FLOAT"); return ERROR_INVALID_OPERATION; } - if ( (audioData == null) || (offsetInFloats < 0 ) || (sizeInFloats < 0) + if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) { + Log.e(TAG, "AudioRecord.read() called with invalid blocking mode"); + return ERROR_BAD_VALUE; + } + + if ((audioData == null) || (offsetInFloats < 0) || (sizeInFloats < 0) || (offsetInFloats + sizeInFloats < 0) // detect integer overflow || (offsetInFloats + sizeInFloats > audioData.length)) { return ERROR_BAD_VALUE; @@ -992,19 +1058,49 @@ public class AudioRecord * The number of bytes will not exceed sizeInBytes. * The number of bytes read will truncated to be a multiple of the frame size. */ - public int read(ByteBuffer audioBuffer, int sizeInBytes) { + public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes) { + return read(audioBuffer, sizeInBytes, READ_BLOCKING); + } + + /** + * Reads audio data from the audio hardware for recording into a direct buffer. If this buffer + * is not a direct buffer, this method will always return 0. + * Note that the value returned by {@link java.nio.Buffer#position()} on this buffer is + * unchanged after a call to this method. + * The representation of the data in the buffer will depend on the format specified in + * the AudioRecord constructor, and will be native endian. + * @param audioBuffer the direct buffer to which the recorded audio data is written. + * @param sizeInBytes the number of requested bytes. It is recommended but not enforced + * that the number of bytes requested be a multiple of the frame size (sample size in + * bytes multiplied by the channel count). + * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}. + * <br>With {@link #READ_BLOCKING}, the read will block until all the requested data + * is read. + * <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after + * reading as much audio data as possible without blocking. + * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION} + * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if + * the parameters don't resolve to valid data and indexes. + * The number of bytes will not exceed sizeInBytes. + * The number of bytes read will truncated to be a multiple of the frame size. + */ + public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes, @ReadMode int readMode) { if (mState != STATE_INITIALIZED) { return ERROR_INVALID_OPERATION; } + if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) { + Log.e(TAG, "AudioRecord.read() called with invalid blocking mode"); + return ERROR_BAD_VALUE; + } + if ( (audioBuffer == null) || (sizeInBytes < 0) ) { return ERROR_BAD_VALUE; } - return native_read_in_direct_buffer(audioBuffer, sizeInBytes); + return native_read_in_direct_buffer(audioBuffer, sizeInBytes, readMode == READ_BLOCKING); } - //-------------------------------------------------------------------------- // Initialization / configuration //-------------------- @@ -1186,15 +1282,16 @@ public class AudioRecord private native final void native_stop(); private native final int native_read_in_byte_array(byte[] audioData, - int offsetInBytes, int sizeInBytes); + int offsetInBytes, int sizeInBytes, boolean isBlocking); private native final int native_read_in_short_array(short[] audioData, - int offsetInShorts, int sizeInShorts); + int offsetInShorts, int sizeInShorts, boolean isBlocking); private native final int native_read_in_float_array(float[] audioData, int offsetInFloats, int sizeInFloats, boolean isBlocking); - private native final int native_read_in_direct_buffer(Object jBuffer, int sizeInBytes); + private native final int native_read_in_direct_buffer(Object jBuffer, + int sizeInBytes, boolean isBlocking); private native final int native_get_native_frame_count(); diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 6c41a2abbb7b..44455fab97de 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -1540,6 +1540,8 @@ public class AudioTrack /** * Writes the audio data to the audio sink for playback (streaming mode), * or copies audio data for later playback (static buffer mode). + * The format specified in the AudioTrack constructor should be + * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array. * In streaming mode, will block until all data has been written to the audio sink. * In static buffer mode, copies the data to the buffer starting at offset 0. * Note that the actual playback of this data might occur after this function @@ -1556,13 +1558,49 @@ public class AudioTrack * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and * needs to be recreated. */ + public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) { + return write(audioData, offsetInBytes, sizeInBytes, WRITE_BLOCKING); + } - public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) { + /** + * Writes the audio data to the audio sink for playback (streaming mode), + * or copies audio data for later playback (static buffer mode). + * The format specified in the AudioTrack constructor should be + * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array. + * In streaming mode, will block until all data has been written to the audio sink. + * In static buffer mode, copies the data to the buffer starting at offset 0. + * Note that the actual playback of this data might occur after this function + * returns. This function is thread safe with respect to {@link #stop} calls, + * in which case all of the specified data might not be written to the audio sink. + * + * @param audioData the array that holds the data to play. + * @param offsetInBytes the offset expressed in bytes in audioData where the data to play + * starts. + * @param sizeInBytes the number of bytes to read in audioData after the offset. + * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no + * effect in static mode. + * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written + * to the audio sink. + * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after + * queuing as much audio data for playback as possible without blocking. + * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION} + * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if + * the parameters don't resolve to valid data and indexes, or + * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and + * needs to be recreated. + */ + public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes, + @WriteMode int writeMode) { if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { return ERROR_INVALID_OPERATION; } + if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { + Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); + return ERROR_BAD_VALUE; + } + if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0) || (offsetInBytes + sizeInBytes < 0) // detect integer overflow || (offsetInBytes + sizeInBytes > audioData.length)) { @@ -1570,7 +1608,7 @@ public class AudioTrack } int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat, - true /*isBlocking*/); + writeMode == WRITE_BLOCKING); if ((mDataLoadMode == MODE_STATIC) && (mState == STATE_NO_STATIC_DATA) @@ -1582,10 +1620,11 @@ public class AudioTrack return ret; } - /** * Writes the audio data to the audio sink for playback (streaming mode), * or copies audio data for later playback (static buffer mode). + * The format specified in the AudioTrack constructor should be + * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array. * In streaming mode, will block until all data has been written to the audio sink. * In static buffer mode, copies the data to the buffer starting at offset 0. * Note that the actual playback of this data might occur after this function @@ -1602,20 +1641,57 @@ public class AudioTrack * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and * needs to be recreated. */ + public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) { + return write(audioData, offsetInShorts, sizeInShorts, WRITE_BLOCKING); + } - public int write(short[] audioData, int offsetInShorts, int sizeInShorts) { + /** + * Writes the audio data to the audio sink for playback (streaming mode), + * or copies audio data for later playback (static buffer mode). + * The format specified in the AudioTrack constructor should be + * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array. + * In streaming mode, will block until all data has been written to the audio sink. + * In static buffer mode, copies the data to the buffer starting at offset 0. + * Note that the actual playback of this data might occur after this function + * returns. This function is thread safe with respect to {@link #stop} calls, + * in which case all of the specified data might not be written to the audio sink. + * + * @param audioData the array that holds the data to play. + * @param offsetInShorts the offset expressed in shorts in audioData where the data to play + * starts. + * @param sizeInShorts the number of shorts to read in audioData after the offset. + * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no + * effect in static mode. + * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written + * to the audio sink. + * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after + * queuing as much audio data for playback as possible without blocking. + * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION} + * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if + * the parameters don't resolve to valid data and indexes, or + * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and + * needs to be recreated. + */ + public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts, + @WriteMode int writeMode) { if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { return ERROR_INVALID_OPERATION; } + if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { + Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); + return ERROR_BAD_VALUE; + } + if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0) || (offsetInShorts + sizeInShorts < 0) // detect integer overflow || (offsetInShorts + sizeInShorts > audioData.length)) { return ERROR_BAD_VALUE; } - int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat); + int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat, + writeMode == WRITE_BLOCKING); if ((mDataLoadMode == MODE_STATIC) && (mState == STATE_NO_STATIC_DATA) @@ -1627,10 +1703,11 @@ public class AudioTrack return ret; } - /** * Writes the audio data to the audio sink for playback (streaming mode), * or copies audio data for later playback (static buffer mode). + * The format specified in the AudioTrack constructor should be + * {@link AudioFormat#ENCODING_PCM_FLOAT} to correspond to the data in the array. * In static buffer mode, copies the data to the buffer starting at offset 0, * and the write mode is ignored. * In streaming mode, the blocking behavior will depend on the write mode. @@ -1654,9 +1731,9 @@ public class AudioTrack * @param sizeInFloats the number of floats to read in audioData after the offset. * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no * effect in static mode. - * <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written + * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written * to the audio sink. - * <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after + * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after * queuing as much audio data for playback as possible without blocking. * @return the number of floats that were written, or {@link #ERROR_INVALID_OPERATION} * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if @@ -1664,7 +1741,7 @@ public class AudioTrack * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and * needs to be recreated. */ - public int write(float[] audioData, int offsetInFloats, int sizeInFloats, + public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats, @WriteMode int writeMode) { if (mState == STATE_UNINITIALIZED) { @@ -1727,7 +1804,7 @@ public class AudioTrack * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and * needs to be recreated. */ - public int write(ByteBuffer audioData, int sizeInBytes, + public int write(@NonNull ByteBuffer audioData, int sizeInBytes, @WriteMode int writeMode) { if (mState == STATE_UNINITIALIZED) { @@ -2017,7 +2094,8 @@ public class AudioTrack boolean isBlocking); private native final int native_write_short(short[] audioData, - int offsetInShorts, int sizeInShorts, int format); + int offsetInShorts, int sizeInShorts, int format, + boolean isBlocking); private native final int native_write_float(float[] audioData, int offsetInFloats, int sizeInFloats, int format, diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index c227eb7fd276..a046512ef1cb 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -18,6 +18,7 @@ package android.media; import android.Manifest; import android.annotation.DrawableRes; +import android.annotation.NonNull; import android.app.ActivityThread; import android.content.BroadcastReceiver; import android.content.Context; @@ -882,8 +883,12 @@ public class MediaRouter { * @param types type flags indicating which types this route should be used for. * The route must support at least a subset. * @param route Route to select + * @throws IllegalArgumentException if the given route is {@code null} */ - public void selectRoute(int types, RouteInfo route) { + public void selectRoute(int types, @NonNull RouteInfo route) { + if (route == null) { + throw new IllegalArgumentException("Route cannot be null."); + } selectRouteStatic(types, route, true); } @@ -894,7 +899,8 @@ public class MediaRouter { selectRouteStatic(types, route, explicit); } - static void selectRouteStatic(int types, RouteInfo route, boolean explicit) { + static void selectRouteStatic(int types, @NonNull RouteInfo route, boolean explicit) { + assert(route != null); final RouteInfo oldRoute = sStatic.mSelectedRoute; if (oldRoute == route) return; if (!route.matchesTypes(types)) { @@ -917,7 +923,7 @@ public class MediaRouter { final WifiDisplay activeDisplay = sStatic.mDisplayService.getWifiDisplayStatus().getActiveDisplay(); final boolean oldRouteHasAddress = oldRoute != null && oldRoute.mDeviceAddress != null; - final boolean newRouteHasAddress = route != null && route.mDeviceAddress != null; + final boolean newRouteHasAddress = route.mDeviceAddress != null; if (activeDisplay != null || oldRouteHasAddress || newRouteHasAddress) { if (newRouteHasAddress && !matchesDeviceAddress(activeDisplay, route)) { if (sStatic.mCanConfigureWifiDisplays) { diff --git a/media/jni/Android.mk b/media/jni/Android.mk index c8464c7664c2..8cf98747a9ba 100644 --- a/media/jni/Android.mk +++ b/media/jni/Android.mk @@ -43,7 +43,7 @@ LOCAL_SHARED_LIBRARIES := \ libusbhost \ libjhead \ libexif \ - libstagefright_amrnb_common + libstagefright_amrnb_common \ LOCAL_REQUIRED_MODULES := \ libjhead_jni @@ -55,7 +55,6 @@ LOCAL_C_INCLUDES += \ external/libexif/ \ external/tremor/Tremor \ frameworks/base/core/jni \ - frameworks/base/libs/hwui \ frameworks/av/media/libmedia \ frameworks/av/media/libstagefright \ frameworks/av/media/libstagefright/codecs/amrnb/enc/src \ diff --git a/native/graphics/jni/Android.mk b/native/graphics/jni/Android.mk index f89a5af42058..91c9ac621be4 100644 --- a/native/graphics/jni/Android.mk +++ b/native/graphics/jni/Android.mk @@ -24,8 +24,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_C_INCLUDES += \ frameworks/base/native/include \ - frameworks/base/core/jni/android/graphics \ - frameworks/base/libs/hwui + frameworks/base/core/jni/android/graphics LOCAL_MODULE:= libjnigraphics diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index f16fb5cd2f34..b828e78a8c57 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -171,6 +171,11 @@ public class KeyguardViewMediator extends SystemUI { */ private static final String KEYGUARD_ANALYTICS_SETTING = "keyguard_analytics"; + /** + * How much faster we collapse the lockscreen when authenticating with fingerprint. + */ + private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.3f; + /** The stream type that the lock sounds are tied to. */ private int mUiSoundsStreamType; @@ -441,7 +446,8 @@ public class KeyguardViewMediator extends SystemUI { if (mStatusBarKeyguardViewManager.isBouncerShowing()) { mViewMediatorCallback.keyguardDone(true); } else { - mStatusBarKeyguardViewManager.animateCollapsePanels(); + mStatusBarKeyguardViewManager.animateCollapsePanels( + FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 9f86475fd126..de4874f31285 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -687,13 +687,7 @@ public abstract class BaseStatusBar extends SystemUI implements setHeadsUpUser(newUserId); } - private void setHeadsUpUser(int newUserId) { - mHeadsUpManager.setUser(newUserId); - } - - public boolean isHeadsUp(String key) { - return mHeadsUpManager.isHeadsUp(key); - } + protected abstract void setHeadsUpUser(int newUserId); @Override // NotificationData.Environment public boolean isNotificationForCurrentProfiles(StatusBarNotification n) { @@ -1578,7 +1572,7 @@ public abstract class BaseStatusBar extends SystemUI implements mCurrentUserId); dismissKeyguardThenExecute(new OnDismissAction() { public boolean onDismiss() { - if (mHeadsUpManager.isHeadsUp(mNotificationKey)) { + if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(mNotificationKey)) { // Release the HUN notification to the shade. // // In most cases, when FLAG_AUTO_CANCEL is set, the notification will @@ -1941,20 +1935,8 @@ public abstract class BaseStatusBar extends SystemUI implements setAreThereNotifications(); } - private void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt, - boolean alertAgain) { - final boolean wasHeadsUp = isHeadsUp(key); - if (wasHeadsUp) { - mHeadsUpManager.updateNotification(entry, alertAgain); - if (!shouldInterrupt) { - // We don't want this to be interrupting anymore, lets remove it - mHeadsUpManager.removeNotification(key); - } - } else if (shouldInterrupt && alertAgain) { - // This notification was updated to be a heads-up, show it! - mHeadsUpManager.showNotification(entry); - } - } + protected abstract void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt, + boolean alertAgain); private void logUpdate(Entry oldEntry, Notification n) { StatusBarNotification oldNotification = oldEntry.notification; @@ -2075,7 +2057,7 @@ public abstract class BaseStatusBar extends SystemUI implements return false; } - if (mHeadsUpManager.isSnoozed(sbn.getPackageName())) { + if (isSnoozedPackage(sbn)) { return false; } @@ -2109,6 +2091,8 @@ public abstract class BaseStatusBar extends SystemUI implements return interrupt; } + protected abstract boolean isSnoozedPackage(StatusBarNotification sbn); + public void setInteracting(int barWindow, boolean interacting) { // hook for subclasses } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index c2664679d9e5..96e95439c7ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -511,9 +511,10 @@ public class NotificationPanelView extends PanelView implements } @Override - protected void flingToHeight(float vel, boolean expand, float target) { + protected void flingToHeight(float vel, boolean expand, float target, + float collapseSpeedUpFactor) { mHeadsUpTouchHelper.notifyFling(!expand); - super.flingToHeight(vel, expand, target); + super.flingToHeight(vel, expand, target, collapseSpeedUpFactor); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index 240438a74394..f3d4c7f83d41 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -140,7 +140,7 @@ public class PanelBar extends FrameLayout { mPanelHolder.setSelectedPanel(mTouchingPanel); for (PanelView pv : mPanels) { if (pv != panel) { - pv.collapse(false /* delayed */); + pv.collapse(false /* delayed */, 1.0f /* speedUpFactor */); } } } @@ -186,11 +186,11 @@ public class PanelBar extends FrameLayout { (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":""); } - public void collapseAllPanels(boolean animate, boolean delayed) { + public void collapseAllPanels(boolean animate, boolean delayed, float speedUpFactor) { boolean waiting = false; for (PanelView pv : mPanels) { if (animate && !pv.isFullyCollapsed()) { - pv.collapse(delayed); + pv.collapse(delayed, speedUpFactor); waiting = true; } else { pv.resetViews(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index ddce9d51dec0..3a30429a5a4f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -101,6 +101,12 @@ public abstract class PanelView extends FrameLayout { private boolean mPeekPending; private boolean mCollapseAfterPeek; + + /** + * Speed-up factor to be used when {@link #mFlingCollapseRunnable} runs the next time. + */ + private float mNextCollapseSpeedUpFactor = 1.0f; + private boolean mExpanding; private boolean mGestureWaitForTouchSlop; private Runnable mPeekRunnable = new Runnable() { @@ -164,7 +170,7 @@ public abstract class PanelView extends FrameLayout { postOnAnimation(new Runnable() { @Override public void run() { - collapse(false /* delayed */); + collapse(false /* delayed */, 1.0f /* speedUpFactor */); } }); } @@ -563,12 +569,17 @@ public abstract class PanelView extends FrameLayout { } protected void fling(float vel, boolean expand) { + fling(vel, expand, 1.0f /* collapseSpeedUpFactor */); + } + + protected void fling(float vel, boolean expand, float collapseSpeedUpFactor) { cancelPeek(); float target = expand ? getMaxPanelHeight() : 0.0f; - flingToHeight(vel, expand, target); + flingToHeight(vel, expand, target, collapseSpeedUpFactor); } - protected void flingToHeight(float vel, boolean expand, float target) { + protected void flingToHeight(float vel, boolean expand, float target, + float collapseSpeedUpFactor) { // Hack to make the expand transition look nice when clear all button is visible - we make // the animation only to the last notification, and then jump to the maximum panel height so // clear all just fades in and the decelerating motion is towards the last notification. @@ -600,7 +611,8 @@ public abstract class PanelView extends FrameLayout { // Make it shorter if we run a canned animation if (vel == 0) { animator.setDuration((long) - (animator.getDuration() * getCannedFlingDurationFactor())); + (animator.getDuration() * getCannedFlingDurationFactor() + / collapseSpeedUpFactor)); } } animator.addListener(new AnimatorListenerAdapter() { @@ -745,7 +757,7 @@ public abstract class PanelView extends FrameLayout { mBar = panelBar; } - public void collapse(boolean delayed) { + public void collapse(boolean delayed, float speedUpFactor) { if (DEBUG) logf("collapse: " + this); if (mPeekPending || mPeekAnimator != null) { mCollapseAfterPeek = true; @@ -761,9 +773,10 @@ public abstract class PanelView extends FrameLayout { mClosing = true; notifyExpandingStarted(); if (delayed) { + mNextCollapseSpeedUpFactor = speedUpFactor; postDelayed(mFlingCollapseRunnable, 120); } else { - fling(0, false /* expand */); + fling(0, false /* expand */, speedUpFactor); } } } @@ -771,7 +784,7 @@ public abstract class PanelView extends FrameLayout { private final Runnable mFlingCollapseRunnable = new Runnable() { @Override public void run() { - fling(0, false /* expand */); + fling(0, false /* expand */, mNextCollapseSpeedUpFactor); } }; @@ -975,7 +988,7 @@ public abstract class PanelView extends FrameLayout { protected final Runnable mPostCollapseRunnable = new Runnable() { @Override public void run() { - collapse(false /* delayed */); + collapse(false /* delayed */, 1.0f /* speedUpFactor */); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index a5dad923b776..b6dbfceb8e2d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1867,6 +1867,35 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } + protected void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt, + boolean alertAgain) { + final boolean wasHeadsUp = isHeadsUp(key); + if (wasHeadsUp) { + mHeadsUpManager.updateNotification(entry, alertAgain); + if (!shouldInterrupt) { + // We don't want this to be interrupting anymore, lets remove it + mHeadsUpManager.removeNotification(key); + } + } else if (shouldInterrupt && alertAgain) { + // This notification was updated to be a heads-up, show it! + mHeadsUpManager.showNotification(entry); + } + } + + protected void setHeadsUpUser(int newUserId) { + if (mHeadsUpManager != null) { + mHeadsUpManager.setUser(newUserId); + } + } + + public boolean isHeadsUp(String key) { + return mHeadsUpManager.isHeadsUp(key); + } + + protected boolean isSnoozedPackage(StatusBarNotification sbn) { + return mHeadsUpManager.isSnoozed(sbn.getPackageName()); + } + /** * All changes to the status bar and notifications funnel through here and are batched. */ @@ -1952,14 +1981,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void animateCollapsePanels(int flags) { - animateCollapsePanels(flags, false /* force */, false /* delayed */); + animateCollapsePanels(flags, false /* force */, false /* delayed */, + 1.0f /* speedUpFactor */); } public void animateCollapsePanels(int flags, boolean force) { - animateCollapsePanels(flags, force, false /* delayed*/); + animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */); } public void animateCollapsePanels(int flags, boolean force, boolean delayed) { + animateCollapsePanels(flags, force, delayed, 1.0f /* speedUpFactor */); + } + + public void animateCollapsePanels(int flags, boolean force, boolean delayed, + float speedUpFactor) { if (!force && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) { runPostCollapseRunnables(); @@ -1983,7 +2018,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarWindowManager.setStatusBarFocusable(false); mStatusBarWindow.cancelExpandHelper(); - mStatusBarView.collapseAllPanels(true /* animate */, delayed); + mStatusBarView.collapseAllPanels(true /* animate */, delayed, speedUpFactor); } } @@ -2026,7 +2061,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void animateCollapseQuickSettings() { if (mState == StatusBarState.SHADE) { - mStatusBarView.collapseAllPanels(true, false /* delayed */); + mStatusBarView.collapseAllPanels(true, false /* delayed */, 1.0f /* speedUpFactor */); } } @@ -2039,7 +2074,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) - mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/); + mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/, + 1.0f /* speedUpFactor */); mNotificationPanel.closeQs(); @@ -2129,7 +2165,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarWindowState = state; if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state)); if (!showing && mState == StatusBarState.SHADE) { - mStatusBarView.collapseAllPanels(false /* animate */, false /* delayed */); + mStatusBarView.collapseAllPanels(false /* animate */, false /* delayed */, + 1.0f /* speedUpFactor */); } } if (mNavigationBarView != null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 6369d5e57f67..194a19afabb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -441,7 +441,8 @@ public class StatusBarKeyguardViewManager { mPhoneStatusBar.keyguardGoingAway(); } - public void animateCollapsePanels() { - mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); + public void animateCollapsePanels(float speedUpFactor) { + mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */, + false /* delayed */, speedUpFactor); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java index 78122d6be664..dce695d67b43 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java @@ -20,8 +20,6 @@ import android.os.IBinder; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.view.WindowManager; import com.android.internal.statusbar.StatusBarIcon; import com.android.systemui.statusbar.ActivatableNotificationView; @@ -166,4 +164,17 @@ public class TvStatusBar extends BaseStatusBar { @Override public void appTransitionStarting(long startTime, long duration) { } + + @Override + protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldInterrupt, + boolean alertAgain) { + } + + @Override + protected void setHeadsUpUser(int newUserId) { + } + + protected boolean isSnoozedPackage(StatusBarNotification sbn) { + return false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java index 818f5ee6f985..4a441c7bf351 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java +++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java @@ -107,8 +107,8 @@ public class StorageNotification extends SystemUI { case VolumeInfo.STATE_UNMOUNTED: onVolumeUnmounted(vol); break; - case VolumeInfo.STATE_MOUNTING: - onVolumeMounting(vol); + case VolumeInfo.STATE_CHECKING: + onVolumeChecking(vol); break; case VolumeInfo.STATE_MOUNTED: onVolumeMounted(vol); @@ -116,8 +116,8 @@ public class StorageNotification extends SystemUI { case VolumeInfo.STATE_FORMATTING: onVolumeFormatting(vol); break; - case VolumeInfo.STATE_UNMOUNTING: - onVolumeUnmounting(vol); + case VolumeInfo.STATE_EJECTING: + onVolumeEjecting(vol); break; case VolumeInfo.STATE_UNMOUNTABLE: onVolumeUnmountable(vol); @@ -125,6 +125,9 @@ public class StorageNotification extends SystemUI { case VolumeInfo.STATE_REMOVED: onVolumeRemoved(vol); break; + case VolumeInfo.STATE_BAD_REMOVAL: + onVolumeBadRemoval(vol); + break; } } @@ -132,7 +135,7 @@ public class StorageNotification extends SystemUI { // Ignored } - private void onVolumeMounting(VolumeInfo vol) { + private void onVolumeChecking(VolumeInfo vol) { final DiskInfo disk = mStorageManager.findDiskById(vol.getDiskId()); final CharSequence title = mContext.getString( R.string.ext_media_checking_notification_title, disk.getDescription()); @@ -194,7 +197,7 @@ public class StorageNotification extends SystemUI { // Ignored } - private void onVolumeUnmounting(VolumeInfo vol) { + private void onVolumeEjecting(VolumeInfo vol) { final DiskInfo disk = mStorageManager.findDiskById(vol.getDiskId()); final CharSequence title = mContext.getString( R.string.ext_media_unmounting_notification_title, disk.getDescription()); @@ -247,6 +250,26 @@ public class StorageNotification extends SystemUI { mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL); } + private void onVolumeBadRemoval(VolumeInfo vol) { + if (!vol.isPrimary()) { + // Ignore non-primary media + return; + } + + final DiskInfo disk = mStorageManager.findDiskById(vol.getDiskId()); + final CharSequence title = mContext.getString( + R.string.ext_media_badremoval_notification_title, disk.getDescription()); + final CharSequence text = mContext.getString( + R.string.ext_media_badremoval_notification_message, disk.getDescription()); + + final Notification notif = buildNotificationBuilder(title, text) + .setSmallIcon(R.drawable.stat_notify_sdcard) + .setCategory(Notification.CATEGORY_ERROR) + .build(); + + mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL); + } + private Notification.Builder buildNotificationBuilder(CharSequence title, CharSequence text) { return new Notification.Builder(mContext) .setColor(mContext.getColor(R.color.system_notification_accent_color)) diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk index 0658620534d8..94f08595746c 100644 --- a/rs/jni/Android.mk +++ b/rs/jni/Android.mk @@ -25,7 +25,6 @@ LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ frameworks/rs \ frameworks/base/core/jni \ - frameworks/base/libs/hwui \ $(rs_generated_include_dir) LOCAL_CFLAGS += -Wno-unused-parameter -std=c++11 diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java index 26f4232ff835..66cc29ad3795 100644 --- a/services/core/java/com/android/server/AssetAtlasService.java +++ b/services/core/java/com/android/server/AssetAtlasService.java @@ -199,6 +199,11 @@ public class AssetAtlasService extends IAssetAtlas.Stub { private final ArrayList<Bitmap> mBitmaps; private final int mPixelCount; + private long mNativeBitmap; + + // Used for debugging only + private Bitmap mAtlasBitmap; + Renderer(ArrayList<Bitmap> bitmaps, int pixelCount) { mBitmaps = bitmaps; mPixelCount = pixelCount; @@ -253,9 +258,8 @@ public class AssetAtlasService extends IAssetAtlas.Stub { // We always render the atlas into a bitmap. This bitmap is then // uploaded into the GraphicBuffer using OpenGL to swizzle the content - final Bitmap atlasBitmap = Bitmap.createBitmap( - buffer.getWidth(), buffer.getHeight(), Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(atlasBitmap); + final Canvas canvas = acquireCanvas(buffer.getWidth(), buffer.getHeight()); + if (canvas == null) return false; final Atlas.Entry entry = new Atlas.Entry(); @@ -264,78 +268,108 @@ public class AssetAtlasService extends IAssetAtlas.Stub { int mapIndex = 0; boolean result = false; - final long startRender = System.nanoTime(); - final int count = mBitmaps.size(); + try { + final long startRender = System.nanoTime(); + final int count = mBitmaps.size(); + + for (int i = 0; i < count; i++) { + final Bitmap bitmap = mBitmaps.get(i); + if (atlas.pack(bitmap.getWidth(), bitmap.getHeight(), entry) != null) { + // We have more bitmaps to pack than the current configuration + // says, we were most likely not able to detect a change in the + // list of preloaded drawables, abort and delete the configuration + if (mapIndex >= mAtlasMap.length) { + deleteDataFile(); + break; + } - for (int i = 0; i < count; i++) { - final Bitmap bitmap = mBitmaps.get(i); - if (atlas.pack(bitmap.getWidth(), bitmap.getHeight(), entry) != null) { - // We have more bitmaps to pack than the current configuration - // says, we were most likely not able to detect a change in the - // list of preloaded drawables, abort and delete the configuration - if (mapIndex >= mAtlasMap.length) { - deleteDataFile(); - break; + canvas.save(); + canvas.translate(entry.x, entry.y); + if (entry.rotated) { + canvas.translate(bitmap.getHeight(), 0.0f); + canvas.rotate(90.0f); + } + canvas.drawBitmap(bitmap, 0.0f, 0.0f, null); + canvas.restore(); + atlasMap[mapIndex++] = bitmap.getSkBitmap(); + atlasMap[mapIndex++] = entry.x; + atlasMap[mapIndex++] = entry.y; + atlasMap[mapIndex++] = entry.rotated ? 1 : 0; } + } - canvas.save(); - canvas.translate(entry.x, entry.y); - if (entry.rotated) { - canvas.translate(bitmap.getHeight(), 0.0f); - canvas.rotate(90.0f); - } - canvas.drawBitmap(bitmap, 0.0f, 0.0f, null); - canvas.restore(); - atlasMap[mapIndex++] = bitmap.refSkPixelRef(); - atlasMap[mapIndex++] = entry.x; - atlasMap[mapIndex++] = entry.y; - atlasMap[mapIndex++] = entry.rotated ? 1 : 0; + final long endRender = System.nanoTime(); + if (mNativeBitmap != 0) { + result = nUploadAtlas(buffer, mNativeBitmap); + } + + final long endUpload = System.nanoTime(); + if (DEBUG_ATLAS) { + float renderDuration = (endRender - startRender) / 1000.0f / 1000.0f; + float uploadDuration = (endUpload - endRender) / 1000.0f / 1000.0f; + Log.d(LOG_TAG, String.format("Rendered atlas in %.2fms (%.2f+%.2fms)", + renderDuration + uploadDuration, renderDuration, uploadDuration)); } - } - final long endRender = System.nanoTime(); - releaseCanvas(canvas, atlasBitmap); - result = nUploadAtlas(buffer, atlasBitmap); - atlasBitmap.recycle(); - final long endUpload = System.nanoTime(); - - if (DEBUG_ATLAS) { - float renderDuration = (endRender - startRender) / 1000.0f / 1000.0f; - float uploadDuration = (endUpload - endRender) / 1000.0f / 1000.0f; - Log.d(LOG_TAG, String.format("Rendered atlas in %.2fms (%.2f+%.2fms)", - renderDuration + uploadDuration, renderDuration, uploadDuration)); + } finally { + releaseCanvas(canvas); } return result; } /** + * Returns a Canvas for the specified buffer. If {@link #DEBUG_ATLAS_TEXTURE} + * is turned on, the returned Canvas will render into a local bitmap that + * will then be saved out to disk for debugging purposes. + * @param width + * @param height + */ + private Canvas acquireCanvas(int width, int height) { + if (DEBUG_ATLAS_TEXTURE) { + mAtlasBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + return new Canvas(mAtlasBitmap); + } else { + Canvas canvas = new Canvas(); + mNativeBitmap = nAcquireAtlasCanvas(canvas, width, height); + return canvas; + } + } + + /** * Releases the canvas used to render into the buffer. Calling this method * will release any resource previously acquired. If {@link #DEBUG_ATLAS_TEXTURE} * is turend on, calling this method will write the content of the atlas * to disk in /data/system/atlas.png for debugging. */ - private void releaseCanvas(Canvas canvas, Bitmap atlasBitmap) { - canvas.setBitmap(null); + private void releaseCanvas(Canvas canvas) { if (DEBUG_ATLAS_TEXTURE) { + canvas.setBitmap(null); File systemDirectory = new File(Environment.getDataDirectory(), "system"); File dataFile = new File(systemDirectory, "atlas.png"); try { FileOutputStream out = new FileOutputStream(dataFile); - atlasBitmap.compress(Bitmap.CompressFormat.PNG, 100, out); + mAtlasBitmap.compress(Bitmap.CompressFormat.PNG, 100, out); out.close(); } catch (FileNotFoundException e) { // Ignore } catch (IOException e) { // Ignore } + + mAtlasBitmap.recycle(); + mAtlasBitmap = null; + } else { + nReleaseAtlasCanvas(canvas, mNativeBitmap); } } } - private static native boolean nUploadAtlas(GraphicBuffer buffer, Bitmap bitmap); + private static native long nAcquireAtlasCanvas(Canvas canvas, int width, int height); + private static native void nReleaseAtlasCanvas(Canvas canvas, long bitmap); + private static native boolean nUploadAtlas(GraphicBuffer buffer, long bitmap); @Override public boolean isCompatible(int ppid) { diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index 16689eed5f12..a31a1a7003f8 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -134,7 +134,11 @@ public class LockSettingsService extends ILockSettings.Stub { public void systemReady() { migrateOldData(); - getGateKeeperService(); + try { + getGateKeeperService(); + } catch (RemoteException e) { + Slog.e(TAG, "Failure retrieving IGateKeeperService", e); + } mStorage.prefetchUser(UserHandle.USER_OWNER); } @@ -695,7 +699,16 @@ public class LockSettingsService extends ILockSettings.Stub { return null; } - private synchronized IGateKeeperService getGateKeeperService() { + private class GateKeeperDiedRecipient implements IBinder.DeathRecipient { + @Override + public void binderDied() { + mGateKeeperService.asBinder().unlinkToDeath(this, 0); + mGateKeeperService = null; + } + } + + private synchronized IGateKeeperService getGateKeeperService() + throws RemoteException { if (mGateKeeperService != null) { return mGateKeeperService; } @@ -703,6 +716,7 @@ public class LockSettingsService extends ILockSettings.Stub { final IBinder service = ServiceManager.getService("android.service.gatekeeper.IGateKeeperService"); if (service != null) { + service.linkToDeath(new GateKeeperDiedRecipient(), 0); mGateKeeperService = IGateKeeperService.Stub.asInterface(service); return mGateKeeperService; } diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java index 94096152670d..e0352e091af7 100644 --- a/services/core/java/com/android/server/MmsServiceBroker.java +++ b/services/core/java/com/android/server/MmsServiceBroker.java @@ -372,7 +372,6 @@ public class MmsServiceBroker extends SystemService { @Override public Uri importTextMessage(String callingPkg, String address, int type, String text, long timestampMillis, boolean seen, boolean read) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Import SMS message"); if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(), callingPkg) != AppOpsManager.MODE_ALLOWED) { // Silently fail AppOps failure due to not being the default SMS app @@ -387,7 +386,6 @@ public class MmsServiceBroker extends SystemService { public Uri importMultimediaMessage(String callingPkg, Uri contentUri, String messageId, long timestampSecs, boolean seen, boolean read) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Import MMS message"); if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(), callingPkg) != AppOpsManager.MODE_ALLOWED) { // Silently fail AppOps failure due to not being the default SMS app @@ -401,8 +399,6 @@ public class MmsServiceBroker extends SystemService { @Override public boolean deleteStoredMessage(String callingPkg, Uri messageUri) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, - "Delete SMS/MMS message"); if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(), callingPkg) != AppOpsManager.MODE_ALLOWED) { return false; @@ -413,7 +409,6 @@ public class MmsServiceBroker extends SystemService { @Override public boolean deleteStoredConversation(String callingPkg, long conversationId) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Delete conversation"); if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(), callingPkg) != AppOpsManager.MODE_ALLOWED) { return false; @@ -424,8 +419,10 @@ public class MmsServiceBroker extends SystemService { @Override public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri, ContentValues statusValues) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, - "Update SMS/MMS message"); + if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(), + callingPkg) != AppOpsManager.MODE_ALLOWED) { + return false; + } return getServiceGuarded() .updateStoredMessageStatus(callingPkg, messageUri, statusValues); } @@ -433,8 +430,10 @@ public class MmsServiceBroker extends SystemService { @Override public boolean archiveStoredConversation(String callingPkg, long conversationId, boolean archived) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, - "Update SMS/MMS message"); + if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(), + callingPkg) != AppOpsManager.MODE_ALLOWED) { + return false; + } return getServiceGuarded() .archiveStoredConversation(callingPkg, conversationId, archived); } @@ -442,7 +441,6 @@ public class MmsServiceBroker extends SystemService { @Override public Uri addTextMessageDraft(String callingPkg, String address, String text) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Add SMS draft"); if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(), callingPkg) != AppOpsManager.MODE_ALLOWED) { // Silently fail AppOps failure due to not being the default SMS app @@ -455,7 +453,6 @@ public class MmsServiceBroker extends SystemService { @Override public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Add MMS draft"); if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(), callingPkg) != AppOpsManager.MODE_ALLOWED) { // Silently fail AppOps failure due to not being the default SMS app @@ -468,8 +465,6 @@ public class MmsServiceBroker extends SystemService { @Override public void sendStoredMessage(int subId, String callingPkg, Uri messageUri, Bundle configOverrides, PendingIntent sentIntent) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, - "Send stored MMS message"); if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPkg) != AppOpsManager.MODE_ALLOWED) { return; @@ -480,7 +475,6 @@ public class MmsServiceBroker extends SystemService { @Override public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException { - mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Set auto persist"); if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(), callingPkg) != AppOpsManager.MODE_ALLOWED) { return; diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 4c937f74067b..34a955998624 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -61,6 +61,7 @@ import android.os.storage.StorageResultCode; import android.os.storage.StorageVolume; import android.os.storage.VolumeInfo; import android.text.TextUtils; +import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.DebugUtils; @@ -102,6 +103,7 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -214,8 +216,7 @@ class MountService extends IMountService.Stub public static final int DISK_CREATED = 640; public static final int DISK_SIZE_CHANGED = 641; public static final int DISK_LABEL_CHANGED = 642; - public static final int DISK_VOLUME_CREATED = 643; - public static final int DISK_VOLUME_DESTROYED = 644; + public static final int DISK_UNSUPPORTED = 643; public static final int DISK_DESTROYED = 649; public static final int VOLUME_CREATED = 650; @@ -533,7 +534,11 @@ class MountService extends IMountService.Stub break; } case H_FSTRIM: { - waitForReady(); + if (!isReady()) { + Slog.i(TAG, "fstrim requested, but no daemon connection yet; trying again"); + sendMessageDelayed(obtainMessage(H_FSTRIM), DateUtils.SECOND_IN_MILLIS); + } + Slog.i(TAG, "Running fstrim idle maintenance"); // Remember when we kicked it off @@ -578,7 +583,8 @@ class MountService extends IMountService.Stub case H_VOLUME_MOUNT: { final VolumeInfo vol = (VolumeInfo) msg.obj; try { - mConnector.execute("volume", "mount", vol.id, vol.flags, vol.userId); + mConnector.execute("volume", "mount", vol.id, vol.mountFlags, + vol.mountUserId); } catch (NativeDaemonConnectorException ignored) { } break; @@ -653,7 +659,7 @@ class MountService extends IMountService.Stub // Create a stub volume that represents internal storage final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL, - VolumeInfo.TYPE_PRIVATE, 0); + VolumeInfo.TYPE_PRIVATE, null, 0); internal.state = VolumeInfo.STATE_MOUNTED; internal.path = Environment.getDataDirectory().getAbsolutePath(); mVolumes.put(internal.id, internal); @@ -821,34 +827,15 @@ class MountService extends IMountService.Stub if (disk != null) { disk.label = cooked[2]; } - break; - } - case VoldResponseCode.DISK_VOLUME_CREATED: { - if (cooked.length != 3) break; - final String diskId = cooked[1]; - final String volId = cooked[2]; - final DiskInfo disk = mDisks.get(diskId); - if (disk != null) { - disk.volumeIds = ArrayUtils.appendElement(String.class, disk.volumeIds, volId); - } - final VolumeInfo vol = mVolumes.get(volId); - if (vol != null) { - vol.diskId = diskId; + if (disk.label != null) { + disk.label = disk.label.trim(); } break; } - case VoldResponseCode.DISK_VOLUME_DESTROYED: { - if (cooked.length != 3) break; - final String diskId = cooked[1]; - final String volId = cooked[2]; - final DiskInfo disk = mDisks.get(diskId); - if (disk != null) { - disk.volumeIds = ArrayUtils.removeElement(String.class, disk.volumeIds, volId); - } - final VolumeInfo vol = mVolumes.get(volId); - if (vol != null) { - vol.diskId = null; - } + case VoldResponseCode.DISK_UNSUPPORTED: { + if (cooked.length != 2) break; + final DiskInfo disk = mDisks.get(cooked[1]); + mCallbacks.notifyDiskUnsupported(disk); break; } case VoldResponseCode.DISK_DESTROYED: { @@ -858,11 +845,11 @@ class MountService extends IMountService.Stub } case VoldResponseCode.VOLUME_CREATED: { - if (cooked.length != 3) break; final String id = cooked[1]; final int type = Integer.parseInt(cooked[2]); + final String diskId = (cooked.length == 4) ? cooked[3] : null; final int mtpIndex = allocateMtpIndex(id); - final VolumeInfo vol = new VolumeInfo(id, type, mtpIndex); + final VolumeInfo vol = new VolumeInfo(id, type, diskId, mtpIndex); mVolumes.put(id, vol); onVolumeCreatedLocked(vol); break; @@ -937,16 +924,24 @@ class MountService extends IMountService.Stub StorageManager.PROP_PRIMARY_PHYSICAL, false); // TODO: enable switching to another emulated primary if (VolumeInfo.ID_EMULATED_INTERNAL.equals(vol.id) && !primaryPhysical) { - vol.flags |= VolumeInfo.FLAG_PRIMARY; - vol.flags |= VolumeInfo.FLAG_VISIBLE; + vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; + vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } else if (vol.type == VolumeInfo.TYPE_PUBLIC) { if (primaryPhysical) { - vol.flags |= VolumeInfo.FLAG_PRIMARY; + vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; + vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; + } + + // Adoptable public disks are visible to apps, since they meet + // public API requirement of being in a stable location. + final DiskInfo disk = mDisks.get(vol.getDiskId()); + if (disk != null && disk.isAdoptable()) { + vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; } - vol.flags |= VolumeInfo.FLAG_VISIBLE; - vol.userId = UserHandle.USER_OWNER; + + vol.mountUserId = UserHandle.USER_OWNER; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } else if (vol.type == VolumeInfo.TYPE_PRIVATE) { @@ -978,7 +973,7 @@ class MountService extends IMountService.Stub } } - if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_UNMOUNTING) { + if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) { // TODO: this should eventually be handled by new ObbVolume state changes /* * Some OBBs might have been unmounted when this volume was @@ -1216,7 +1211,7 @@ class MountService extends IMountService.Stub enforceUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA); } try { - mConnector.execute("volume", "mount", vol.id, vol.flags, vol.userId); + mConnector.execute("volume", "mount", vol.id, vol.mountFlags, vol.mountUserId); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } @@ -2628,6 +2623,7 @@ class MountService extends IMountService.Stub private static final int MSG_STORAGE_STATE_CHANGED = 1; private static final int MSG_VOLUME_STATE_CHANGED = 2; private static final int MSG_VOLUME_METADATA_CHANGED = 3; + private static final int MSG_DISK_UNSUPPORTED = 4; private final RemoteCallbackList<IMountServiceListener> mCallbacks = new RemoteCallbackList<>(); @@ -2675,6 +2671,10 @@ class MountService extends IMountService.Stub callback.onVolumeMetadataChanged((VolumeInfo) args.arg1); break; } + case MSG_DISK_UNSUPPORTED: { + callback.onDiskUnsupported((DiskInfo) args.arg1); + break; + } } } @@ -2699,6 +2699,12 @@ class MountService extends IMountService.Stub args.arg1 = vol; obtainMessage(MSG_VOLUME_METADATA_CHANGED, args).sendToTarget(); } + + private void notifyDiskUnsupported(DiskInfo disk) { + final SomeArgs args = SomeArgs.obtain(); + args.arg1 = disk; + obtainMessage(MSG_DISK_UNSUPPORTED, args).sendToTarget(); + } } @Override @@ -2752,6 +2758,7 @@ class MountService extends IMountService.Stub pw.increaseIndent(); for (int i = 0; i < mVolumes.size(); i++) { final VolumeInfo vol = mVolumes.valueAt(i); + if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue; vol.dump(pw); } pw.decreaseIndent(); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 908ee22c75ec..4ee665770d4f 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -17,6 +17,7 @@ package com.android.server; import android.app.ActivityManager; +import android.app.AppOpsManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -84,7 +85,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private static final boolean VDBG = false; // STOPSHIP if true private static class Record { - String pkgForDebug; + String callingPackage; IBinder binder; @@ -109,7 +110,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { @Override public String toString() { - return "{pkgForDebug=" + pkgForDebug + " binder=" + binder + " callback=" + callback + return "{callingPackage=" + callingPackage + " binder=" + binder + + " callback=" + callback + " onSubscriptionsChangedListenererCallback=" + onSubscriptionsChangedListenerCallback + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId @@ -125,6 +127,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private final IBatteryStats mBatteryStats; + private final AppOpsManager mAppOps; + private boolean hasNotifySubscriptionInfoChangedOccurred = false; private int mNumPhones; @@ -327,6 +331,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } mConnectedApns = new ArrayList<String>(); + + mAppOps = mContext.getSystemService(AppOpsManager.class); } public void systemRunning() { @@ -340,18 +346,24 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void addOnSubscriptionsChangedListener(String pkgForDebug, + public void addOnSubscriptionsChangedListener(String callingPackage, IOnSubscriptionsChangedListener callback) { int callerUid = UserHandle.getCallingUserId(); int myUid = UserHandle.myUserId(); if (VDBG) { - log("listen oscl: E pkg=" + pkgForDebug + " myUid=" + myUid + log("listen oscl: E pkg=" + callingPackage + " myUid=" + myUid + " callerUid=" + callerUid + " callback=" + callback + " callback.asBinder=" + callback.asBinder()); } - /* Checks permission and throws Security exception */ - checkOnSubscriptionsChangedListenerPermission(); + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.READ_PHONE_STATE, null); + + if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(), + callingPackage) != AppOpsManager.MODE_ALLOWED) { + return; + } + Record r = null; synchronized (mRecords) { @@ -372,7 +384,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } r.onSubscriptionsChangedListenerCallback = callback; - r.pkgForDebug = pkgForDebug; + r.callingPackage = callingPackage; r.callerUid = callerUid; r.events = 0; if (DBG) { @@ -401,12 +413,6 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(callback.asBinder()); } - private void checkOnSubscriptionsChangedListenerPermission() { - mContext.enforceCallingOrSelfPermission( - SubscriptionManager.OnSubscriptionsChangedListener - .PERMISSION_ON_SUBSCRIPTIONS_CHANGED, null); - } - @Override public void notifySubscriptionInfoChanged() { if (VDBG) log("notifySubscriptionInfoChanged:"); @@ -446,12 +452,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { listen(pkgForDebug, callback, events, notifyNow, subId); } - private void listen(String pkgForDebug, IPhoneStateListener callback, int events, + private void listen(String callingPackage, IPhoneStateListener callback, int events, boolean notifyNow, int subId) { int callerUid = UserHandle.getCallingUserId(); int myUid = UserHandle.myUserId(); if (VDBG) { - log("listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events) + log("listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events) + " notifyNow=" + notifyNow + " subId=" + subId + " myUid=" + myUid + " callerUid=" + callerUid); } @@ -459,6 +465,14 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (events != PhoneStateListener.LISTEN_NONE) { /* Checks permission and throws Security exception */ checkListenerPermission(events); + + if ((events & PHONE_STATE_PERMISSION_MASK) != 0) { + if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(), + callingPackage) != AppOpsManager.MODE_ALLOWED) { + return; + } + } + synchronized (mRecords) { // register Record r = null; @@ -478,7 +492,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } r.callback = callback; - r.pkgForDebug = pkgForDebug; + r.callingPackage = callingPackage; r.callerUid = callerUid; // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID, // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID @@ -631,7 +645,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (mRecords.get(i).binder == binder) { if (DBG) { Record r = mRecords.get(i); - log("remove: binder=" + binder + "r.pkgForDebug" + r.pkgForDebug + log("remove: binder=" + binder + "r.callingPackage" + r.callingPackage + "r.callback" + r.callback); } mRecords.remove(i); @@ -1380,7 +1394,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, - android.Manifest.permission.READ_PHONE_STATE); + android.Manifest.permission.READ_PHONE_STATE, + AppOpsManager.OP_READ_PHONE_STATE); } private void broadcastDataConnectionStateChanged(int state, diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 0ca0c0e5ad27..770df82fda12 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -143,75 +143,67 @@ public class FingerprintService extends SystemService { + ", mAuthClients = " + mAuthClient + ", mEnrollClient = " + mEnrollClient); if (mEnrollClient != null) { final IBinder token = mEnrollClient.token; - if (doNotify(mEnrollClient, type, arg1, arg2, arg3)) { - stopEnrollment(token); + if (dispatchNotify(mEnrollClient, type, arg1, arg2, arg3)) { + stopEnrollment(token, false); + removeClient(mEnrollClient); } } if (mAuthClient != null) { final IBinder token = mAuthClient.token; - if (doNotify(mAuthClient, type, arg1, arg2, arg3)) { - stopAuthentication(token); + if (dispatchNotify(mAuthClient, type, arg1, arg2, arg3)) { + stopAuthentication(token, false); + removeClient(mAuthClient); } } if (mRemoveClient != null) { - if (doNotify(mRemoveClient, type, arg1, arg2, arg3)) { + if (dispatchNotify(mRemoveClient, type, arg1, arg2, arg3)) { removeClient(mRemoveClient); } } } - // Returns true if the operation is done, i.e. authentication completed - boolean doNotify(ClientMonitor clientMonitor, int type, int arg1, int arg2, int arg3) { + /* + * Dispatch notify events to clients. + * + * @return true if the operation is done, i.e. authentication completed + */ + boolean dispatchNotify(ClientMonitor clientMonitor, int type, int arg1, int arg2, int arg3) { ContentResolver contentResolver = mContext.getContentResolver(); boolean operationCompleted = false; + int fpId; + int groupId; + int remaining; + int acquireInfo; switch (type) { case FINGERPRINT_ERROR: - { - final int error = arg1; - clientMonitor.sendError(error); - removeClient(clientMonitor); - operationCompleted = true; // any error means the operation is done - } + fpId = arg1; + operationCompleted = clientMonitor.sendError(fpId); break; case FINGERPRINT_ACQUIRED: - clientMonitor.sendAcquired(arg1 /* acquireInfo */); + acquireInfo = arg1; + operationCompleted = clientMonitor.sendAcquired(acquireInfo); break; case FINGERPRINT_AUTHENTICATED: - { - final int fpId = arg1; - final int groupId = arg2; - clientMonitor.sendAuthenticated(fpId, groupId); - if (fpId == 0) { - if (clientMonitor == mAuthClient) { - operationCompleted = handleFailedAttempt(clientMonitor); - } - } else { - mLockoutReset.run(); // a valid fingerprint resets lockout - } - } + fpId = arg1; + groupId = arg2; + operationCompleted = clientMonitor.sendAuthenticated(fpId, groupId); break; case FINGERPRINT_TEMPLATE_ENROLLING: - { - final int fpId = arg1; - final int groupId = arg2; - final int remaining = arg3; - clientMonitor.sendEnrollResult(fpId, groupId, remaining); - if (remaining == 0) { - addTemplateForUser(clientMonitor, contentResolver, fpId); - operationCompleted = true; // enroll completed - } + fpId = arg1; + groupId = arg2; + remaining = arg3; + operationCompleted = clientMonitor.sendEnrollResult(fpId, groupId, remaining); + if (remaining == 0) { + addTemplateForUser(clientMonitor, contentResolver, fpId); + operationCompleted = true; // enroll completed } break; case FINGERPRINT_TEMPLATE_REMOVED: - { - final int fingerId = arg1; - final int groupId = arg2; - removeTemplateForUser(clientMonitor, contentResolver, fingerId); - if (fingerId == 0) { - operationCompleted = true; // remove completed - } else { - clientMonitor.sendRemoved(fingerId, groupId); - } + fpId = arg1; + groupId = arg2; + operationCompleted = clientMonitor.sendRemoved(fpId, groupId); + if (fpId != 0) { + removeTemplateForUser(clientMonitor, contentResolver, fpId); } break; } @@ -235,7 +227,9 @@ public class FingerprintService extends SystemService { } private void resetFailedAttempts() { - if (DEBUG) Slog.v(TAG, "Reset fingerprint lockout"); + if (DEBUG && inLockoutMode()) { + Slog.v(TAG, "Reset fingerprint lockout"); + } mFailedAttempts = 0; } @@ -283,19 +277,21 @@ public class FingerprintService extends SystemService { private void stopPendingOperations() { if (mEnrollClient != null) { - stopEnrollment(mEnrollClient.token); + stopEnrollment(mEnrollClient.token, true); } if (mAuthClient != null) { - stopAuthentication(mAuthClient.token); + stopAuthentication(mAuthClient.token, true); } // mRemoveClient is allowed to continue } - void stopEnrollment(IBinder token) { + void stopEnrollment(IBinder token, boolean notify) { final ClientMonitor client = mEnrollClient; if (client == null || client.token != token) return; int result = nativeStopEnrollment(); - client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED); + if (notify) { + client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED); + } removeClient(mEnrollClient); if (result != 0) { Slog.w(TAG, "startEnrollCancel failed, result=" + result); @@ -321,11 +317,13 @@ public class FingerprintService extends SystemService { } } - void stopAuthentication(IBinder token) { + void stopAuthentication(IBinder token, boolean notify) { final ClientMonitor client = mAuthClient; if (client == null || client.token != token) return; int result = nativeStopAuthentication(); - client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED); + if (notify) { + client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED); + } removeClient(mAuthClient); if (result != 0) { Slog.w(TAG, "stopAuthentication failed, result=" + result); @@ -408,74 +406,89 @@ public class FingerprintService extends SystemService { } } + /* + * @return true if we're done. + */ private boolean sendRemoved(int fingerId, int groupId) { IFingerprintServiceReceiver rx = receiver.get(); - if (rx != null) { - try { - rx.onRemoved(mHalDeviceId, fingerId, groupId); - return true; - } catch (RemoteException e) { - if (DEBUG) Slog.v(TAG, "Failed to invoke sendRemoved:", e); - } + if (rx == null) return true; // client not listening + try { + rx.onRemoved(mHalDeviceId, fingerId, groupId); + return fingerId == 0; + } catch (RemoteException e) { + Slog.w(TAG, "Failed to notify Removed:", e); } - removeClient(this); return false; } + /* + * @return true if we're done. + */ private boolean sendEnrollResult(int fpId, int groupId, int remaining) { IFingerprintServiceReceiver rx = receiver.get(); - if (rx != null) { - try { - rx.onEnrollResult(mHalDeviceId, fpId, groupId, remaining); - return true; - } catch (RemoteException e) { - if (DEBUG) Slog.v(TAG, "Failed to invoke sendEnrollResult:", e); - } + if (rx == null) return true; // client not listening + try { + rx.onEnrollResult(mHalDeviceId, fpId, groupId, remaining); + return remaining == 0; + } catch (RemoteException e) { + Slog.w(TAG, "Failed to notify EnrollResult:", e); + return true; } - removeClient(this); - return false; } + /* + * @return true if we're done. + */ private boolean sendAuthenticated(int fpId, int groupId) { IFingerprintServiceReceiver rx = receiver.get(); + boolean result = false; if (rx != null) { try { rx.onAuthenticated(mHalDeviceId, fpId, groupId); - return true; } catch (RemoteException e) { - if (DEBUG) Slog.v(TAG, "Failed to invoke sendProcessed:", e); + Slog.w(TAG, "Failed to notify Authenticated:", e); + result = true; // client failed } + } else { + result = true; // client not listening } - removeClient(this); - return false; + if (fpId <= 0) { + result |= handleFailedAttempt(this); + } else { + result |= true; // we have a valid fingerprint + mLockoutReset.run(); + } + return result; } + /* + * @return true if we're done. + */ private boolean sendAcquired(int acquiredInfo) { IFingerprintServiceReceiver rx = receiver.get(); - if (rx != null) { - try { - rx.onAcquired(mHalDeviceId, acquiredInfo); - return true; - } catch (RemoteException e) { - if (DEBUG) Slog.v(TAG, "Failed to invoke sendAcquired:", e); - } + if (rx == null) return true; // client not listening + try { + rx.onAcquired(mHalDeviceId, acquiredInfo); + return false; // acquisition continues... + } catch (RemoteException e) { + Slog.w(TAG, "Failed to invoke sendAcquired:", e); + return true; // client failed } - removeClient(this); - return false; } + /* + * @return true if we're done. + */ private boolean sendError(int error) { IFingerprintServiceReceiver rx = receiver.get(); if (rx != null) { try { rx.onError(mHalDeviceId, error); - return true; } catch (RemoteException e) { - if (DEBUG) Slog.v(TAG, "Failed to invoke sendError:", e); + Slog.w(TAG, "Failed to invoke sendError:", e); } } - removeClient(this); - return false; + return true; // errors always terminate progress } } @@ -507,7 +520,7 @@ public class FingerprintService extends SystemService { mHandler.post(new Runnable() { @Override public void run() { - stopEnrollment(token); + stopEnrollment(token, true); } }); } @@ -533,7 +546,7 @@ public class FingerprintService extends SystemService { mHandler.post(new Runnable() { @Override public void run() { - stopAuthentication(token); + stopAuthentication(token, true); } }); } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 5de7d422ee80..4e90f97723a7 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -74,6 +74,7 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG; import android.Manifest; import android.app.ActivityManager; import android.app.AppGlobals; +import android.app.AppOpsManager; import android.app.IActivityManager; import android.app.INotificationManager; import android.app.IProcessObserver; @@ -136,6 +137,7 @@ import android.util.SparseIntArray; import android.util.TrustedTime; import android.util.Xml; +import com.android.server.AppOpsService; import libcore.io.IoUtils; import com.android.internal.R; @@ -292,6 +294,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private final AtomicFile mPolicyFile; + private final AppOpsManager mAppOps; + // TODO: keep whitelist of system-critical services that should never have // rules enforced, such as system, phone, and radio UIDs. @@ -326,6 +330,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mSuppressDefaultPolicy = suppressDefaultPolicy; mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); + + mAppOps = context.getSystemService(AppOpsManager.class); } public void bindConnectivityManager(IConnectivityManager connManager) { @@ -1593,16 +1599,21 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } void addNetworkPolicyLocked(NetworkPolicy policy) { - NetworkPolicy[] policies = getNetworkPolicies(); + NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName()); policies = ArrayUtils.appendElement(NetworkPolicy.class, policies, policy); setNetworkPolicies(policies); } @Override - public NetworkPolicy[] getNetworkPolicies() { + public NetworkPolicy[] getNetworkPolicies(String callingPackage) { mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); + if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(), + callingPackage) != AppOpsManager.MODE_ALLOWED) { + return new NetworkPolicy[0]; + } + synchronized (mRulesLock) { final int size = mNetworkPolicy.size(); final NetworkPolicy[] policies = new NetworkPolicy[size]; @@ -1614,7 +1625,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } private void normalizePoliciesLocked() { - normalizePoliciesLocked(getNetworkPolicies()); + normalizePoliciesLocked(getNetworkPolicies(mContext.getOpPackageName())); } private void normalizePoliciesLocked(NetworkPolicy[] policies) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index c12545b36d82..331683b6fe2b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1534,15 +1534,15 @@ public class PackageManagerService extends IPackageManager.Stub { if (vol.type == VolumeInfo.TYPE_PRIVATE) { if (vol.state == VolumeInfo.STATE_MOUNTED) { loadPrivatePackages(vol); - } else if (vol.state == VolumeInfo.STATE_UNMOUNTING) { + } else if (vol.state == VolumeInfo.STATE_EJECTING) { unloadPrivatePackages(vol); } } - if (vol.isPrimary() && vol.type == VolumeInfo.TYPE_PUBLIC) { + if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.isPrimary()) { if (vol.state == VolumeInfo.STATE_MOUNTED) { updateExternalMediaStatus(true, false); - } else if (vol.state == VolumeInfo.STATE_UNMOUNTING) { + } else if (vol.state == VolumeInfo.STATE_EJECTING) { updateExternalMediaStatus(false, false); } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 964dcc2155e5..f29d524bce03 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -709,6 +709,11 @@ public class WindowManagerService extends IWindowManager.Stub private WindowContentFrameStats mTempWindowRenderStats; final class DragInputEventReceiver extends InputEventReceiver { + // Set, if stylus button was down at the start of the drag. + private boolean mStylusButtonDownAtStart; + // Indicates the first event to check for button state. + private boolean mIsStartEvent = true; + public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); } @@ -724,6 +729,18 @@ public class WindowManagerService extends IWindowManager.Stub boolean endDrag = false; final float newX = motionEvent.getRawX(); final float newY = motionEvent.getRawY(); + final boolean isStylusButtonDown = + (motionEvent.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS) + && (motionEvent.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0; + + if (mIsStartEvent) { + if (isStylusButtonDown) { + // First event and the button was down, check for the button being + // lifted in the future, if that happens we'll drop the item. + mStylusButtonDownAtStart = true; + } + mIsStartEvent = false; + } switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: { @@ -733,9 +750,17 @@ public class WindowManagerService extends IWindowManager.Stub } break; case MotionEvent.ACTION_MOVE: { - synchronized (mWindowMap) { - // move the surface and tell the involved window(s) where we are - mDragState.notifyMoveLw(newX, newY); + if (mStylusButtonDownAtStart && !isStylusButtonDown) { + if (DEBUG_DRAG) Slog.d(TAG, "Button no longer pressed; dropping at " + + newX + "," + newY); + synchronized (mWindowMap) { + endDrag = mDragState.notifyDropLw(newX, newY); + } + } else { + synchronized (mWindowMap) { + // move the surface and tell the involved window(s) where we are + mDragState.notifyMoveLw(newX, newY); + } } } break; @@ -759,6 +784,8 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { mDragState.endDragLw(); } + mStylusButtonDownAtStart = false; + mIsStartEvent = true; } handled = true; diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index a5546cf806a6..19ca2b46af14 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -33,7 +33,6 @@ LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ frameworks/base/services \ frameworks/base/libs \ - frameworks/base/libs/hwui \ frameworks/base/core/jni \ frameworks/native/services \ libcore/include \ diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp index 8f4fb51093d9..e4f242e32fba 100644 --- a/services/core/jni/com_android_server_AssetAtlasService.cpp +++ b/services/core/jni/com_android_server_AssetAtlasService.cpp @@ -47,9 +47,40 @@ namespace android { #define FENCE_TIMEOUT 2000000000 // ---------------------------------------------------------------------------- +// JNI Helpers +// ---------------------------------------------------------------------------- + +static struct { + jmethodID setNativeBitmap; +} gCanvasClassInfo; + +#define INVOKEV(object, method, ...) \ + env->CallVoidMethod(object, method, __VA_ARGS__) + +// ---------------------------------------------------------------------------- // Canvas management // ---------------------------------------------------------------------------- +static jlong com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject, + jobject canvas, jint width, jint height) { + + SkBitmap* bitmap = new SkBitmap; + bitmap->allocN32Pixels(width, height); + bitmap->eraseColor(0); + INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(bitmap)); + + return reinterpret_cast<jlong>(bitmap); +} + +static void com_android_server_AssetAtlasService_releaseCanvas(JNIEnv* env, jobject, + jobject canvas, jlong bitmapHandle) { + + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); + INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0); + + delete bitmap; +} + #define CLEANUP_GL_AND_RETURN(result) \ if (fence != EGL_NO_SYNC_KHR) eglDestroySyncKHR(display, fence); \ if (image) eglDestroyImageKHR(display, image); \ @@ -62,12 +93,9 @@ namespace android { return result; static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject, - jobject graphicBuffer, jobject bitmapHandle) { - - SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, bitmapHandle, &bitmap); - SkAutoLockPixels alp(bitmap); + jobject graphicBuffer, jlong bitmapHandle) { + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); // The goal of this method is to copy the bitmap into the GraphicBuffer // using the GPU to swizzle the texture content sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer)); @@ -158,9 +186,9 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject } // Upload the content of the bitmap in the GraphicBuffer - glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap.bytesPerPixel()); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), - GL_RGBA, GL_UNSIGNED_BYTE, bitmap.getPixels()); + glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap->width(), bitmap->height(), + GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels()); if (glGetError() != GL_NO_ERROR) { ALOGW("Could not upload to texture"); CLEANUP_GL_AND_RETURN(JNI_FALSE); @@ -205,11 +233,20 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject const char* const kClassPathName = "com/android/server/AssetAtlasService"; static JNINativeMethod gMethods[] = { - { "nUploadAtlas", "(Landroid/view/GraphicBuffer;Landroid/graphics/Bitmap;)Z", + { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)J", + (void*) com_android_server_AssetAtlasService_acquireCanvas }, + { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;J)V", + (void*) com_android_server_AssetAtlasService_releaseCanvas }, + { "nUploadAtlas", "(Landroid/view/GraphicBuffer;J)Z", (void*) com_android_server_AssetAtlasService_upload }, }; int register_android_server_AssetAtlasService(JNIEnv* env) { + jclass clazz; + + FIND_CLASS(clazz, "android/graphics/Canvas"); + GET_METHOD_ID(gCanvasClassInfo.setNativeBitmap, clazz, "setNativeBitmap", "(J)V"); + return jniRegisterNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); } diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 5abbb504aabc..a72172cc91da 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -359,7 +359,8 @@ public class TelecomManager { public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) { try { if (isServiceConnected()) { - return getTelecomService().getDefaultOutgoingPhoneAccount(uriScheme); + return getTelecomService().getDefaultOutgoingPhoneAccount(uriScheme, + mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#getDefaultOutgoingPhoneAccount", e); @@ -443,7 +444,7 @@ public class TelecomManager { public List<PhoneAccountHandle> getSimCallManagers() { try { if (isServiceConnected()) { - return getTelecomService().getSimCallManagers(); + return getTelecomService().getSimCallManagers(mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#getSimCallManagers"); @@ -491,7 +492,8 @@ public class TelecomManager { public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) { try { if (isServiceConnected()) { - return getTelecomService().getPhoneAccountsSupportingScheme(uriScheme); + return getTelecomService().getPhoneAccountsSupportingScheme(uriScheme, + mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsSupportingScheme", e); @@ -511,7 +513,7 @@ public class TelecomManager { public List<PhoneAccountHandle> getCallCapablePhoneAccounts() { try { if (isServiceConnected()) { - return getTelecomService().getCallCapablePhoneAccounts(); + return getTelecomService().getCallCapablePhoneAccounts(mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#getCallCapablePhoneAccounts", e); @@ -711,7 +713,8 @@ public class TelecomManager { public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number) { try { if (isServiceConnected()) { - return getTelecomService().isVoiceMailNumber(accountHandle, number); + return getTelecomService().isVoiceMailNumber(accountHandle, number, + mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "RemoteException calling ITelecomService#isVoiceMailNumber.", e); @@ -729,7 +732,8 @@ public class TelecomManager { public String getVoiceMailNumber(PhoneAccountHandle accountHandle) { try { if (isServiceConnected()) { - return getTelecomService().getVoiceMailNumber(accountHandle); + return getTelecomService().getVoiceMailNumber(accountHandle, + mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "RemoteException calling ITelecomService#hasVoiceMailNumber.", e); @@ -746,7 +750,8 @@ public class TelecomManager { public String getLine1Number(PhoneAccountHandle accountHandle) { try { if (isServiceConnected()) { - return getTelecomService().getLine1Number(accountHandle); + return getTelecomService().getLine1Number(accountHandle, + mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "RemoteException calling ITelecomService#getLine1Number.", e); @@ -764,7 +769,7 @@ public class TelecomManager { public boolean isInCall() { try { if (isServiceConnected()) { - return getTelecomService().isInCall(); + return getTelecomService().isInCall(mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "RemoteException calling isInCall().", e); @@ -806,7 +811,7 @@ public class TelecomManager { public boolean isRinging() { try { if (isServiceConnected()) { - return getTelecomService().isRinging(); + return getTelecomService().isRinging(mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "RemoteException attempting to get ringing state of phone app.", e); @@ -872,7 +877,7 @@ public class TelecomManager { public boolean isTtySupported() { try { if (isServiceConnected()) { - return getTelecomService().isTtySupported(); + return getTelecomService().isTtySupported(mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "RemoteException attempting to get TTY supported state.", e); @@ -893,7 +898,7 @@ public class TelecomManager { public int getCurrentTtyMode() { try { if (isServiceConnected()) { - return getTelecomService().getCurrentTtyMode(); + return getTelecomService().getCurrentTtyMode(mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "RemoteException attempting to get the current TTY mode.", e); @@ -1045,7 +1050,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - service.showInCallScreen(showDialpad); + service.showInCallScreen(showDialpad, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#showCallScreen", e); } diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl index 35db97fb50ee..727fd4bba30e 100644 --- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl @@ -33,12 +33,12 @@ interface ITelecomService { * * @param showDialpad if true, make the dialpad visible initially. */ - void showInCallScreen(boolean showDialpad); + void showInCallScreen(boolean showDialpad, String callingPackage); /** * @see TelecomServiceImpl#getDefaultOutgoingPhoneAccount */ - PhoneAccountHandle getDefaultOutgoingPhoneAccount(in String uriScheme); + PhoneAccountHandle getDefaultOutgoingPhoneAccount(in String uriScheme, String callingPackage); /** * @see TelecomServiceImpl#getUserSelectedOutgoingPhoneAccount @@ -53,12 +53,13 @@ interface ITelecomService { /** * @see TelecomServiceImpl#getCallCapablePhoneAccounts */ - List<PhoneAccountHandle> getCallCapablePhoneAccounts(); + List<PhoneAccountHandle> getCallCapablePhoneAccounts(String callingPackage); /** * @see TelecomManager#getPhoneAccountsSupportingScheme */ - List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme); + List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme, + String callingPackage); /** * @see TelecomManager#getPhoneAccountsForPackage @@ -98,7 +99,7 @@ interface ITelecomService { /** * @see TelecomServiceImpl#getSimCallManagers */ - List<PhoneAccountHandle> getSimCallManagers(); + List<PhoneAccountHandle> getSimCallManagers(String callingPackage); /** * @see TelecomServiceImpl#registerPhoneAccount @@ -118,17 +119,18 @@ interface ITelecomService { /** * @see TelecomServiceImpl#isVoiceMailNumber */ - boolean isVoiceMailNumber(in PhoneAccountHandle accountHandle, String number); + boolean isVoiceMailNumber(in PhoneAccountHandle accountHandle, String number, + String callingPackage); /** * @see TelecomServiceImpl#getVoiceMailNumber */ - String getVoiceMailNumber(in PhoneAccountHandle accountHandle); + String getVoiceMailNumber(in PhoneAccountHandle accountHandle, String callingPackage); /** * @see TelecomServiceImpl#getLine1Number */ - String getLine1Number(in PhoneAccountHandle accountHandle); + String getLine1Number(in PhoneAccountHandle accountHandle, String callingPackage); /** * @see TelecomServiceImpl#getDefaultPhoneApp @@ -147,12 +149,12 @@ interface ITelecomService { /** * @see TelecomServiceImpl#isInCall */ - boolean isInCall(); + boolean isInCall(String callingPackage); /** * @see TelecomServiceImpl#isRinging */ - boolean isRinging(); + boolean isRinging(String callingPackage); /** * @see TelecomServiceImpl#getCallState @@ -192,12 +194,12 @@ interface ITelecomService { /** * @see TelecomServiceImpl#isTtySupported */ - boolean isTtySupported(); + boolean isTtySupported(String callingPackage); /** * @see TelecomServiceImpl#getCurrentTtyMode */ - int getCurrentTtyMode(); + int getCurrentTtyMode(String callingPackage); /** * @see TelecomServiceImpl#addNewIncomingCall diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index b1fb3a612d52..d103fbf8d9ab 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -85,7 +85,6 @@ public class CarrierConfigManager { * * @hide */ - @SystemApi public static final String STRING_VVM_DESTINATION_NUMBER = "string_vvm_destination_number"; /** @@ -93,15 +92,13 @@ public class CarrierConfigManager { * * @hide */ - @SystemApi - public static final String SHORT_VVM_PORT_NUMBER = "string_vvm_port_number"; + public static final String INT_VVM_PORT_NUMBER = "int_vvm_port_number"; /** * The type of visual voicemail protocol the carrier adheres to (see below). * * @hide */ - @SystemApi public static final String STRING_VVM_TYPE = "string_vvm_type"; /* Visual voicemail protocols */ @@ -111,7 +108,6 @@ public class CarrierConfigManager { * * @hide */ - @SystemApi public static final String VVM_TYPE_OMTP = "vvm_type_omtp"; private final static String TAG = "CarrierConfigManager"; @@ -127,6 +123,10 @@ public class CarrierConfigManager { sDefaults.putBoolean(BOOL_SHOW_APN_SETTING_CDMA, false); sDefaults.putInt(INT_VOLTE_REPLACEMENT_RAT, 0); + + sDefaults.putString(STRING_VVM_DESTINATION_NUMBER, ""); + sDefaults.putString(STRING_VVM_TYPE, ""); + sDefaults.putInt(INT_VVM_PORT_NUMBER, 0); } /** diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 08aec08cbb3c..3ecf5ac6b85a 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -272,10 +272,6 @@ public class SubscriptionManager { * for #onSubscriptionsChanged to be invoked. */ public static class OnSubscriptionsChangedListener { - /** @hide */ - public static final String PERMISSION_ON_SUBSCRIPTIONS_CHANGED = - android.Manifest.permission.READ_PHONE_STATE; - private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 128f6e3c1eea..81f329c2ce82 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -664,7 +664,7 @@ public class TelephonyManager { ITelephony telephony = getITelephony(); if (telephony == null) return null; - return telephony.getDeviceId(); + return telephony.getDeviceId(mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -782,7 +782,7 @@ public class TelephonyManager { ITelephony telephony = getITelephony(); if (telephony == null) return null; - Bundle bundle = telephony.getCellLocation(); + Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName()); if (bundle.isEmpty()) return null; CellLocation cl = CellLocation.newFromBundle(bundle); if (cl.isEmpty()) @@ -1975,7 +1975,7 @@ public class TelephonyManager { try { ITelephony telephony = getITelephony(); if (telephony != null) - number = telephony.getLine1NumberForDisplay(subId); + number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { } catch (NullPointerException ex) { } @@ -2096,7 +2096,8 @@ public class TelephonyManager { try { ITelephony telephony = getITelephony(); if (telephony != null) - alphaTag = telephony.getLine1AlphaTagForDisplay(subId); + alphaTag = telephony.getLine1AlphaTagForDisplay(subId, + mContext.getOpPackageName()); } catch (RemoteException ex) { } catch (NullPointerException ex) { } @@ -2728,7 +2729,7 @@ public class TelephonyManager { ITelephony telephony = getITelephony(); if (telephony == null) return null; - return telephony.getAllCellInfo(); + return telephony.getAllCellInfo(mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -3342,7 +3343,7 @@ public class TelephonyManager { ITelephony telephony = getITelephony(); if (telephony == null) return new String[0]; - return telephony.getPcscfAddress(apnType); + return telephony.getPcscfAddress(apnType, mContext.getOpPackageName()); } catch (RemoteException e) { return new String[0]; } @@ -3759,7 +3760,7 @@ public class TelephonyManager { try { ITelephony telephony = getITelephony(); if (telephony != null) - return telephony.isSimPinEnabled(); + return telephony.isSimPinEnabled(mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelephony#isSimPinEnabled", e); } @@ -4026,7 +4027,7 @@ public class TelephonyManager { try { ITelephony telephony = getITelephony(); if (telephony != null) - return telephony.isVideoCallingEnabled(); + return telephony.isVideoCallingEnabled(mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelephony#isVideoCallingEnabled", e); } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index a24859b2820a..0b77c26a8b1d 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -45,6 +45,7 @@ interface ITelephony { /** * Place a call to the specified number. + * @param callingPackage The package making the call. * @param number the number to be called. */ void call(String callingPackage, String number); @@ -169,8 +170,9 @@ interface ITelephony { /** * Check if the SIM pin lock is enabled. * @return true if the SIM pin lock is enabled. + * @param callingPackage The package making the call. */ - boolean isSimPinEnabled(); + boolean isSimPinEnabled(String callingPackage); /** * Supply a pin to unlock the SIM. Blocks until a result is determined. @@ -341,7 +343,7 @@ interface ITelephony { */ boolean isDataConnectivityPossible(); - Bundle getCellLocation(); + Bundle getCellLocation(String callingPkg); /** * Returns the neighboring cell information of the device. @@ -505,7 +507,7 @@ interface ITelephony { /** * Returns the all observed cell information of the device. */ - List<CellInfo> getAllCellInfo(); + List<CellInfo> getAllCellInfo(String callingPkg); /** * Sets minimum time in milli-seconds between onCellInfoChanged @@ -644,10 +646,11 @@ interface ITelephony { /* * Get the calculated preferred network type. * Used for device configuration by some CDMA operators. + * @param callingPackage The package making the call. * * @return the calculated preferred network type, defined in RILConstants.java. */ - int getCalculatedPreferredNetworkType(); + int getCalculatedPreferredNetworkType(String callingPackage); /* * Get the preferred network type. @@ -701,8 +704,9 @@ interface ITelephony { /** * Get P-CSCF address from PCO after data connection is established or modified. * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN + * @param callingPackage The package making the call. */ - String[] getPcscfAddress(String apnType); + String[] getPcscfAddress(String apnType, String callingPackage); /** * Set IMS registration state @@ -768,19 +772,21 @@ interface ITelephony { * {@link #setLine1NumberForDisplay}. Otherwise returns null. * * @param subId whose dialing number for line 1 is returned. + * @param callingPackage The package making the call. * @return the displayed dialing number if set, or null if not set. */ - String getLine1NumberForDisplay(int subId); + String getLine1NumberForDisplay(int subId, String callingPackage); /** * Returns the displayed alphatag of the dialing number if it was set * previously via {@link #setLine1NumberForDisplay}. Otherwise returns null. * * @param subId whose alphatag associated with line 1 is returned. + * @param callingPackage The package making the call. * @return the displayed alphatag of the dialing number if set, or null if * not set. */ - String getLine1AlphaTagForDisplay(int subId); + String getLine1AlphaTagForDisplay(int subId, String callingPackage); String[] getMergedSubscriberIds(); @@ -872,9 +878,10 @@ interface ITelephony { /** * Whether video calling has been enabled by the user. * + * @param callingPackage The package making the call. * @return {@code true} if the user has enabled video calling, {@code false} otherwise. */ - boolean isVideoCallingEnabled(); + boolean isVideoCallingEnabled(String callingPackage); /** * Whether the DTMF tone length can be changed. @@ -925,10 +932,11 @@ interface ITelephony { * Returns the unique device ID of phone, for example, the IMEI for * GSM and the MEID for CDMA phones. Return null if device ID is not available. * + * @param callingPackage The package making the call. * <p>Requires Permission: * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} */ - String getDeviceId(); + String getDeviceId(String callingPackage); /** * Returns the subscription ID associated with the specified PhoneAccount. diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java index b265d470dbe9..04ded9d5b264 100644 --- a/test-runner/src/android/test/mock/MockContext.java +++ b/test-runner/src/android/test/mock/MockContext.java @@ -354,6 +354,13 @@ public class MockContext extends Context { throw new UnsupportedOperationException(); } + /** @hide */ + @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp) { + throw new UnsupportedOperationException(); + } + @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 1da8bb4db849..094778d2b4a5 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -1401,6 +1401,11 @@ public final class BridgeContext extends Context { // pass } + public void sendBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp) { + // pass + } + @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, |