diff options
33 files changed, 1597 insertions, 451 deletions
diff --git a/api/current.txt b/api/current.txt index e96eec2e29ea..e50e57f7b01c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -20,6 +20,7 @@ package android { field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS"; field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE"; field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET"; + field public static final java.lang.String BIND_CALL_SERVICE = "android.permission.BIND_CALL_SERVICE"; field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN"; field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD"; field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE"; @@ -5986,6 +5987,7 @@ package android.content { field public static final int MODE_PRIVATE = 0; // 0x0 field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1 field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2 + field public static final java.lang.String NETWORKMANAGEMENT_SERVICE = "network_management"; field public static final java.lang.String NFC_SERVICE = "nfc"; field public static final java.lang.String NOTIFICATION_SERVICE = "notification"; field public static final java.lang.String NSD_SERVICE = "servicediscovery"; @@ -12769,6 +12771,25 @@ package android.media { field public static final java.lang.String KEY_WIDTH = "width"; } + public abstract class MediaMetadataEditor { + method public synchronized void addEditableKey(int); + method public abstract void apply(); + method public synchronized void clear(); + method public synchronized android.graphics.Bitmap getBitmap(int, android.graphics.Bitmap) throws java.lang.IllegalArgumentException; + method public synchronized int[] getEditableKeys(); + method public synchronized long getLong(int, long) throws java.lang.IllegalArgumentException; + method public synchronized java.lang.Object getObject(int, java.lang.Object) throws java.lang.IllegalArgumentException; + method public synchronized java.lang.String getString(int, java.lang.String) throws java.lang.IllegalArgumentException; + method public synchronized android.media.MediaMetadataEditor putBitmap(int, android.graphics.Bitmap) throws java.lang.IllegalArgumentException; + method public synchronized android.media.MediaMetadataEditor putLong(int, long) throws java.lang.IllegalArgumentException; + method public synchronized android.media.MediaMetadataEditor putObject(int, java.lang.Object) throws java.lang.IllegalArgumentException; + method public synchronized android.media.MediaMetadataEditor putString(int, java.lang.String) throws java.lang.IllegalArgumentException; + method public synchronized void removeEditableKeys(); + field public static final int BITMAP_KEY_ARTWORK = 100; // 0x64 + field public static final int RATING_KEY_BY_OTHERS = 101; // 0x65 + field public static final int RATING_KEY_BY_USER = 268435457; // 0x10000001 + } + public class MediaMetadataRetriever { ctor public MediaMetadataRetriever(); method public java.lang.String extractMetadata(int); @@ -13185,6 +13206,29 @@ package android.media { ctor public NotProvisionedException(java.lang.String); } + public final class Rating implements android.os.Parcelable { + method public int describeContents(); + method public float getPercentRating(); + method public int getRatingStyle(); + method public float getStarRating(); + method public boolean hasHeart(); + method public boolean isRated(); + method public boolean isThumbUp(); + method public static android.media.Rating newHeartRating(boolean); + method public static android.media.Rating newPercentageRating(float); + method public static android.media.Rating newStarRating(int, float); + method public static android.media.Rating newThumbRating(boolean); + method public static android.media.Rating newUnratedRating(int); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int RATING_3_STARS = 3; // 0x3 + field public static final int RATING_4_STARS = 4; // 0x4 + field public static final int RATING_5_STARS = 5; // 0x5 + field public static final int RATING_HEART = 1; // 0x1 + field public static final int RATING_PERCENTAGE = 6; // 0x6 + field public static final int RATING_THUMB_UP_DOWN = 2; // 0x2 + } + public class RemoteControlClient { ctor public RemoteControlClient(android.app.PendingIntent); ctor public RemoteControlClient(android.app.PendingIntent, android.os.Looper); @@ -13216,21 +13260,9 @@ package android.media { field public static final int PLAYSTATE_STOPPED = 1; // 0x1 } - public class RemoteControlClient.MetadataEditor { - method public synchronized void addEditableKey(int); + public class RemoteControlClient.MetadataEditor extends android.media.MediaMetadataEditor { method public synchronized void apply(); - method public synchronized void clear(); - method public synchronized void clearEditableKeys(); - method public synchronized android.media.RemoteControlClient.MetadataEditor putBitmap(int, android.graphics.Bitmap) throws java.lang.IllegalArgumentException; - method public synchronized android.media.RemoteControlClient.MetadataEditor putLong(int, long) throws java.lang.IllegalArgumentException; - method public synchronized android.media.RemoteControlClient.MetadataEditor putString(int, java.lang.String) throws java.lang.IllegalArgumentException; field public static final int BITMAP_KEY_ARTWORK = 100; // 0x64 - field public static final int LONG_KEY_RATING_BY_OTHERS = 102; // 0x66 - field public static final int LONG_KEY_RATING_BY_USER = 268435457; // 0x10000001 - field public static final int LONG_KEY_RATING_TYPE = 101; // 0x65 - field public static final long RATING_HEART = -1L; // 0xffffffffffffffffL - field public static final long RATING_NOT_RATED = -101L; // 0xffffffffffffff9bL - field public static final long RATING_THUMB_UP_DOWN = -2L; // 0xfffffffffffffffeL } public static abstract interface RemoteControlClient.OnGetPlaybackPositionListener { @@ -13238,9 +13270,7 @@ package android.media { } public static abstract interface RemoteControlClient.OnMetadataUpdateListener { - method public abstract void onMetadataUpdateBitmap(int, android.graphics.Bitmap); - method public abstract void onMetadataUpdateLong(int, long); - method public abstract void onMetadataUpdateString(int, java.lang.String); + method public abstract void onMetadataUpdate(int, java.lang.Object); } public static abstract interface RemoteControlClient.OnPlaybackPositionUpdateListener { @@ -19115,12 +19145,54 @@ package android.print { field public static final android.print.PrintAttributes.MediaSize ISO_C7; field public static final android.print.PrintAttributes.MediaSize ISO_C8; field public static final android.print.PrintAttributes.MediaSize ISO_C9; + field public static final android.print.PrintAttributes.MediaSize JIS_B0; + field public static final android.print.PrintAttributes.MediaSize JIS_B1; + field public static final android.print.PrintAttributes.MediaSize JIS_B10; + field public static final android.print.PrintAttributes.MediaSize JIS_B2; + field public static final android.print.PrintAttributes.MediaSize JIS_B3; + field public static final android.print.PrintAttributes.MediaSize JIS_B4; + field public static final android.print.PrintAttributes.MediaSize JIS_B5; + field public static final android.print.PrintAttributes.MediaSize JIS_B6; + field public static final android.print.PrintAttributes.MediaSize JIS_B7; + field public static final android.print.PrintAttributes.MediaSize JIS_B8; + field public static final android.print.PrintAttributes.MediaSize JIS_B9; + field public static final android.print.PrintAttributes.MediaSize JIS_EXEC; + field public static final android.print.PrintAttributes.MediaSize JPN_CHOU2; + field public static final android.print.PrintAttributes.MediaSize JPN_CHOU3; + field public static final android.print.PrintAttributes.MediaSize JPN_CHOU4; + field public static final android.print.PrintAttributes.MediaSize JPN_HAGAKI; + field public static final android.print.PrintAttributes.MediaSize JPN_KAHU; + field public static final android.print.PrintAttributes.MediaSize JPN_KAKU2; + field public static final android.print.PrintAttributes.MediaSize JPN_OUFUKU; + field public static final android.print.PrintAttributes.MediaSize JPN_YOU4; + field public static final android.print.PrintAttributes.MediaSize NA_FOOLSCAP; field public static final android.print.PrintAttributes.MediaSize NA_GOVT_LETTER; + field public static final android.print.PrintAttributes.MediaSize NA_INDEX_3X5; + field public static final android.print.PrintAttributes.MediaSize NA_INDEX_4X6; + field public static final android.print.PrintAttributes.MediaSize NA_INDEX_5X8; field public static final android.print.PrintAttributes.MediaSize NA_JUNIOR_LEGAL; field public static final android.print.PrintAttributes.MediaSize NA_LEDGER; field public static final android.print.PrintAttributes.MediaSize NA_LEGAL; field public static final android.print.PrintAttributes.MediaSize NA_LETTER; + field public static final android.print.PrintAttributes.MediaSize NA_MONARCH; + field public static final android.print.PrintAttributes.MediaSize NA_QUARTO; field public static final android.print.PrintAttributes.MediaSize NA_TBLOID; + field public static final android.print.PrintAttributes.MediaSize OM_DAI_PA_KAI; + field public static final android.print.PrintAttributes.MediaSize OM_JUURO_KU_KAI; + field public static final android.print.PrintAttributes.MediaSize OM_PA_KAI; + field public static final android.print.PrintAttributes.MediaSize PRC_1; + field public static final android.print.PrintAttributes.MediaSize PRC_10; + field public static final android.print.PrintAttributes.MediaSize PRC_16k; + field public static final android.print.PrintAttributes.MediaSize PRC_2; + field public static final android.print.PrintAttributes.MediaSize PRC_3; + field public static final android.print.PrintAttributes.MediaSize PRC_4; + field public static final android.print.PrintAttributes.MediaSize PRC_5; + field public static final android.print.PrintAttributes.MediaSize PRC_6; + field public static final android.print.PrintAttributes.MediaSize PRC_7; + field public static final android.print.PrintAttributes.MediaSize PRC_8; + field public static final android.print.PrintAttributes.MediaSize PRC_9; + field public static final android.print.PrintAttributes.MediaSize ROC_16K; + field public static final android.print.PrintAttributes.MediaSize ROC_8K; } public static final class PrintAttributes.Resolution { diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 3e4795c08957..bf2a1e485f41 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -65,7 +65,7 @@ public class AppOpsManager { // when adding one of these: // - increment _NUM_OP - // - add rows to sOpToSwitch, sOpNames, sOpPerms + // - add rows to sOpToSwitch, sOpNames, sOpPerms, sOpDefaultMode // - add descriptive strings to Settings/res/values/arrays.xml // - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app) @@ -315,6 +315,55 @@ public class AppOpsManager { }; /** + * This specifies the default mode for each operation. + */ + private static int[] sOpDefaultMode = new int[] { + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + }; + + /** * Retrieve the op switch that controls the given operation. * @hide */ @@ -339,6 +388,14 @@ public class AppOpsManager { } /** + * Retrieve the default mode for the operation. + * @hide + */ + public static int opToDefaultMode(int op) { + return sOpDefaultMode[op]; + } + + /** * Class holding all of the operation information associated with an app. * @hide */ diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java index d88935330d4d..efe6b159d474 100644 --- a/core/java/android/print/PrintAttributes.java +++ b/core/java/android/print/PrintAttributes.java @@ -373,27 +373,208 @@ public final class PrintAttributes implements Parcelable { // North America - /** North America Letter media size: 8.5" x 11" */ + /** North America Letter media size: 8.5" x 11" (279mm x 216mm) */ public static final MediaSize NA_LETTER = new MediaSize("NA_LETTER", "android", R.string.mediaSize_na_letter, 8500, 11000); - /** North America Government-Letter media size: 8.0" x 10.5" */ + /** North America Government-Letter media size: 8.0" x 10.5" (203mm x 267mm) */ public static final MediaSize NA_GOVT_LETTER = new MediaSize("NA_GOVT_LETTER", "android", R.string.mediaSize_na_gvrnmt_letter, 8000, 10500); - /** North America Legal media size: 8.5" x 14" */ + /** North America Legal media size: 8.5" x 14" (216mm x 356mm) */ public static final MediaSize NA_LEGAL = new MediaSize("NA_LEGAL", "android", R.string.mediaSize_na_legal, 8500, 14000); - /** North America Junior Legal media size: 8.0" x 5.0" */ + /** North America Junior Legal media size: 8.0" x 5.0" (203mm × 127mm) */ public static final MediaSize NA_JUNIOR_LEGAL = new MediaSize("NA_JUNIOR_LEGAL", "android", R.string.mediaSize_na_junior_legal, 8000, 5000); - /** North America Ledger media size: 17" x 11" */ + /** North America Ledger media size: 17" x 11" (432mm × 279mm) */ public static final MediaSize NA_LEDGER = new MediaSize("NA_LEDGER", "android", R.string.mediaSize_na_ledger, 17000, 11000); - /** North America Tabloid media size: 11" x 17" */ + /** North America Tabloid media size: 11" x 17" (279mm × 432mm) */ public static final MediaSize NA_TBLOID = new MediaSize("NA_TABLOID", "android", R.string.mediaSize_na_tabloid, 11000, 17000); + /** North America Index Card 3x5 media size: 3" x 5" (76mm x 127mm) */ + public static final MediaSize NA_INDEX_3X5 = + new MediaSize("NA_INDEX_3X5", "android", + R.string.mediaSize_na_index_3x5, 3000, 5000); + /** North America Index Card 4x6 media size: 4" x 6" (102mm x 152mm) */ + public static final MediaSize NA_INDEX_4X6 = + new MediaSize("NA_INDEX_4X6", "android", + R.string.mediaSize_na_index_4x6, 4000, 6000); + /** North America Index Card 5x8 media size: 5" x 8" (127mm x 203mm) */ + public static final MediaSize NA_INDEX_5X8 = + new MediaSize("NA_INDEX_5X8", "android", + R.string.mediaSize_na_index_5x8, 5000, 8000); + /** North America Monarch media size: 7.25" x 10.5" (184mm x 267mm) */ + public static final MediaSize NA_MONARCH = + new MediaSize("NA_MONARCH", "android", + R.string.mediaSize_na_monarch, 7250, 10500); + /** North America Quarto media size: 8" x 10" (203mm x 254mm) */ + public static final MediaSize NA_QUARTO = + new MediaSize("NA_QUARTO", "android", + R.string.mediaSize_na_quarto, 8000, 10000); + /** North America Foolscap media size: 8" x 13" (203mm x 330mm) */ + public static final MediaSize NA_FOOLSCAP = + new MediaSize("NA_FOOLSCAP", "android", + R.string.mediaSize_na_foolscap, 8000, 13000); + + // Chinese + + /** Chinese ROC 8K media size: 270mm x 390mm (10.629" x 15.3543") */ + public static final MediaSize ROC_8K = + new MediaSize("ROC_8K", "android", + R.string.mediaSize_chinese_roc_8k, 10629, 15354); + /** Chinese ROC 16K media size: 195mm x 270mm (7.677" x 10.629") */ + public static final MediaSize ROC_16K = + new MediaSize("ROC_16K", "android", + R.string.mediaSize_chinese_roc_16k, 7677, 10629); + + /** Chinese PRC 1 media size: 102mm x 165mm (4.015" x 6.496") */ + public static final MediaSize PRC_1 = + new MediaSize("PRC_1", "android", + R.string.mediaSize_chinese_prc_1, 4015, 6496); + /** Chinese PRC 2 media size: 102mm x 176mm (4.015" x 6.929") */ + public static final MediaSize PRC_2 = + new MediaSize("PRC_2", "android", + R.string.mediaSize_chinese_prc_2, 4015, 6929); + /** Chinese PRC 3 media size: 125mm x 176mm (4.921" x 6.929") */ + public static final MediaSize PRC_3 = + new MediaSize("PRC_3", "android", + R.string.mediaSize_chinese_prc_3, 4921, 6929); + /** Chinese PRC 4 media size: 110mm x 208mm (4.330" x 8.189") */ + public static final MediaSize PRC_4 = + new MediaSize("PRC_4", "android", + R.string.mediaSize_chinese_prc_4, 4330, 8189); + /** Chinese PRC 5 media size: 110mm x 220mm (4.330" x 8.661") */ + public static final MediaSize PRC_5 = + new MediaSize("PRC_5", "android", + R.string.mediaSize_chinese_prc_5, 4330, 8661); + /** Chinese PRC 6 media size: 120mm x 320mm (4.724" x 12.599") */ + public static final MediaSize PRC_6 = + new MediaSize("PRC_6", "android", + R.string.mediaSize_chinese_prc_6, 4724, 12599); + /** Chinese PRC 7 media size: 160mm x 230mm (6.299" x 9.055") */ + public static final MediaSize PRC_7 = + new MediaSize("PRC_7", "android", + R.string.mediaSize_chinese_prc_7, 6299, 9055); + /** Chinese PRC 8 media size: 120mm x 309mm (4.724" x 12.165") */ + public static final MediaSize PRC_8 = + new MediaSize("PRC_8", "android", + R.string.mediaSize_chinese_prc_8, 4724, 12165); + /** Chinese PRC 9 media size: 229mm x 324mm (9.016" x 12.756") */ + public static final MediaSize PRC_9 = + new MediaSize("PRC_9", "android", + R.string.mediaSize_chinese_prc_9, 9016, 12756); + /** Chinese PRC 10 media size: 324mm x 458mm (12.756" x 18.032") */ + public static final MediaSize PRC_10 = + new MediaSize("PRC_10", "android", + R.string.mediaSize_chinese_prc_10, 12756, 18032); + + /** Chinese PRC 16k media size: 146mm x 215mm (5.749" x 8.465") */ + public static final MediaSize PRC_16k = + new MediaSize("PRC_16k", "android", + R.string.mediaSize_chinese_prc_16k, 5749, 8465); + /** Chinese Pa Kai media size: 267mm x 389mm (10.512" x 15.315") */ + public static final MediaSize OM_PA_KAI = + new MediaSize("OM_PA_KAI", "android", + R.string.mediaSize_chinese_om_pa_kai, 10512, 15315); + /** Chinese Dai Pa Kai media size: 275mm x 395mm (10.827" x 15.551") */ + public static final MediaSize OM_DAI_PA_KAI = + new MediaSize("OM_DAI_PA_KAI", "android", + R.string.mediaSize_chinese_om_dai_pa_kai, 10827, 15551); + /** Chinese Jurro Ku Kai media size: 198mm x 275mm (7.796" x 10.827") */ + public static final MediaSize OM_JUURO_KU_KAI = + new MediaSize("OM_JUURO_KU_KAI", "android", + R.string.mediaSize_chinese_om_jurro_ku_kai, 7796, 10827); + + // Japanese + + /** Japanese JIS B10 media size: 32mm x 45mm (1.259" x 1.772") */ + public static final MediaSize JIS_B10 = + new MediaSize("JIS_B10", "android", + R.string.mediaSize_japanese_jis_b10, 1259, 1772); + /** Japanese JIS B9 media size: 45mm x 64mm (1.772" x 2.52") */ + public static final MediaSize JIS_B9 = + new MediaSize("JIS_B9", "android", + R.string.mediaSize_japanese_jis_b9, 1772, 2520); + /** Japanese JIS B8 media size: 64mm x 91mm (2.52" x 3.583") */ + public static final MediaSize JIS_B8 = + new MediaSize("JIS_B8", "android", + R.string.mediaSize_japanese_jis_b8, 2520, 3583); + /** Japanese JIS B7 media size: 91mm x 128mm (3.583" x 5.049") */ + public static final MediaSize JIS_B7 = + new MediaSize("JIS_B7", "android", + R.string.mediaSize_japanese_jis_b7, 3583, 5049); + /** Japanese JIS B6 media size: 128mm x 182mm (5.049" x 7.165") */ + public static final MediaSize JIS_B6 = + new MediaSize("JIS_B6", "android", + R.string.mediaSize_japanese_jis_b6, 5049, 7165); + /** Japanese JIS B5 media size: 182mm x 257mm (7.165" x 10.118") */ + public static final MediaSize JIS_B5 = + new MediaSize("JIS_B5", "android", + R.string.mediaSize_japanese_jis_b5, 7165, 10118); + /** Japanese JIS B4 media size: 257mm x 364mm (10.118" x 14.331") */ + public static final MediaSize JIS_B4 = + new MediaSize("JIS_B4", "android", + R.string.mediaSize_japanese_jis_b4, 10118, 14331); + /** Japanese JIS B3 media size: 364mm x 515mm (14.331" x 20.276") */ + public static final MediaSize JIS_B3 = + new MediaSize("JIS_B3", "android", + R.string.mediaSize_japanese_jis_b3, 14331, 20276); + /** Japanese JIS B2 media size: 515mm x 728mm (20.276" x 28.661") */ + public static final MediaSize JIS_B2 = + new MediaSize("JIS_B2", "android", + R.string.mediaSize_japanese_jis_b2, 20276, 28661); + /** Japanese JIS B1 media size: 728mm x 1030mm (28.661" x 40.551") */ + public static final MediaSize JIS_B1 = + new MediaSize("JIS_B1", "android", + R.string.mediaSize_japanese_jis_b1, 28661, 40551); + /** Japanese JIS B0 media size: 1030mm x 1456mm (40.551" x 57.323") */ + public static final MediaSize JIS_B0 = + new MediaSize("JIS_B0", "android", + R.string.mediaSize_japanese_jis_b0, 40551, 57323); + + /** Japanese JIS Exec media size: 216mm x 330mm (8.504" x 12.992") */ + public static final MediaSize JIS_EXEC = + new MediaSize("JIS_EXEC", "android", + R.string.mediaSize_japanese_jis_exec, 8504, 12992); + + /** Japanese Chou4 media size: 90mm x 205mm (3.543" x 8.071") */ + public static final MediaSize JPN_CHOU4 = + new MediaSize("JPN_CHOU4", "android", + R.string.mediaSize_japanese_chou4, 3543, 8071); + /** Japanese Chou3 media size: 120mm x 235mm (4.724" x 9.252") */ + public static final MediaSize JPN_CHOU3 = + new MediaSize("JPN_CHOU3", "android", + R.string.mediaSize_japanese_chou3, 4724, 9252); + /** Japanese Chou2 media size: 111.1mm x 146mm (4.374" x 5.748") */ + public static final MediaSize JPN_CHOU2 = + new MediaSize("JPN_CHOU2", "android", + R.string.mediaSize_japanese_chou2, 4374, 5748); + + /** Japanese Hagaki media size: 100mm x 148mm (3.937" x 5.827") */ + public static final MediaSize JPN_HAGAKI = + new MediaSize("JPN_HAGAKI", "android", + R.string.mediaSize_japanese_hagaki, 3937, 5827); + /** Japanese Oufuku media size: 148mm x 200mm (5.827" x 7.874") */ + public static final MediaSize JPN_OUFUKU = + new MediaSize("JPN_OUFUKU", "android", + R.string.mediaSize_japanese_oufuku, 5827, 7874); + + /** Japanese Kahu media size: 240mm x 322.1mm (9.449" x 12.681") */ + public static final MediaSize JPN_KAHU = + new MediaSize("JPN_KAHU", "android", + R.string.mediaSize_japanese_kahu, 9449, 12681); + /** Japanese Kaku2 media size: 240mm x 332mm (9.449" x 13.071") */ + public static final MediaSize JPN_KAKU2 = + new MediaSize("JPN_KAKU2", "android", + R.string.mediaSize_japanese_kaku2, 9449, 13071); + + /** Japanese You4 media size: 105mm x 235mm (4.134" x 9.252") */ + public static final MediaSize JPN_YOU4 = + new MediaSize("JPN_YOU4", "android", + R.string.mediaSize_japanese_you4, 4134, 9252); private final String mId; /**@hide */ diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index c8312e3adec6..6c6635dfd531 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4355,6 +4355,12 @@ public final class Settings { public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component"; /** + * Specifies the package name currently configured to be the primary sms application + * @hide + */ + public static final String SMS_DEFAULT_APPLICATION = "sms_default_application"; + + /** * Name of a package that the current user has explicitly allowed to see all of that * user's notifications. * diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 969c94babd68..7efcb6ec019e 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -1639,6 +1639,8 @@ public class ActionBarView extends AbsActionBarView { @Override public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { + TransitionManager.beginDelayedTransition(ActionBarView.this, sTransition); + mExpandedActionView = item.getActionView(); mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources())); mCurrentExpandedItem = item; @@ -1666,6 +1668,8 @@ public class ActionBarView extends AbsActionBarView { @Override public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { + TransitionManager.beginDelayedTransition(ActionBarView.this, sTransition); + // Do this before detaching the actionview from the hierarchy, in case // it needs to dismiss the soft keyboard, etc. if (mExpandedActionView instanceof CollapsibleActionView) { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 499a930d86b2..c2a830d4f21a 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1103,6 +1103,13 @@ android:description="@string/permdesc_use_sip" android:label="@string/permlab_use_sip" /> + <!-- Allows an application to request CallHandlerService implementations. --> + <permission android:name="android.permission.BIND_CALL_SERVICE" + android:permissionGroup="android.permission-group.PHONE_CALLS" + android:protectionLevel="system|signature" + android:description="@string/permdesc_bind_call_service" + android:label="@string/permlab_bind_call_service" /> + <!-- ================================== --> <!-- Permissions for sdcard interaction --> <!-- ================================== --> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 98368a162aaf..99b703b86c76 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1898,6 +1898,11 @@ <string name="permdesc_use_sip">Allows the app to use the SIP service to make/receive Internet calls.</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_bind_call_service">interact with in-call screen</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_bind_call_service">Allows the app to control when and how the user sees the in-call screen.</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_readNetworkUsageHistory">read historical network usage</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_readNetworkUsageHistory">Allows the app to read historical network usage for specific networks and apps.</string> @@ -4296,19 +4301,111 @@ <!-- ISO (European standard) C10 media (paper) size: 1.10" x 1.57" --> <string name="mediaSize_iso_c10">ISO C10</string> - <!-- North America Letter media (paper) size: 8.5" × 11" --> + <!-- North America Letter media (paper) size: 8.5" × 11" (279mm x 216mm) --> <string name="mediaSize_na_letter">Letter</string> - <!-- North America Government Letter media (paper) size: 8.0" × 10.5" --> + <!-- North America Government Letter media (paper) size: 8.0" × 10.5" (203mm x 267mm) --> <string name="mediaSize_na_gvrnmt_letter">Government Letter</string> - <!-- North America Legal media (paper) size: 8.5" × 14" --> + <!-- North America Legal media (paper) size: 8.5" × 14" (216mm x 356mm) --> <string name="mediaSize_na_legal">Legal</string> - <!-- North America Junior Legal media (paper) size: 8.0" × 5.0" --> + <!-- North America Junior Legal media (paper) size: 8.0" × 5.0" (203mm × 127mm) --> <string name="mediaSize_na_junior_legal">Junior Legal</string> - <!-- North America Ledger media (paper) size: 17" × 11" --> + <!-- North America Ledger media (paper) size: 17" × 11" (432mm × 279mm) --> <string name="mediaSize_na_ledger">Ledger</string> - <!-- North America Tabloid media (paper) size: 11" × 17" --> + <!-- North America Tabloid media (paper) size: 11" × 17" (279mm × 432mm) --> <string name="mediaSize_na_tabloid">Tabloid</string> + <!-- North America Index Card 3x5 media (paper) size: 3" x 5" (76mm x 127mm) --> + <string name="mediaSize_na_index_3x5">Index Card 3x5</string> + <!-- North America Index Card 4x6 media (paper) size: 4" x 6" (102mm x 152mm) --> + <string name="mediaSize_na_index_4x6">Index Card 4x6</string> + <!-- North America Index Card 5x8 media (paper) size: 5" x 8" (127mm x 203mm) --> + <string name="mediaSize_na_index_5x8">Index Card 5x8</string> + <!-- North America Monarch media (paper) size: 7.25" x 10.5" (184mm x 267mm) --> + <string name="mediaSize_na_monarch">Monarch</string> + <!-- North America Quarto media (paper) size: 8" x 10" (203mm x 254mm) --> + <string name="mediaSize_na_quarto">Quarto</string> + <!-- North America Foolscap media (paper) size: 8" x 13" (203mm x 330mm) --> + <string name="mediaSize_na_foolscap">Foolscap</string> + + <!-- Chinese Roc 8k media (paper) size: 270mm x 390mm (10.629" x 15.3543") --> + <string name="mediaSize_chinese_roc_8k">ROC 8K</string> + <!-- Chinese Roc 16k media (paper) size: 195mm x 270mm (7.677" x 10.629") --> + <string name="mediaSize_chinese_roc_16k">ROC 16K</string> + + <!-- Chinese PRC 1 media (paper) size: 102mm x 165mm (4.015" x 6.496") --> + <string name="mediaSize_chinese_prc_1">PRC 1</string> + <!-- Chinese PRC 2 media (paper) size: 102mm x 176mm (4.015" x 6.929") --> + <string name="mediaSize_chinese_prc_2">PRC 2</string> + <!-- Chinese PRC 3 media (paper) size: 125mm x 176mm (4.921" x 6.929") --> + <string name="mediaSize_chinese_prc_3">PRC 3</string> + <!-- Chinese PRC 4 media (paper) size: 110mm x 208mm (4.330" x 8.189") --> + <string name="mediaSize_chinese_prc_4">PRC 4</string> + <!-- Chinese PRC 5 media (paper) size: 110mm x 220mm (4.330" x 8.661") --> + <string name="mediaSize_chinese_prc_5">PRC 5</string> + <!-- Chinese PRC 6 media (paper) size: 120mm x 320mm (4.724" x 12.599") --> + <string name="mediaSize_chinese_prc_6">PRC 6</string> + <!-- Chinese PRC 7 media (paper) size: 160mm x 230mm (6.299" x 9.055") --> + <string name="mediaSize_chinese_prc_7">PRC 7</string> + <!-- Chinese PRC 8 media (paper) size: 120mm x 309mm (4.724" x 12.165") --> + <string name="mediaSize_chinese_prc_8">PRC 8</string> + <!-- Chinese PRC 9 media (paper) size: 229mm x 324mm (9.016" x 12.756") --> + <string name="mediaSize_chinese_prc_9">PRC 9</string> + <!-- Chinese PRC 10 media (paper) size: 324mm x 458mm (12.756" x 18.032") --> + <string name="mediaSize_chinese_prc_10">PRC 10</string> + + <!-- Chinese RPC 16K media (paper) size: 146mm x 215mm (5.749" x 8.465") --> + <string name="mediaSize_chinese_prc_16k">PRC 16K</string> + <!-- Chinese Pa Kai media (paper) size: 146mm x 215mm (5.749" x 8.465") --> + <string name="mediaSize_chinese_om_pa_kai">Pa Kai</string> + <!-- Chinese Dai Pa Kai media (paper) size: 275mm x 395mm (10.827" x 15.551") --> + <string name="mediaSize_chinese_om_dai_pa_kai">Dai Pa Kai</string> + <!-- Chinese Jurro Ku Kai media (paper) size: 275mm x 395mm (10.827" x 15.551") --> + <string name="mediaSize_chinese_om_jurro_ku_kai">Jurro Ku Kai</string> + + <!-- Japanese JIS B10 media (paper) size: 32mm x 45mm (1.259" x 1.772") --> + <string name="mediaSize_japanese_jis_b10">JIS B10</string> + <!-- Japanese JIS B9 media (paper) size: 45mm x 64mm (1.772" x 2.52") --> + <string name="mediaSize_japanese_jis_b9">JIS B9</string> + <!-- Japanese JIS B8 media (paper) size: 64mm x 91mm (2.52" x 3.583") --> + <string name="mediaSize_japanese_jis_b8">JIS B8</string> + <!-- Japanese JIS B7 media (paper) size: 91mm x 128mm (3.583" x 5.049") --> + <string name="mediaSize_japanese_jis_b7">JIS B7</string> + <!-- Japanese JIS B6 media (paper) size: 128mm x 182mm (5.049" x 7.165") --> + <string name="mediaSize_japanese_jis_b6">JIS B6</string> + <!-- Japanese JIS B5 media (paper) size: 182mm x 257mm (7.165" x 10.118") --> + <string name="mediaSize_japanese_jis_b5">JIS B5</string> + <!-- Japanese JIS B4 media (paper) size: 257mm x 364mm (10.118" x 14.331") --> + <string name="mediaSize_japanese_jis_b4">JIS B4</string> + <!-- Japanese JIS B3 media (paper) size: 364mm x 515mm (14.331" x 20.276") --> + <string name="mediaSize_japanese_jis_b3">JIS B3</string> + <!-- Japanese JIS B2 media (paper) size: 515mm x 728mm (20.276" x 28.661") --> + <string name="mediaSize_japanese_jis_b2">JIS B2</string> + <!-- Japanese JIS B1 media (paper) size: 728mm x 1030mm (28.661" x 40.551") --> + <string name="mediaSize_japanese_jis_b1">JIS B1</string> + <!-- Japanese JIS B0 media (paper) size: 1030mm x 1456mm (40.551" x 57.323") --> + <string name="mediaSize_japanese_jis_b0">JIS B0</string> + + <!-- Japanese JIS Exec media (paper) size: 216mm x 330mm (8.504" x 12.992") --> + <string name="mediaSize_japanese_jis_exec">JIS Exec</string> + + <!-- Japanese Chou4 media (paper) size: 90mm x 205mm (3.543" x 8.071") --> + <string name="mediaSize_japanese_chou4">Chou4</string> + <!-- Japanese Chou3 media (paper) size: 120mm x 235mm (4.724" x 9.252") --> + <string name="mediaSize_japanese_chou3">Chou3</string> + <!-- Japanese Chou2 media (paper) size: 111.1mm x 146mm (4.374" x 5.748") --> + <string name="mediaSize_japanese_chou2">Chou2</string> + + <!-- Japanese Hagaki media (paper) size: 100mm x 148mm (3.937" x 5.827") --> + <string name="mediaSize_japanese_hagaki">Hagaki </string> + <!-- Japanese Oufuku media (paper) size: 148mm x 200mm (5.827" x 7.874") --> + <string name="mediaSize_japanese_oufuku">Oufuku </string> + <!-- Japanese Kahu media (paper) size: 240mm x 322.1mm (9.449" x 12.681") --> + <string name="mediaSize_japanese_kahu">Kahu</string> + <!-- Japanese Kaku2 media (paper) size: 240mm x 332mm (9.449" x 13.071") --> + <string name="mediaSize_japanese_kaku2">Kaku2</string> + <!-- Japanese You4 media (paper) size: 105mm x 235mm (4.134" x 9.252") --> + <string name="mediaSize_japanese_you4">You4</string> + <!-- Write fail reason: printing was cancelled.[CHAR LIMIT=none] --> <string name="write_fail_reason_cancelled">Cancelled</string> <!-- Write fail reason: couldn't write the printed content. [CHAR LIMIT=none] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 9cb0a371ce8d..e82c0e11944b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -878,6 +878,48 @@ <java-symbol type="string" name="mediaSize_na_junior_legal" /> <java-symbol type="string" name="mediaSize_na_ledger" /> <java-symbol type="string" name="mediaSize_na_tabloid" /> + <java-symbol type="string" name="mediaSize_na_index_3x5" /> + <java-symbol type="string" name="mediaSize_na_index_4x6" /> + <java-symbol type="string" name="mediaSize_na_index_5x8" /> + <java-symbol type="string" name="mediaSize_na_monarch" /> + <java-symbol type="string" name="mediaSize_na_quarto" /> + <java-symbol type="string" name="mediaSize_na_foolscap" /> + <java-symbol type="string" name="mediaSize_chinese_roc_8k" /> + <java-symbol type="string" name="mediaSize_chinese_roc_16k" /> + <java-symbol type="string" name="mediaSize_chinese_prc_1" /> + <java-symbol type="string" name="mediaSize_chinese_prc_2" /> + <java-symbol type="string" name="mediaSize_chinese_prc_3" /> + <java-symbol type="string" name="mediaSize_chinese_prc_4" /> + <java-symbol type="string" name="mediaSize_chinese_prc_5" /> + <java-symbol type="string" name="mediaSize_chinese_prc_6" /> + <java-symbol type="string" name="mediaSize_chinese_prc_7" /> + <java-symbol type="string" name="mediaSize_chinese_prc_8" /> + <java-symbol type="string" name="mediaSize_chinese_prc_9" /> + <java-symbol type="string" name="mediaSize_chinese_prc_10" /> + <java-symbol type="string" name="mediaSize_chinese_prc_16k" /> + <java-symbol type="string" name="mediaSize_chinese_om_pa_kai" /> + <java-symbol type="string" name="mediaSize_chinese_om_dai_pa_kai" /> + <java-symbol type="string" name="mediaSize_chinese_om_jurro_ku_kai" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b10" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b9" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b8" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b7" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b6" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b5" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b4" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b3" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b2" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b1" /> + <java-symbol type="string" name="mediaSize_japanese_jis_b0" /> + <java-symbol type="string" name="mediaSize_japanese_jis_exec" /> + <java-symbol type="string" name="mediaSize_japanese_chou4" /> + <java-symbol type="string" name="mediaSize_japanese_chou3" /> + <java-symbol type="string" name="mediaSize_japanese_chou2" /> + <java-symbol type="string" name="mediaSize_japanese_hagaki" /> + <java-symbol type="string" name="mediaSize_japanese_oufuku" /> + <java-symbol type="string" name="mediaSize_japanese_kahu" /> + <java-symbol type="string" name="mediaSize_japanese_kaku2" /> + <java-symbol type="string" name="mediaSize_japanese_you4" /> <java-symbol type="string" name="reason_unknown" /> <java-symbol type="string" name="restr_pin_enter_admin_pin" /> <java-symbol type="string" name="restr_pin_enter_pin" /> diff --git a/media/java/android/media/IRemoteControlClient.aidl b/media/java/android/media/IRemoteControlClient.aidl index dd729b4011c8..48079f28dabf 100644 --- a/media/java/android/media/IRemoteControlClient.aidl +++ b/media/java/android/media/IRemoteControlClient.aidl @@ -17,6 +17,7 @@ package android.media; import android.graphics.Bitmap; import android.media.IRemoteControlDisplay; +import android.media.Rating; /** * @hide @@ -49,5 +50,5 @@ oneway interface IRemoteControlClient void setBitmapSizeForDisplay(IRemoteControlDisplay rcd, int w, int h); void setWantsSyncForDisplay(IRemoteControlDisplay rcd, boolean wantsSync); void seekTo(int clientGeneration, long timeMs); - void updateMetadata(int clientGeneration, int key, long value); + void updateMetadata(int clientGeneration, int key, in Rating value); }
\ No newline at end of file diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java index ab686e6d43a3..34dc58048027 100644 --- a/media/java/android/media/MediaFocusControl.java +++ b/media/java/android/media/MediaFocusControl.java @@ -2093,8 +2093,11 @@ public class MediaFocusControl implements OnFinished { if ((mCurrentRcClient != null) && (mCurrentRcClientGen == genId)) { try { switch (key) { - case RemoteControlClient.MetadataEditor.LONG_KEY_RATING_BY_USER: - mCurrentRcClient.updateMetadata(genId, key, value); + case RemoteControlClient.MetadataEditor.RATING_KEY_BY_USER: + // TODO handle rating update, placeholder code here that sends + // an unrated percent-based rating + mCurrentRcClient.updateMetadata(genId, key, + Rating.newUnratedRating(Rating.RATING_PERCENTAGE)); break; default: Log.e(TAG, "unhandled metadata key " + key + " update for RCC " diff --git a/media/java/android/media/MediaMetadataEditor.java b/media/java/android/media/MediaMetadataEditor.java new file mode 100644 index 000000000000..b601016ae5d8 --- /dev/null +++ b/media/java/android/media/MediaMetadataEditor.java @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2013 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.media; + +import android.graphics.Bitmap; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; +import android.util.SparseIntArray; + +/** + * An abstract class for editing and storing metadata that can be published by + * {@link RemoteControlClient}. See the {@link RemoteControlClient#editMetadata(boolean)} + * method to instantiate a {@link RemoteControlClient.MetadataEditor} object. + */ +public abstract class MediaMetadataEditor { + + private final static String TAG = "MediaMetadataEditor"; + /** + * @hide + */ + protected MediaMetadataEditor() { + } + + // Public keys for metadata used by RemoteControlClient and RemoteController. + // Note that these keys are defined here, and not in MediaMetadataRetriever + // because they are not supported by the MediaMetadataRetriever features. + /** + * The metadata key for the content artwork / album art. + */ + public final static int BITMAP_KEY_ARTWORK = + RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK; + + /** + * The metadata key for the content's average rating, not the user's rating. + * The value associated with this key is a {@link Rating} instance. + * @see #RATING_KEY_BY_USER + */ + public final static int RATING_KEY_BY_OTHERS = 101; + + /** + * The metadata key for the content's user rating. + * The value associated with this key is a {@link Rating} instance. + * This key can be flagged as "editable" (with {@link #addEditableKey(int)}) to enable + * receiving user rating values through the + * {@link android.media.RemoteControlClient.OnMetadataUpdateListener} interface. + */ + public final static int RATING_KEY_BY_USER = 0x10000001; + + /** + * @hide + * Editable key mask + */ + public final static int KEY_EDITABLE_MASK = 0x1FFFFFFF; + + + /** + * Applies all of the metadata changes that have been set since the MediaMetadataEditor instance + * was created or since {@link #clear()} was called. + */ + public abstract void apply(); + + + /** + * @hide + * Mask of editable keys. + */ + protected long mEditableKeys; + + /** + * @hide + */ + protected boolean mMetadataChanged = false; + + /** + * @hide + */ + protected boolean mApplied = false; + + /** + * @hide + */ + protected boolean mArtworkChanged = false; + + /** + * @hide + */ + protected Bitmap mEditorArtwork; + + /** + * @hide + */ + protected Bundle mEditorMetadata; + + + /** + * Clears all the pending metadata changes set since the MediaMetadataEditor instance was + * created or since this method was last called. + * Note that clearing the metadata doesn't reset the editable keys + * (use {@link #removeEditableKeys()} instead). + */ + public synchronized void clear() { + if (mApplied) { + Log.e(TAG, "Can't clear a previously applied MediaMetadataEditor"); + return; + } + mEditorMetadata.clear(); + mEditorArtwork = null; + } + + /** + * Flags the given key as being editable. + * This should only be used by metadata publishers, such as {@link RemoteControlClient}, + * which will declare the metadata field as eligible to be updated, with new values + * received through the {@link RemoteControlClient.OnMetadataUpdateListener} interface. + * @param key the type of metadata that can be edited. The supported key is + * {@link #RATING_KEY_BY_USER}. + */ + public synchronized void addEditableKey(int key) { + if (mApplied) { + Log.e(TAG, "Can't change editable keys of a previously applied MetadataEditor"); + return; + } + // only one editable key at the moment, so we're not wasting memory on an array + // of editable keys to check the validity of the key, just hardcode the supported key. + if (key == RATING_KEY_BY_USER) { + mEditableKeys |= (KEY_EDITABLE_MASK & key); + mMetadataChanged = true; + } else { + Log.e(TAG, "Metadata key " + key + " cannot be edited"); + } + } + + /** + * Causes all metadata fields to be read-only. + */ + public synchronized void removeEditableKeys() { + if (mApplied) { + Log.e(TAG, "Can't remove all editable keys of a previously applied MetadataEditor"); + return; + } + if (mEditableKeys != 0) { + mEditableKeys = 0; + mMetadataChanged = true; + } + } + + /** + * Retrieves the keys flagged as editable. + * @return null if there are no editable keys, or an array containing the keys. + */ + public synchronized int[] getEditableKeys() { + // only one editable key supported here + if (mEditableKeys == RATING_KEY_BY_USER) { + int[] keys = { RATING_KEY_BY_USER }; + return keys; + } else { + return null; + } + } + + /** + * Adds textual information. + * Note that none of the information added after {@link #apply()} has been called, + * will be available to consumers of metadata stored by the MediaMetadataEditor. + * @param key The identifier of a the metadata field to set. Valid values are + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUM}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ARTIST}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_AUTHOR}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPILATION}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPOSER}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DATE}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_GENRE}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER}. + * @param value The text for the given key, or {@code null} to signify there is no valid + * information for the field. + * @return Returns a reference to the same MediaMetadataEditor object, so you can chain put + * calls together. + */ + public synchronized MediaMetadataEditor putString(int key, String value) + throws IllegalArgumentException { + if (mApplied) { + Log.e(TAG, "Can't edit a previously applied MediaMetadataEditor"); + return this; + } + if (METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID) != METADATA_TYPE_STRING) { + throw(new IllegalArgumentException("Invalid type 'String' for key "+ key)); + } + mEditorMetadata.putString(String.valueOf(key), value); + mMetadataChanged = true; + return this; + } + + /** + * Adds numerical information. + * Note that none of the information added after {@link #apply()} has been called + * will be available to consumers of metadata stored by the MediaMetadataEditor. + * @param key the identifier of a the metadata field to set. Valid values are + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}, + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} (with a value + * expressed in milliseconds), + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}. + * @param value The long value for the given key + * @return Returns a reference to the same MediaMetadataEditor object, so you can chain put + * calls together. + * @throws IllegalArgumentException + */ + public synchronized MediaMetadataEditor putLong(int key, long value) + throws IllegalArgumentException { + if (mApplied) { + Log.e(TAG, "Can't edit a previously applied MediaMetadataEditor"); + return this; + } + if (METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID) != METADATA_TYPE_LONG) { + throw(new IllegalArgumentException("Invalid type 'long' for key "+ key)); + } + mEditorMetadata.putLong(String.valueOf(key), value); + mMetadataChanged = true; + return this; + } + + /** + * Adds image. + * @param key the identifier of the bitmap to set. The only valid value is + * {@link #BITMAP_KEY_ARTWORK} + * @param bitmap The bitmap for the artwork, or null if there isn't any. + * @return Returns a reference to the same MediaMetadataEditor object, so you can chain put + * calls together. + * @throws IllegalArgumentException + * @see android.graphics.Bitmap + */ + public synchronized MediaMetadataEditor putBitmap(int key, Bitmap bitmap) + throws IllegalArgumentException { + if (mApplied) { + Log.e(TAG, "Can't edit a previously applied MediaMetadataEditor"); + return this; + } + if (key != BITMAP_KEY_ARTWORK) { + throw(new IllegalArgumentException("Invalid type 'Bitmap' for key "+ key)); + } + mEditorArtwork = bitmap; + mArtworkChanged = true; + return this; + } + + /** + * Adds information stored as an instance. + * Note that none of the information added after {@link #apply()} has been called + * will be available to consumers of metadata stored by the MediaMetadataEditor. + * @param key the identifier of a the metadata field to set. Valid keys for a: + * <ul> + * <li>{@link Bitmap} object are {@link #BITMAP_KEY_ARTWORK},</li> + * <li>{@link String} object are the same as for {@link #putString(int, String)}</li> + * <li>{@link Long} object are the same as for {@link #putLong(int, long)}</li> + * <li>{@link Rating} object are {@link #RATING_KEY_BY_OTHERS} + * and {@link #RATING_KEY_BY_USER}.</li> + * </ul> + * @param obj the metadata to add. + * @return Returns a reference to the same MediaMetadataEditor object, so you can chain put + * calls together. + * @throws IllegalArgumentException + */ + public synchronized MediaMetadataEditor putObject(int key, Object value) + throws IllegalArgumentException { + if (mApplied) { + Log.e(TAG, "Can't edit a previously applied MediaMetadataEditor"); + return this; + } + switch(METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID)) { + case METADATA_TYPE_LONG: + if (value instanceof Long) { + return putLong(key, ((Long)value).longValue()); + } else { + throw(new IllegalArgumentException("Not a non-null Long for key "+ key)); + } + case METADATA_TYPE_STRING: + if ((value == null) || (value instanceof String)) { + return putString(key, (String) value); + } else { + throw(new IllegalArgumentException("Not a String for key "+ key)); + } + case METADATA_TYPE_RATING: + mEditorMetadata.putParcelable(String.valueOf(key), (Parcelable)value); + mMetadataChanged = true; + break; + case METADATA_TYPE_BITMAP: + if ((value == null) || (value instanceof Bitmap)) { + return putBitmap(key, (Bitmap) value); + } else { + throw(new IllegalArgumentException("Not a Bitmap for key "+ key)); + } + default: + throw(new IllegalArgumentException("Invalid key "+ key)); + } + return this; + } + + + /** + * Returns the long value for the key. + * @param key one of the keys supported in {@link #putLong(int, long)} + * @param defaultValue the value returned if the key is not present + * @return the long value for the key, or the supplied default value if the key is not present + * @throws IllegalArgumentException + */ + public synchronized long getLong(int key, long defaultValue) + throws IllegalArgumentException { + if (METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID) != METADATA_TYPE_LONG) { + throw(new IllegalArgumentException("Invalid type 'long' for key "+ key)); + } + return mEditorMetadata.getLong(String.valueOf(key), defaultValue); + } + + /** + * Returns the {@link String} value for the key. + * @param key one of the keys supported in {@link #putString(int, String)} + * @param defaultValue the value returned if the key is not present + * @return the {@link String} value for the key, or the supplied default value if the key is + * not present + * @throws IllegalArgumentException + */ + public synchronized String getString(int key, String defaultValue) + throws IllegalArgumentException { + if (METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID) != METADATA_TYPE_STRING) { + throw(new IllegalArgumentException("Invalid type 'String' for key "+ key)); + } + return mEditorMetadata.getString(String.valueOf(key), defaultValue); + } + + /** + * Returns the {@link Bitmap} value for the key. + * @param key the {@link #BITMAP_KEY_ARTWORK} key + * @param defaultValue the value returned if the key is not present + * @return the {@link Bitmap} value for the key, or the supplied default value if the key is + * not present + * @throws IllegalArgumentException + */ + public synchronized Bitmap getBitmap(int key, Bitmap defaultValue) + throws IllegalArgumentException { + if (key != BITMAP_KEY_ARTWORK) { + throw(new IllegalArgumentException("Invalid type 'Bitmap' for key "+ key)); + } + return (mEditorArtwork != null ? mEditorArtwork : defaultValue); + } + + /** + * Returns an object representation of the value for the key + * @param key one of the keys supported in {@link #putObject(int, Object)} + * @param defaultValue the value returned if the key is not present + * @return the object for the key, as a {@link Long}, {@link Bitmap}, {@link String}, or + * {@link Rating} depending on the key value, or the supplied default value if the key is + * not present + * @throws IllegalArgumentException + */ + public synchronized Object getObject(int key, Object defaultValue) + throws IllegalArgumentException { + switch (METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID)) { + case METADATA_TYPE_LONG: + if (mEditorMetadata.containsKey(String.valueOf(key))) { + return mEditorMetadata.getLong(String.valueOf(key)); + } else { + return defaultValue; + } + case METADATA_TYPE_STRING: + if (mEditorMetadata.containsKey(String.valueOf(key))) { + return mEditorMetadata.getString(String.valueOf(key)); + } else { + return defaultValue; + } + case METADATA_TYPE_RATING: + if (mEditorMetadata.containsKey(String.valueOf(key))) { + return mEditorMetadata.getParcelable(String.valueOf(key)); + } else { + return defaultValue; + } + case METADATA_TYPE_BITMAP: + // only one key for Bitmap supported, value is not stored in mEditorMetadata Bundle + if (key == BITMAP_KEY_ARTWORK) { + return (mEditorArtwork != null ? mEditorArtwork : defaultValue); + } // else: fall through to invalid key handling + default: + throw(new IllegalArgumentException("Invalid key "+ key)); + } + } + + + /** + * @hide + */ + protected static final int METADATA_TYPE_INVALID = -1; + /** + * @hide + */ + protected static final int METADATA_TYPE_LONG = 0; + + /** + * @hide + */ + protected static final int METADATA_TYPE_STRING = 1; + + /** + * @hide + */ + protected static final int METADATA_TYPE_BITMAP = 2; + + /** + * @hide + */ + protected static final int METADATA_TYPE_RATING = 3; + + /** + * @hide + */ + protected static final SparseIntArray METADATA_KEYS_TYPE; + + static { + METADATA_KEYS_TYPE = new SparseIntArray(17); + // NOTE: if adding to the list below, make sure you increment the array initialization size + // keys with long values + METADATA_KEYS_TYPE.put( + MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, METADATA_TYPE_LONG); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_DURATION, METADATA_TYPE_LONG); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_YEAR, METADATA_TYPE_LONG); + // keys with String values + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_ALBUM, METADATA_TYPE_STRING); + METADATA_KEYS_TYPE.put( + MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, METADATA_TYPE_STRING); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_TITLE, METADATA_TYPE_STRING); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_ARTIST, METADATA_TYPE_STRING); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_AUTHOR, METADATA_TYPE_STRING); + METADATA_KEYS_TYPE.put( + MediaMetadataRetriever.METADATA_KEY_COMPILATION, METADATA_TYPE_STRING); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_COMPOSER, METADATA_TYPE_STRING); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_DATE, METADATA_TYPE_STRING); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_GENRE, METADATA_TYPE_STRING); + METADATA_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_WRITER, METADATA_TYPE_STRING); + // keys with Bitmap values + METADATA_KEYS_TYPE.put(BITMAP_KEY_ARTWORK, METADATA_TYPE_BITMAP); + // keys with Rating values + METADATA_KEYS_TYPE.put(RATING_KEY_BY_OTHERS, METADATA_TYPE_RATING); + METADATA_KEYS_TYPE.put(RATING_KEY_BY_USER, METADATA_TYPE_RATING); + } +} diff --git a/media/java/android/media/Rating.aidl b/media/java/android/media/Rating.aidl new file mode 100644 index 000000000000..1dc336aeb79d --- /dev/null +++ b/media/java/android/media/Rating.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2013 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.media; + +parcelable Rating; diff --git a/media/java/android/media/Rating.java b/media/java/android/media/Rating.java new file mode 100644 index 000000000000..48443ffe4fc3 --- /dev/null +++ b/media/java/android/media/Rating.java @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2013 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.media; + +import android.graphics.Bitmap; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +/** + * A class to encapsulate rating information used as content metadata. + * A rating is defined by its rating style (see {@link #RATING_HEART}, + * {@link #RATING_THUMB_UP_DOWN}, {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, + * {@link #RATING_5_STARS} or {@link #RATING_PERCENTAGE}) and the actual rating value (which may + * be defined as "unrated"), both of which are defined when the rating instance is constructed + * through one of the factory methods. + */ +public final class Rating implements Parcelable { + + private final static String TAG = "Rating"; + + /** + * A rating style with a single degree of rating, "heart" vs "no heart". Can be used to + * indicate the content referred to is a favorite (or not). + */ + public final static int RATING_HEART = 1; + + /** + * A rating style for "thumb up" vs "thumb down". + */ + public final static int RATING_THUMB_UP_DOWN = 2; + + /** + * A rating style with 0 to 3 stars. + */ + public final static int RATING_3_STARS = 3; + + /** + * A rating style with 0 to 4 stars. + */ + public final static int RATING_4_STARS = 4; + + /** + * A rating style with 0 to 5 stars. + */ + public final static int RATING_5_STARS = 5; + + /** + * A rating style expressed as a percentage. + */ + public final static int RATING_PERCENTAGE = 6; + + private final static float RATING_NOT_RATED = -1.0f; + + private final int mRatingStyle; + + private final float mRatingValue; + + private Rating(int ratingStyle, float rating) { + mRatingStyle = ratingStyle; + mRatingValue = rating; + } + + @Override + public int describeContents() { + return mRatingStyle; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mRatingStyle); + dest.writeFloat(mRatingValue); + } + + public static final Parcelable.Creator<Rating> CREATOR + = new Parcelable.Creator<Rating>() { + /** + * Rebuilds a Rating previously stored with writeToParcel(). + * @param p Parcel object to read the Rating from + * @return a new Rating created from the data in the parcel + */ + public Rating createFromParcel(Parcel p) { + return new Rating(p.readInt(), p.readFloat()); + } + public Rating[] newArray(int size) { + return new Rating[size]; + } + }; + + /** + * Return a Rating instance with no rating. + * Create and return a new Rating instance with no rating known for the given + * rating style. + * @param ratingStyle one of {@link #RATING_HEART}, {@link #RATING_THUMB_UP_DOWN}, + * {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS}, + * or {@link #RATING_PERCENTAGE}. + * @return null if an invalid rating style is passed, a new Rating instance otherwise. + */ + public static Rating newUnratedRating(int ratingStyle) { + switch(ratingStyle) { + case RATING_HEART: + case RATING_THUMB_UP_DOWN: + case RATING_3_STARS: + case RATING_4_STARS: + case RATING_5_STARS: + case RATING_PERCENTAGE: + return new Rating(ratingStyle, RATING_NOT_RATED); + default: + return null; + } + } + + /** + * Return a Rating instance with a heart-based rating. + * Create and return a new Rating instance with a rating style of {@link #RATING_HEART}, + * and a heart-based rating. + * @param hasHeart true for a "heart selected" rating, false for "heart unselected". + * @return a new Rating instance. + */ + public static Rating newHeartRating(boolean hasHeart) { + return new Rating(RATING_HEART, hasHeart ? 1.0f : 0.0f); + } + + /** + * Return a Rating instance with a thumb-based rating. + * Create and return a new Rating instance with a {@link #RATING_THUMB_UP_DOWN} + * rating style, and a "thumb up" or "thumb down" rating. + * @param thumbIsUp true for a "thumb up" rating, false for "thumb down". + * @return a new Rating instance. + */ + public static Rating newThumbRating(boolean thumbIsUp) { + return new Rating(RATING_THUMB_UP_DOWN, thumbIsUp ? 1.0f : 0.0f); + } + + /** + * Return a Rating instance with a star-based rating. + * Create and return a new Rating instance with one of the star-base rating styles + * and the given integer or fractional number of stars. Non integer values can for instance + * be used to represent an average rating value, which might not be an integer number of stars. + * @param starRatingStyle one of {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, + * {@link #RATING_5_STARS}. + * @param starRating a number ranging from 0.0f to 3.0f, 4.0f or 5.0f according to + * the rating style. + * @return null if the rating style is invalid, or the rating is out of range, + * a new Rating instance otherwise. + */ + public static Rating newStarRating(int starRatingStyle, float starRating) { + float maxRating = -1.0f; + switch(starRatingStyle) { + case RATING_3_STARS: + maxRating = 3.0f; + break; + case RATING_4_STARS: + maxRating = 4.0f; + break; + case RATING_5_STARS: + maxRating = 5.0f; + break; + default: + Log.e(TAG, "Invalid rating style (" + starRatingStyle + ") for a star rating"); + return null; + } + if ((starRating < 0.0f) || (starRating > maxRating)) { + Log.e(TAG, "Trying to set out of range star-based rating"); + return null; + } + return new Rating(starRatingStyle, starRating); + } + + /** + * Return a Rating instance with a percentage-based rating. + * Create and return a new Rating instance with a {@link #RATING_PERCENTAGE} + * rating style, and a rating of the given percentage. + * @param percent the value of the rating + * @return null if the rating is out of range, a new Rating instance otherwise. + */ + public static Rating newPercentageRating(float percent) { + if ((percent < 0.0f) || (percent > 100.0f)) { + Log.e(TAG, "Invalid percentage-based rating value"); + return null; + } else { + return new Rating(RATING_PERCENTAGE, percent); + } + } + + /** + * Return whether there is a rating value available. + * @return true if the instance was not created with {@link #newUnratedRating(int)}. + */ + public boolean isRated() { + return mRatingValue >= 0.0f; + } + + /** + * Return the rating style. + * @return one of {@link #RATING_HEART}, {@link #RATING_THUMB_UP_DOWN}, + * {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS}, + * or {@link #RATING_PERCENTAGE}. + */ + public int getRatingStyle() { + return mRatingStyle; + } + + /** + * Return whether the rating is "heart selected". + * @return true if the rating is "heart selected", false if the rating is "heart unselected", + * if the rating style is not {@link #RATING_HEART} or if it is unrated. + */ + public boolean hasHeart() { + if (mRatingStyle != RATING_HEART) { + return false; + } else { + return (mRatingValue == 1.0f); + } + } + + /** + * Return whether the rating is "thumb up". + * @return true if the rating is "thumb up", false if the rating is "thumb down", + * if the rating style is not {@link #RATING_THUMB_UP_DOWN} or if it is unrated. + */ + public boolean isThumbUp() { + if (mRatingStyle != RATING_THUMB_UP_DOWN) { + return false; + } else { + return (mRatingValue == 1.0f); + } + } + + /** + * Return the star-based rating value. + * @return a rating value greater or equal to 0.0f, or a negative value if the rating style is + * not star-based, or if it is unrated. + */ + public float getStarRating() { + switch (mRatingStyle) { + case RATING_3_STARS: + case RATING_4_STARS: + case RATING_5_STARS: + if (isRated()) { + return mRatingValue; + } + default: + return -1.0f; + } + } + + /** + * Return the percentage-based rating value. + * @return a rating value greater or equal to 0.0f, or a negative value if the rating style is + * not percentage-based, or if it is unrated. + */ + public float getPercentRating() { + if ((mRatingStyle != RATING_PERCENTAGE) || !isRated()) { + return -1.0f; + } else { + return mRatingValue; + } + } +}
\ No newline at end of file diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java index 58f5d55369d0..f8faf3a962d0 100644 --- a/media/java/android/media/RemoteControlClient.java +++ b/media/java/android/media/RemoteControlClient.java @@ -30,6 +30,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -385,27 +386,6 @@ public class RemoteControlClient mEventHandler = new EventHandler(this, looper); } - private static final int[] METADATA_KEYS_TYPE_STRING = { - MediaMetadataRetriever.METADATA_KEY_ALBUM, - MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, - MediaMetadataRetriever.METADATA_KEY_TITLE, - MediaMetadataRetriever.METADATA_KEY_ARTIST, - MediaMetadataRetriever.METADATA_KEY_AUTHOR, - MediaMetadataRetriever.METADATA_KEY_COMPILATION, - MediaMetadataRetriever.METADATA_KEY_COMPOSER, - MediaMetadataRetriever.METADATA_KEY_DATE, - MediaMetadataRetriever.METADATA_KEY_GENRE, - MediaMetadataRetriever.METADATA_KEY_TITLE, - MediaMetadataRetriever.METADATA_KEY_WRITER }; - private static final int[] METADATA_KEYS_TYPE_LONG = { - MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, - MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER, - MediaMetadataRetriever.METADATA_KEY_DURATION, - MediaMetadataRetriever.METADATA_KEY_YEAR, - MetadataEditor.LONG_KEY_RATING_TYPE, - MetadataEditor.LONG_KEY_RATING_BY_OTHERS, - MetadataEditor.LONG_KEY_RATING_BY_USER}; - /** * Class used to modify metadata in a {@link RemoteControlClient} object. * Use {@link RemoteControlClient#editMetadata(boolean)} to create an instance of an editor, @@ -414,28 +394,7 @@ public class RemoteControlClient * for the associated client. Once the metadata has been "applied", you cannot reuse this * instance of the MetadataEditor. */ - public class MetadataEditor { - /** - * Mask of editable keys. - */ - private long mEditableKeys; - /** - * @hide - */ - protected boolean mMetadataChanged; - /** - * @hide - */ - protected boolean mArtworkChanged; - /** - * @hide - */ - protected Bitmap mEditorArtwork; - /** - * @hide - */ - protected Bundle mEditorMetadata; - private boolean mApplied = false; + public class MetadataEditor extends MediaMetadataEditor { // only use RemoteControlClient.editMetadata() to get a MetadataEditor instance private MetadataEditor() { } @@ -450,73 +409,10 @@ public class RemoteControlClient * The metadata key for the content artwork / album art. */ public final static int BITMAP_KEY_ARTWORK = 100; - /** - * The metadata key qualifying the content rating. - * The value associated with this key may be: {@link #RATING_HEART}, - * {@link #RATING_THUMB_UP_DOWN}, or a non-null positive integer expressing a maximum - * number of "stars" for the rating, for which a typical value is 3 or 5. - */ - public final static int LONG_KEY_RATING_TYPE = 101; - /** - * The metadata key for the content's average rating, not the user's rating. - * The value associated with this key may be: an integer value between 0 and 100, - * or {@link #RATING_NOT_RATED} to express that no average rating is available. - * <p></p> - * Note that a rating value up to 100 is not incompatible with a rating type using up - * to 5 stars for instance, as the average may be an non-integer number of stars. - * <p></p> - * When the rating type is: - * <ul> - * <li>{@link #RATING_HEART}, a rating of 51 to 100 means "heart selected",</li> - * <li>{@link #RATING_THUMB_UP_DOWN}, a rating of 0 to 50 means "thumb down", - * 51 to 100 means "thumb up"</li> - * <li>a non-null positive integer, the rating value is mapped to the number of stars, e.g. - * with a maximum of 5 stars, a rating of 0 maps to 0 stars, 1 to 20 maps to 1 star, - * 21 to 40 maps to 2 stars, etc.</li> - * </ul> - * @see #LONG_KEY_RATING_BY_USER - */ - public final static int LONG_KEY_RATING_BY_OTHERS = 102; - // editable keys /** * @hide - * Editable key mask - */ - public final static int KEY_EDITABLE_MASK = 0x1FFFFFFF; - /** - * The metadata key for the content's user rating. - * The value associated with this key may be: an integer value between 0 and 100, - * or {@link #RATING_NOT_RATED} to express that the user hasn't rated this content. - * Rules for the interpretation of the rating value according to the rating style are - * the same as for {@link #LONG_KEY_RATING_BY_OTHERS}. - * This key can be flagged as "editable" (with {@link #addEditableKey(int)}) to enable - * receiving user rating values through the - * {@link android.media.RemoteControlClient.OnMetadataUpdateListener} interface. - */ - public final static int LONG_KEY_RATING_BY_USER = 0x10000001; - - /** - * A rating style with a single degree of rating, "heart" vs "no heart". Can be used to - * indicate the content referred to is a favorite (or not). - * @see #LONG_KEY_RATING_TYPE - */ - public final static long RATING_HEART = -1; - /** - * A rating style for "thumb up" vs "thumb down". - * @see #LONG_KEY_RATING_TYPE - */ - public final static long RATING_THUMB_UP_DOWN = -2; - /** - * A rating value indicating no rating is available. - * @see #LONG_KEY_RATING_BY_OTHERS - * @see #LONG_KEY_RATING_BY_USER - */ - public final static long RATING_NOT_RATED = -101; - - /** - * @hide - * TODO(jmtrivi) have lockscreen and music move to the new key name + * TODO(jmtrivi) have lockscreen move to the new key name and remove */ public final static int METADATA_KEY_ARTWORK = BITMAP_KEY_ARTWORK; @@ -543,15 +439,7 @@ public class RemoteControlClient */ public synchronized MetadataEditor putString(int key, String value) throws IllegalArgumentException { - if (mApplied) { - Log.e(TAG, "Can't edit a previously applied MetadataEditor"); - return this; - } - if (!validTypeForKey(key, METADATA_KEYS_TYPE_STRING)) { - throw(new IllegalArgumentException("Invalid type 'String' for key "+ key)); - } - mEditorMetadata.putString(String.valueOf(key), value); - mMetadataChanged = true; + super.putString(key, value); return this; } @@ -564,9 +452,7 @@ public class RemoteControlClient * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}, * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} (with a value * expressed in milliseconds), - * {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}, - * {@link #LONG_KEY_RATING_BY_OTHERS}, {@link #LONG_KEY_RATING_BY_USER}, - * {@link #LONG_KEY_RATING_TYPE}. + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}. * @param value The long value for the given key * @return Returns a reference to the same MetadataEditor object, so you can chain put * calls together. @@ -574,15 +460,7 @@ public class RemoteControlClient */ public synchronized MetadataEditor putLong(int key, long value) throws IllegalArgumentException { - if (mApplied) { - Log.e(TAG, "Can't edit a previously applied MetadataEditor"); - return this; - } - if (!validTypeForKey(key, METADATA_KEYS_TYPE_LONG)) { - throw(new IllegalArgumentException("Invalid type 'long' for key "+ key)); - } - mEditorMetadata.putLong(String.valueOf(key), value); - mMetadataChanged = true; + super.putLong(key, value); return this; } @@ -596,69 +474,22 @@ public class RemoteControlClient * @throws IllegalArgumentException * @see android.graphics.Bitmap */ + @Override public synchronized MetadataEditor putBitmap(int key, Bitmap bitmap) throws IllegalArgumentException { - if (mApplied) { - Log.e(TAG, "Can't edit a previously applied MetadataEditor"); - return this; - } - if (key != BITMAP_KEY_ARTWORK) { - throw(new IllegalArgumentException("Invalid type 'Bitmap' for key "+ key)); - } - mEditorArtwork = bitmap; - mArtworkChanged = true; + super.putBitmap(key, bitmap); return this; } /** - * Clears all the metadata that has been set since the MetadataEditor instance was - * created with {@link RemoteControlClient#editMetadata(boolean)}. + * Clears all the metadata that has been set since the MetadataEditor instance was created + * (with {@link RemoteControlClient#editMetadata(boolean)}). * Note that clearing the metadata doesn't reset the editable keys - * (use {@link #clearEditableKeys()} instead). + * (use {@link MediaMetadataEditor#removeEditableKeys()} instead). */ + @Override public synchronized void clear() { - if (mApplied) { - Log.e(TAG, "Can't clear a previously applied MetadataEditor"); - return; - } - mEditorMetadata.clear(); - mEditorArtwork = null; - } - - /** - * Flag the given key as being editable. - * This will declare the metadata field as eligible to be updated, with new values - * received through the {@link RemoteControlClient.OnMetadataUpdateListener} interface. - * @param key the type of metadata that can be edited. The supported key is - * {@link #LONG_KEY_RATING_BY_USER}. - */ - public synchronized void addEditableKey(int key) { - if (mApplied) { - Log.e(TAG, "Can't change editable keys of a previously applied MetadataEditor"); - return; - } - // only one editable key at the moment, so we're not wasting memory on an array - // of editable keys to check the validity of the key, just hardcode the supported key. - if (key == MetadataEditor.LONG_KEY_RATING_BY_USER) { - mEditableKeys |= (MetadataEditor.KEY_EDITABLE_MASK & key); - mMetadataChanged = true; - } else { - Log.e(TAG, "Metadata key " + key + " cannot be edited"); - } - } - - /** - * Causes all metadata fields to be read-only. - */ - public synchronized void clearEditableKeys() { - if (mApplied) { - Log.e(TAG, "Can't clear editable keys of a previously applied MetadataEditor"); - return; - } - if (mEditableKeys != 0) { - mEditableKeys = 0; - mMetadataChanged = true; - } + super.clear(); } /** @@ -881,30 +712,17 @@ public class RemoteControlClient /** * Interface definition for a callback to be invoked when one of the metadata values has * been updated. + * Implement this interface to receive metadata updates after registering your listener + * through {@link RemoteControlClient#setMetadataUpdateListener(OnMetadataUpdateListener)}. */ public interface OnMetadataUpdateListener { /** * Called on the implementer to notify that the metadata field for the given key has - * been updated to the new value of type <code>long</long>. - * @param key the identifier of the updated metadata field of type <code>long</long>. - * @param newValue the new <code>long</long> value for the key + * been updated to the new value. + * @param key the identifier of the updated metadata field. + * @param newValue the Object storing the new value for the key. */ - void onMetadataUpdateLong(int key, long newValue); - /** - * Called on the implementer to notify that the metadata field for the given key has - * been updated to the new <code>String</long>. - * @param key the identifier of the updated metadata field of type <code>String</long>. - * @param newValue the new <code>String</long> value for the key - */ - void onMetadataUpdateString(int key, String newValue); - /** - * Called on the implementer to notify that the metadata field for the given key has - * been updated to the new {@link android.graphics.Bitmap}. - * @param key the identifier of the updated metadata field of type - * {@link android.graphics.Bitmap}. - * @param newValue the new {@link android.graphics.Bitmap} for the key - */ - void onMetadataUpdateBitmap(int key, Bitmap newValue); + public abstract void onMetadataUpdate(int key, Object newValue); } /** @@ -1338,12 +1156,11 @@ public class RemoteControlClient } } - public void updateMetadata(int generationId, int key, long value) { + public void updateMetadata(int generationId, int key, Rating value) { // only post messages, we can't block here if (mEventHandler != null) { mEventHandler.sendMessage(mEventHandler.obtainMessage( - MSG_UPDATE_METADATA_LONG, generationId /* arg1 */, key /* arg2*/, - new Long(value))); + MSG_UPDATE_METADATA, generationId /* arg1 */, key /* arg2*/, value)); } } }; @@ -1389,7 +1206,7 @@ public class RemoteControlClient private final static int MSG_SEEK_TO = 10; private final static int MSG_POSITION_DRIFT_CHECK = 11; private final static int MSG_DISPLAY_WANTS_POS_SYNC = 12; - private final static int MSG_UPDATE_METADATA_LONG = 13; + private final static int MSG_UPDATE_METADATA = 13; private class EventHandler extends Handler { public EventHandler(RemoteControlClient rcc, Looper looper) { @@ -1443,8 +1260,8 @@ public class RemoteControlClient case MSG_DISPLAY_WANTS_POS_SYNC: onDisplayWantsSync((IRemoteControlDisplay)msg.obj, msg.arg1 == 1); break; - case MSG_UPDATE_METADATA_LONG: - onUpdateMetadata(msg.arg1, msg.arg2, ((Long)msg.obj).longValue()); + case MSG_UPDATE_METADATA: + onUpdateMetadata(msg.arg1, msg.arg2, msg.obj); break; default: Log.e(TAG, "Unknown event " + msg.what + " in RemoteControlClient handler"); @@ -1725,10 +1542,10 @@ public class RemoteControlClient } } - private void onUpdateMetadata(int generationId, int key, long value) { + private void onUpdateMetadata(int generationId, int key, Object value) { synchronized (mCacheLock) { if ((mCurrentClientGenId == generationId) && (mMetadataUpdateListener != null)) { - mMetadataUpdateListener.onMetadataUpdateLong(key, value); + mMetadataUpdateListener.onMetadataUpdate(key, value); } } } @@ -1771,24 +1588,6 @@ public class RemoteControlClient return bitmap; } - /** - * Fast routine to go through an array of allowed keys and return whether the key is part - * of that array - * @param key the key value - * @param validKeys the array of valid keys for a given type - * @return true if the key is part of the array, false otherwise - */ - private static boolean validTypeForKey(int key, int[] validKeys) { - try { - for (int i = 0 ; ; i++) { - if (key == validKeys[i]) { - return true; - } - } - } catch (ArrayIndexOutOfBoundsException e) { - return false; - } - } /** * Returns whether, for the given playback state, the playback position is expected to diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java index 6badaaf542d1..8cdcb7a36b37 100644 --- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java +++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java @@ -102,6 +102,8 @@ public class EmergencyButton extends Button { == TelephonyManager.CALL_STATE_OFFHOOK) { mLockPatternUtils.resumeCall(); } else { + final boolean bypassHandler = true; + KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction(bypassHandler); Intent intent = new Intent(ACTION_EMERGENCY_DIAL); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java index 3e499b2b0be7..c2cd32f79298 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java @@ -295,6 +295,13 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu } } } + + @Override + public void onEmergencyCallAction() { + if (mBiometricUnlock != null) { + mBiometricUnlock.stop(); + } + } }; @Override diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index dcec6541ce5d..f4bbf9adda38 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -91,6 +91,7 @@ public class KeyguardUpdateMonitor { private static final int MSG_SET_CURRENT_CLIENT_ID = 315; protected static final int MSG_SET_PLAYBACK_STATE = 316; protected static final int MSG_USER_INFO_CHANGED = 317; + protected static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318; private static KeyguardUpdateMonitor sInstance; @@ -181,6 +182,9 @@ public class KeyguardUpdateMonitor { case MSG_USER_INFO_CHANGED: handleUserInfoChanged(msg.arg1); break; + case MSG_REPORT_EMERGENCY_CALL_ACTION: + handleReportEmergencyCallAction(); + break; } } }; @@ -758,6 +762,18 @@ public class KeyguardUpdateMonitor { } } + /** + * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION} + */ + private void handleReportEmergencyCallAction() { + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onEmergencyCallAction(); + } + } + } + public boolean isKeyguardVisible() { return mKeyguardIsVisible; } @@ -902,6 +918,22 @@ public class KeyguardUpdateMonitor { handleSimStateChange(new SimArgs(IccCardConstants.State.READY)); } + /** + * Report that the emergency call button has been pressed and the emergency dialer is + * about to be displayed. + * + * @param bypassHandler runs immediately. + * + * NOTE: Must be called from UI thread if bypassHandler == true. + */ + public void reportEmergencyCallAction(boolean bypassHandler) { + if (!bypassHandler) { + mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget(); + } else { + handleReportEmergencyCallAction(); + } + } + public CharSequence getTelephonyPlmn() { return mTelephonyPlmn; } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index 30b43f5e87e7..b0511e56a6b1 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -131,4 +131,8 @@ class KeyguardUpdateMonitorCallback { */ public void onMusicPlaybackStateChanged(int playbackState, long eventTime) { } + /** + * Called when the emergency call button is pressed. + */ + void onEmergencyCallAction() { } } diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java index 4333aea9491f..8ab46453e372 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java @@ -414,12 +414,25 @@ public class PrintJobConfigActivity extends Activity { // write anything and wait for the user to fix the range which will // trigger an update. mRequestedPages = mEditor.getRequestedPages(); - if (mRequestedPages == null) { + if (mRequestedPages == null || mRequestedPages.length == 0) { mEditor.updateUi(); if (mEditor.isDone()) { PrintJobConfigActivity.this.finish(); } return; + } else { + // If print is not confirmed we just ask for the first of the + // selected pages to emulate a behavior that shows preview + // increasing the chances that apps will implement the APIs + // correctly. + if (!mEditor.isPrintConfirmed()) { + if (ALL_PAGES_ARRAY.equals(mRequestedPages)) { + mRequestedPages = new PageRange[] {new PageRange(0, 0)}; + } else { + final int firstPage = mRequestedPages[0].getStart(); + mRequestedPages = new PageRange[] {new PageRange(firstPage, firstPage)}; + } + } } // If the info and the layout did not change and we already have @@ -1461,8 +1474,12 @@ public class PrintJobConfigActivity extends Activity { if (dashIndex > 0) { fromIndex = Integer.parseInt(range.substring(0, dashIndex)) - 1; - toIndex = Integer.parseInt(range.substring( - dashIndex + 1, range.length())) - 1; + // It is possible that the dash is at the end since the input + // verification can has to allow the user to keep entering if + // this would lead to a valid input. So we handle this. + toIndex = (dashIndex < range.length() - 1) + ? Integer.parseInt(range.substring(dashIndex + 1, + range.length())) - 1 : fromIndex; } else { fromIndex = toIndex = Integer.parseInt(range) - 1; } diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index 2257617b5429..2be8ee59e16d 100755 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -292,11 +292,7 @@ public class BatteryMeterView extends View implements DemoMode { c.drawRect(mFrame, mBatteryPaint); c.restore(); - if (level <= EMPTY) { - final float x = mWidth * 0.5f; - final float y = (mHeight + mWarningTextHeight) * 0.48f; - c.drawText(mWarningString, x, y, mWarningTextPaint); - } else if (tracker.plugged) { + if (tracker.plugged) { // draw the bolt final int bl = (int)(mFrame.left + width / 4f); final int bt = (int)(mFrame.top + height / 6f); @@ -319,6 +315,10 @@ public class BatteryMeterView extends View implements DemoMode { mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); } c.drawPath(mBoltPath, mBoltPaint); + } else if (level <= EMPTY) { + final float x = mWidth * 0.5f; + final float y = (mHeight + mWarningTextHeight) * 0.48f; + c.drawText(mWarningString, x, y, mWarningTextPaint); } else if (mShowPercent && !(tracker.level == 100 && !SHOW_100_PERCENT)) { mTextPaint.setTextSize(height * (SINGLE_DIGIT_PERCENT ? 0.75f diff --git a/packages/SystemUI/src/com/android/systemui/recent/ColorDrawableWithDimensions.java b/packages/SystemUI/src/com/android/systemui/recent/ColorDrawableWithDimensions.java new file mode 100644 index 000000000000..b4d3edda6c68 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recent/ColorDrawableWithDimensions.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013 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 com.android.systemui.recent; + +import android.graphics.drawable.ColorDrawable; + +public class ColorDrawableWithDimensions extends ColorDrawable { + private int mWidth; + private int mHeight; + + public ColorDrawableWithDimensions(int color, int width, int height) { + super(color); + mWidth = width; + mHeight = height; + } + + @Override + public int getIntrinsicWidth() { + return mWidth; + } + + @Override + public int getIntrinsicHeight() { + return mHeight; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java b/packages/SystemUI/src/com/android/systemui/recent/FadedEdgeDrawHelper.java index f17766b5bc9f..1cfc892b3824 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recent/FadedEdgeDrawHelper.java @@ -30,7 +30,7 @@ import android.widget.LinearLayout; import com.android.systemui.R; -public class RecentsScrollViewPerformanceHelper { +public class FadedEdgeDrawHelper { public static final boolean OPTIMIZE_SW_RENDERED_RECENTS = true; public static final boolean USE_DARK_FADE_IN_HW_ACCELERATED_MODE = true; private View mScrollView; @@ -43,18 +43,18 @@ public class RecentsScrollViewPerformanceHelper { private Matrix mFadeMatrix; private LinearGradient mFade; - public static RecentsScrollViewPerformanceHelper create(Context context, + public static FadedEdgeDrawHelper create(Context context, AttributeSet attrs, View scrollView, boolean isVertical) { boolean isTablet = context.getResources(). getBoolean(R.bool.config_recents_interface_for_tablets); if (!isTablet && (OPTIMIZE_SW_RENDERED_RECENTS || USE_DARK_FADE_IN_HW_ACCELERATED_MODE)) { - return new RecentsScrollViewPerformanceHelper(context, attrs, scrollView, isVertical); + return new FadedEdgeDrawHelper(context, attrs, scrollView, isVertical); } else { return null; } } - public RecentsScrollViewPerformanceHelper(Context context, + public FadedEdgeDrawHelper(Context context, AttributeSet attrs, View scrollView, boolean isVertical) { mScrollView = scrollView; TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View); @@ -64,7 +64,7 @@ public class RecentsScrollViewPerformanceHelper { } public void onAttachedToWindowCallback( - RecentsCallback callback, LinearLayout layout, boolean hardwareAccelerated) { + LinearLayout layout, boolean hardwareAccelerated) { mSoftwareRendered = !hardwareAccelerated; if ((mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) || USE_DARK_FADE_IN_HW_ACCELERATED_MODE) { @@ -178,11 +178,11 @@ public class RecentsScrollViewPerformanceHelper { } } - public int getVerticalFadingEdgeLengthCallback() { + public int getVerticalFadingEdgeLength() { return mFadingEdgeLength; } - public int getHorizontalFadingEdgeLengthCallback() { + public int getHorizontalFadingEdgeLength() { return mFadingEdgeLength; } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java index 8b2cd3f25171..c714d8b61f32 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java @@ -25,7 +25,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Handler; @@ -62,8 +62,8 @@ public class RecentTasksLoader implements View.OnTouchListener { private Handler mHandler; private int mIconDpi; - private Bitmap mDefaultThumbnailBackground; - private Bitmap mDefaultIconBackground; + private ColorDrawableWithDimensions mDefaultThumbnailBackground; + private ColorDrawableWithDimensions mDefaultIconBackground; private int mNumTasksInFirstScreenful = Integer.MAX_VALUE; private boolean mFirstScreenful; @@ -100,7 +100,7 @@ public class RecentTasksLoader implements View.OnTouchListener { // Render default icon (just a blank image) int defaultIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.app_icon_size); int iconSize = (int) (defaultIconSize * mIconDpi / res.getDisplayMetrics().densityDpi); - mDefaultIconBackground = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); + mDefaultIconBackground = new ColorDrawableWithDimensions(0x00000000, iconSize, iconSize); // Render the default thumbnail background int thumbnailWidth = @@ -110,9 +110,7 @@ public class RecentTasksLoader implements View.OnTouchListener { int color = res.getColor(R.drawable.status_bar_recents_app_thumbnail_background); mDefaultThumbnailBackground = - Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888); - Canvas c = new Canvas(mDefaultThumbnailBackground); - c.drawColor(color); + new ColorDrawableWithDimensions(color, thumbnailWidth, thumbnailHeight); } public void setRecentsPanel(RecentsPanelView newRecentsPanel, RecentsPanelView caller) { @@ -125,11 +123,11 @@ public class RecentTasksLoader implements View.OnTouchListener { } } - public Bitmap getDefaultThumbnail() { + public Drawable getDefaultThumbnail() { return mDefaultThumbnailBackground; } - public Bitmap getDefaultIcon() { + public Drawable getDefaultIcon() { return mDefaultIconBackground; } @@ -199,7 +197,7 @@ public class RecentTasksLoader implements View.OnTouchListener { + td + ": " + thumbnail); synchronized (td) { if (thumbnail != null) { - td.setThumbnail(thumbnail); + td.setThumbnail(new BitmapDrawable(mContext.getResources(), thumbnail)); } else { td.setThumbnail(mDefaultThumbnailBackground); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java index f51e34b57688..f5670e11ab06 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java @@ -22,7 +22,10 @@ import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.util.DisplayMetrics; import android.util.Log; @@ -68,7 +71,14 @@ public class Recents extends SystemUI implements RecentsComponent { } } else { - Bitmap first = firstTask.getThumbnail(); + Bitmap first = null; + if (firstTask.getThumbnail() instanceof BitmapDrawable) { + first = ((BitmapDrawable) firstTask.getThumbnail()).getBitmap(); + } else { + first = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + Drawable d = RecentTasksLoader.getInstance(mContext).getDefaultThumbnail(); + d.draw(new Canvas(first)); + } final Resources res = mContext.getResources(); float thumbWidth = res diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java index 217b7fd54621..be42bc0c9b32 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java @@ -49,16 +49,17 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView private RecentsCallback mCallback; protected int mLastScrollPosition; private SwipeHelper mSwipeHelper; - private RecentsScrollViewPerformanceHelper mPerformanceHelper; + private FadedEdgeDrawHelper mFadedEdgeDrawHelper; private HashSet<View> mRecycledViews; private int mNumItemsInOneScreenful; + private Runnable mOnScrollListener; public RecentsHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs, 0); float densityScale = getResources().getDisplayMetrics().density; float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); mSwipeHelper = new SwipeHelper(SwipeHelper.Y, this, densityScale, pagingTouchSlop); - mPerformanceHelper = RecentsScrollViewPerformanceHelper.create(context, attrs, this, false); + mFadedEdgeDrawHelper = FadedEdgeDrawHelper.create(context, attrs, this, false); mRecycledViews = new HashSet<View>(); } @@ -108,8 +109,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView final View view = mAdapter.getView(i, old, mLinearLayout); - if (mPerformanceHelper != null) { - mPerformanceHelper.addViewCallback(view); + if (mFadedEdgeDrawHelper != null) { + mFadedEdgeDrawHelper.addViewCallback(view); } OnTouchListener noOpListener = new OnTouchListener() { @@ -234,26 +235,10 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } @Override - public void draw(Canvas canvas) { - super.draw(canvas); - - if (mPerformanceHelper != null) { - int paddingLeft = mPaddingLeft; - final boolean offsetRequired = isPaddingOffsetRequired(); - if (offsetRequired) { - paddingLeft += getLeftPaddingOffset(); - } - - int left = mScrollX + paddingLeft; - int right = left + mRight - mLeft - mPaddingRight - paddingLeft; - int top = mScrollY + getFadeTop(offsetRequired); - int bottom = top + getFadeHeight(offsetRequired); + public void drawFadedEdges(Canvas canvas, int left, int right, int top, int bottom) { + if (mFadedEdgeDrawHelper != null) { - if (offsetRequired) { - right += getRightPaddingOffset(); - bottom += getBottomPaddingOffset(); - } - mPerformanceHelper.drawCallback(canvas, + mFadedEdgeDrawHelper.drawCallback(canvas, left, right, top, bottom, mScrollX, mScrollY, 0, 0, getLeftFadingEdgeStrength(), getRightFadingEdgeStrength(), mPaddingTop); @@ -261,9 +246,21 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + if (mOnScrollListener != null) { + mOnScrollListener.run(); + } + } + + public void setOnScrollListener(Runnable listener) { + mOnScrollListener = listener; + } + + @Override public int getVerticalFadingEdgeLength() { - if (mPerformanceHelper != null) { - return mPerformanceHelper.getVerticalFadingEdgeLengthCallback(); + if (mFadedEdgeDrawHelper != null) { + return mFadedEdgeDrawHelper.getVerticalFadingEdgeLength(); } else { return super.getVerticalFadingEdgeLength(); } @@ -271,8 +268,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView @Override public int getHorizontalFadingEdgeLength() { - if (mPerformanceHelper != null) { - return mPerformanceHelper.getHorizontalFadingEdgeLengthCallback(); + if (mFadedEdgeDrawHelper != null) { + return mFadedEdgeDrawHelper.getHorizontalFadingEdgeLength(); } else { return super.getHorizontalFadingEdgeLength(); } @@ -290,9 +287,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView @Override public void onAttachedToWindow() { - if (mPerformanceHelper != null) { - mPerformanceHelper.onAttachedToWindowCallback( - mCallback, mLinearLayout, isHardwareAccelerated()); + if (mFadedEdgeDrawHelper != null) { + mFadedEdgeDrawHelper.onAttachedToWindowCallback(mLinearLayout, isHardwareAccelerated()); } } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 5ebd11e03160..788e84390929 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -30,6 +30,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Shader.TileMode; import android.graphics.drawable.BitmapDrawable; @@ -74,7 +75,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener private PopupMenu mPopup; private View mRecentsScrim; private View mRecentsNoApps; - private ViewGroup mRecentsContainer; + private RecentsScrollView mRecentsContainer; private boolean mShowing; private boolean mWaitingToShow; @@ -98,6 +99,8 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener public void setCallback(RecentsCallback callback); public void setMinSwipeAlpha(float minAlpha); public View findViewForTask(int persistentTaskId); + public void drawFadedEdges(Canvas c, int left, int right, int top, int bottom); + public void setOnScrollListener(Runnable listener); } private final class OnLongClickDelegate implements View.OnLongClickListener { @@ -113,7 +116,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener /* package */ final static class ViewHolder { View thumbnailView; ImageView thumbnailViewImage; - Bitmap thumbnailViewImageBitmap; + Drawable thumbnailViewDrawable; ImageView iconView; TextView labelView; TextView descriptionView; @@ -151,7 +154,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener // the thumbnail later (if they both have the same dimensions) updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false); holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon); - holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon()); + holder.iconView.setImageDrawable(mRecentTasksLoader.getDefaultIcon()); holder.labelView = (TextView) convertView.findViewById(R.id.app_label); holder.calloutLine = convertView.findViewById(R.id.recents_callout_line); holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description); @@ -227,7 +230,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener public void recycleView(View v) { ViewHolder holder = (ViewHolder) v.getTag(); updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false); - holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon()); + holder.iconView.setImageDrawable(mRecentTasksLoader.getDefaultIcon()); holder.iconView.setVisibility(INVISIBLE); holder.iconView.animate().cancel(); holder.labelView.setText(null); @@ -270,13 +273,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener } public int numItemsInOneScreenful() { - if (mRecentsContainer instanceof RecentsScrollView){ - RecentsScrollView scrollView - = (RecentsScrollView) mRecentsContainer; - return scrollView.numItemsInOneScreenful(); - } else { - throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView"); - } + return mRecentsContainer.numItemsInOneScreenful(); } private boolean pointInside(int x, int y, View v) { @@ -288,7 +285,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener } public boolean isInContentArea(int x, int y) { - return pointInside(x, y, mRecentsContainer); + return pointInside(x, y, (View) mRecentsContainer); } public void show(boolean show) { @@ -436,16 +433,16 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener protected void onFinishInflate() { super.onFinishInflate(); - mRecentsContainer = (ViewGroup) findViewById(R.id.recents_container); + mRecentsContainer = (RecentsScrollView) findViewById(R.id.recents_container); + mRecentsContainer.setOnScrollListener(new Runnable() { + public void run() { + // need to redraw the faded edges + invalidate(); + } + }); mListAdapter = new TaskDescriptionAdapter(mContext); - if (mRecentsContainer instanceof RecentsScrollView){ - RecentsScrollView scrollView - = (RecentsScrollView) mRecentsContainer; - scrollView.setAdapter(mListAdapter); - scrollView.setCallback(this); - } else { - throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView"); - } + mRecentsContainer.setAdapter(mListAdapter); + mRecentsContainer.setCallback(this); mRecentsScrim = findViewById(R.id.recents_bg_protect); mRecentsNoApps = findViewById(R.id.recents_no_apps); @@ -462,11 +459,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener } public void setMinSwipeAlpha(float minAlpha) { - if (mRecentsContainer instanceof RecentsScrollView){ - RecentsScrollView scrollView - = (RecentsScrollView) mRecentsContainer; - scrollView.setMinSwipeAlpha(minAlpha); - } + mRecentsContainer.setMinSwipeAlpha(minAlpha); } private void createCustomAnimations(LayoutTransition transitioner) { @@ -488,23 +481,23 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener } } - private void updateThumbnail(ViewHolder h, Bitmap thumbnail, boolean show, boolean anim) { + private void updateThumbnail(ViewHolder h, Drawable thumbnail, boolean show, boolean anim) { if (thumbnail != null) { // Should remove the default image in the frame // that this now covers, to improve scrolling speed. // That can't be done until the anim is complete though. - h.thumbnailViewImage.setImageBitmap(thumbnail); + h.thumbnailViewImage.setImageDrawable(thumbnail); // scale the image to fill the full width of the ImageView. do this only if // we haven't set a bitmap before, or if the bitmap size has changed - if (h.thumbnailViewImageBitmap == null || - h.thumbnailViewImageBitmap.getWidth() != thumbnail.getWidth() || - h.thumbnailViewImageBitmap.getHeight() != thumbnail.getHeight()) { + if (h.thumbnailViewDrawable == null || + h.thumbnailViewDrawable.getIntrinsicWidth() != thumbnail.getIntrinsicWidth() || + h.thumbnailViewDrawable.getIntrinsicHeight() != thumbnail.getIntrinsicHeight()) { if (mFitThumbnailToXY) { h.thumbnailViewImage.setScaleType(ScaleType.FIT_XY); } else { Matrix scaleMatrix = new Matrix(); - float scale = mThumbnailWidth / (float) thumbnail.getWidth(); + float scale = mThumbnailWidth / (float) thumbnail.getIntrinsicWidth(); scaleMatrix.setScale(scale, scale); h.thumbnailViewImage.setScaleType(ScaleType.MATRIX); h.thumbnailViewImage.setImageMatrix(scaleMatrix); @@ -517,14 +510,14 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener } h.thumbnailView.setVisibility(View.VISIBLE); } - h.thumbnailViewImageBitmap = thumbnail; + h.thumbnailViewDrawable = thumbnail; } } void onTaskThumbnailLoaded(TaskDescription td) { synchronized (td) { if (mRecentsContainer != null) { - ViewGroup container = mRecentsContainer; + ViewGroup container = (ViewGroup) mRecentsContainer; if (container instanceof RecentsScrollView) { container = (ViewGroup) container.findViewById( R.id.recents_linear_layout); @@ -633,7 +626,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener final int items = mRecentTaskDescriptions != null ? mRecentTaskDescriptions.size() : 0; - mRecentsContainer.setVisibility(items > 0 ? View.VISIBLE : View.GONE); + ((View) mRecentsContainer).setVisibility(items > 0 ? View.VISIBLE : View.GONE); // Set description for accessibility int numRecentApps = mRecentTaskDescriptions != null @@ -650,33 +643,33 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener } public boolean simulateClick(int persistentTaskId) { - if (mRecentsContainer instanceof RecentsScrollView){ - RecentsScrollView scrollView - = (RecentsScrollView) mRecentsContainer; - View v = scrollView.findViewForTask(persistentTaskId); - if (v != null) { - handleOnClick(v); - return true; - } + View v = mRecentsContainer.findViewForTask(persistentTaskId); + if (v != null) { + handleOnClick(v); + return true; } return false; } public void handleOnClick(View view) { - ViewHolder holder = (ViewHolder)view.getTag(); + ViewHolder holder = (ViewHolder) view.getTag(); TaskDescription ad = holder.taskDescription; final Context context = view.getContext(); final ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - Bitmap bm = holder.thumbnailViewImageBitmap; - boolean usingDrawingCache; - if (bm.getWidth() == holder.thumbnailViewImage.getWidth() && - bm.getHeight() == holder.thumbnailViewImage.getHeight()) { - usingDrawingCache = false; - } else { + + Bitmap bm = null; + boolean usingDrawingCache = true; + if (holder.thumbnailViewDrawable instanceof BitmapDrawable) { + bm = ((BitmapDrawable) holder.thumbnailViewDrawable).getBitmap(); + if (bm.getWidth() == holder.thumbnailViewImage.getWidth() && + bm.getHeight() == holder.thumbnailViewImage.getHeight()) { + usingDrawingCache = false; + } + } + if (usingDrawingCache) { holder.thumbnailViewImage.setDrawingCacheEnabled(true); bm = holder.thumbnailViewImage.getDrawingCache(); - usingDrawingCache = true; } Bundle opts = (bm == null) ? null : @@ -771,7 +764,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { if (item.getItemId() == R.id.recent_remove_item) { - mRecentsContainer.removeViewInLayout(selectedView); + ((ViewGroup) mRecentsContainer).removeViewInLayout(selectedView); } else if (item.getItemId() == R.id.recent_inspect_item) { ViewHolder viewHolder = (ViewHolder) selectedView.getTag(); if (viewHolder != null) { @@ -795,4 +788,26 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener }); popup.show(); } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + + int paddingLeft = mPaddingLeft; + final boolean offsetRequired = isPaddingOffsetRequired(); + if (offsetRequired) { + paddingLeft += getLeftPaddingOffset(); + } + + int left = mScrollX + paddingLeft; + int right = left + mRight - mLeft - mPaddingRight - paddingLeft; + int top = mScrollY + getFadeTop(offsetRequired); + int bottom = top + getFadeHeight(offsetRequired); + + if (offsetRequired) { + right += getRightPaddingOffset(); + bottom += getBottomPaddingOffset(); + } + mRecentsContainer.drawFadedEdges(canvas, left, right, top, bottom); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java index ee076d95255d..6dddc392be8b 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java @@ -49,9 +49,10 @@ public class RecentsVerticalScrollView extends ScrollView private RecentsCallback mCallback; protected int mLastScrollPosition; private SwipeHelper mSwipeHelper; - private RecentsScrollViewPerformanceHelper mPerformanceHelper; + private FadedEdgeDrawHelper mFadedEdgeDrawHelper; private HashSet<View> mRecycledViews; private int mNumItemsInOneScreenful; + private Runnable mOnScrollListener; public RecentsVerticalScrollView(Context context, AttributeSet attrs) { super(context, attrs, 0); @@ -59,7 +60,7 @@ public class RecentsVerticalScrollView extends ScrollView float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop); - mPerformanceHelper = RecentsScrollViewPerformanceHelper.create(context, attrs, this, true); + mFadedEdgeDrawHelper = FadedEdgeDrawHelper.create(context, attrs, this, true); mRecycledViews = new HashSet<View>(); } @@ -112,8 +113,8 @@ public class RecentsVerticalScrollView extends ScrollView } final View view = mAdapter.getView(i, old, mLinearLayout); - if (mPerformanceHelper != null) { - mPerformanceHelper.addViewCallback(view); + if (mFadedEdgeDrawHelper != null) { + mFadedEdgeDrawHelper.addViewCallback(view); } OnTouchListener noOpListener = new OnTouchListener() { @@ -243,36 +244,32 @@ public class RecentsVerticalScrollView extends ScrollView } @Override - public void draw(Canvas canvas) { - super.draw(canvas); - - if (mPerformanceHelper != null) { - int paddingLeft = mPaddingLeft; + public void drawFadedEdges(Canvas canvas, int left, int right, int top, int bottom) { + if (mFadedEdgeDrawHelper != null) { final boolean offsetRequired = isPaddingOffsetRequired(); - if (offsetRequired) { - paddingLeft += getLeftPaddingOffset(); - } - - int left = mScrollX + paddingLeft; - int right = left + mRight - mLeft - mPaddingRight - paddingLeft; - int top = mScrollY + getFadeTop(offsetRequired); - int bottom = top + getFadeHeight(offsetRequired); - - if (offsetRequired) { - right += getRightPaddingOffset(); - bottom += getBottomPaddingOffset(); - } - mPerformanceHelper.drawCallback(canvas, - left, right, top, bottom, mScrollX, mScrollY, + mFadedEdgeDrawHelper.drawCallback(canvas, + left, right, top + getFadeTop(offsetRequired), bottom, mScrollX, mScrollY, getTopFadingEdgeStrength(), getBottomFadingEdgeStrength(), 0, 0, mPaddingTop); } } @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + if (mOnScrollListener != null) { + mOnScrollListener.run(); + } + } + + public void setOnScrollListener(Runnable listener) { + mOnScrollListener = listener; + } + + @Override public int getVerticalFadingEdgeLength() { - if (mPerformanceHelper != null) { - return mPerformanceHelper.getVerticalFadingEdgeLengthCallback(); + if (mFadedEdgeDrawHelper != null) { + return mFadedEdgeDrawHelper.getVerticalFadingEdgeLength(); } else { return super.getVerticalFadingEdgeLength(); } @@ -280,8 +277,8 @@ public class RecentsVerticalScrollView extends ScrollView @Override public int getHorizontalFadingEdgeLength() { - if (mPerformanceHelper != null) { - return mPerformanceHelper.getHorizontalFadingEdgeLengthCallback(); + if (mFadedEdgeDrawHelper != null) { + return mFadedEdgeDrawHelper.getHorizontalFadingEdgeLength(); } else { return super.getHorizontalFadingEdgeLength(); } @@ -299,9 +296,8 @@ public class RecentsVerticalScrollView extends ScrollView @Override public void onAttachedToWindow() { - if (mPerformanceHelper != null) { - mPerformanceHelper.onAttachedToWindowCallback( - mCallback, mLinearLayout, isHardwareAccelerated()); + if (mFadedEdgeDrawHelper != null) { + mFadedEdgeDrawHelper.onAttachedToWindowCallback(mLinearLayout, isHardwareAccelerated()); } } diff --git a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java index 7e979b723bda..2bc28210c57a 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java +++ b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java @@ -29,7 +29,7 @@ public final class TaskDescription { final String packageName; // used to override animations (see onClick()) final CharSequence description; - private Bitmap mThumbnail; // generated by Activity.onCreateThumbnail() + private Drawable mThumbnail; // generated by Activity.onCreateThumbnail() private Drawable mIcon; // application package icon private CharSequence mLabel; // application package label private boolean mLoaded; @@ -85,11 +85,11 @@ public final class TaskDescription { mIcon = icon; } - public void setThumbnail(Bitmap thumbnail) { + public void setThumbnail(Drawable thumbnail) { mThumbnail = thumbnail; } - public Bitmap getThumbnail() { + public Drawable getThumbnail() { return mThumbnail; } } diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java index c6c4a94177b4..67b2307c128c 100644 --- a/services/java/com/android/server/AppOpsService.java +++ b/services/java/com/android/server/AppOpsService.java @@ -113,7 +113,7 @@ public class AppOpsService extends IAppOpsService.Stub { uid = _uid; packageName = _packageName; op = _op; - mode = AppOpsManager.MODE_ALLOWED; + mode = AppOpsManager.opToDefaultMode(op); } } @@ -191,7 +191,7 @@ public class AppOpsService extends IAppOpsService.Stub { mHandler = new Handler(); readState(); } - + public void publish(Context context) { mContext = context; ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder()); @@ -379,7 +379,7 @@ public class AppOpsService extends IAppOpsService.Stub { } repCbs.addAll(cbs); } - if (mode == AppOpsManager.MODE_ALLOWED) { + if (mode == AppOpsManager.opToDefaultMode(op.op)) { // If going into the default mode, prune this op // if there is nothing else interesting in it. pruneOp(op, uid, packageName); @@ -435,8 +435,8 @@ public class AppOpsService extends IAppOpsService.Stub { Ops pkgOps = ent.getValue(); for (int j=pkgOps.size()-1; j>=0; j--) { Op curOp = pkgOps.valueAt(j); - if (curOp.mode != AppOpsManager.MODE_ALLOWED) { - curOp.mode = AppOpsManager.MODE_ALLOWED; + if (curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { + curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); changed = true; callbacks = addCallbacks(callbacks, packageName, curOp.op, mOpModeWatchers.get(curOp.op)); @@ -545,7 +545,7 @@ public class AppOpsService extends IAppOpsService.Stub { synchronized (this) { Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false); if (op == null) { - return AppOpsManager.MODE_ALLOWED; + return AppOpsManager.opToDefaultMode(code); } return op.mode; } @@ -947,7 +947,7 @@ public class AppOpsService extends IAppOpsService.Stub { AppOpsManager.OpEntry op = ops.get(j); out.startTag(null, "op"); out.attribute(null, "n", Integer.toString(op.getOp())); - if (op.getMode() != AppOpsManager.MODE_ALLOWED) { + if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) { out.attribute(null, "m", Integer.toString(op.getMode())); } long time = op.getTime(); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 2bac96ede974..80f4b0011272 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -14749,7 +14749,7 @@ public final class ActivityManagerService extends ActivityManagerNative } private final void setProcessTrackerState(ProcessRecord proc, int memFactor, long now) { - if (proc.thread != null) { + if (proc.thread != null && proc.baseProcessTracker != null) { proc.baseProcessTracker.setState(proc.repProcState, memFactor, now, proc.pkgList); } } diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index f5d45b343b3f..7756ff9ad685 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -1417,8 +1417,8 @@ public final class ActivityStackSupervisor { final ActivityStack lastStack = getLastStack(); ActivityRecord curTop = lastStack == null? null : lastStack.topRunningNonDelayedActivityLocked(notTop); - if (curTop != null && (curTop.task != intentActivity.task) || - curTop.task != lastStack.topTask()) { + if (curTop != null && (curTop.task != intentActivity.task || + curTop.task != lastStack.topTask())) { r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); if (sourceRecord == null || (sourceStack.topActivity() != null && sourceStack.topActivity().task == sourceRecord.task)) { diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index 4fdacb3733ce..d230779d8492 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -567,7 +567,8 @@ final class ProcessRecord { */ public boolean addPackage(String pkg, ProcessStatsService tracker) { if (!pkgList.containsKey(pkg)) { - pkgList.put(pkg, tracker.getProcessStateLocked(pkg, info.uid, processName)); + pkgList.put(pkg, baseProcessTracker != null + ? tracker.getProcessStateLocked(pkg, info.uid, processName) : null); return true; } return false; @@ -592,25 +593,30 @@ final class ProcessRecord { * Delete all packages from list except the package indicated in info */ public void resetPackageList(ProcessStatsService tracker) { - long now = SystemClock.uptimeMillis(); - baseProcessTracker.setState(ProcessStats.STATE_NOTHING, - tracker.getMemFactorLocked(), now, pkgList); final int N = pkgList.size(); - if (N != 1) { - for (int i=0; i<N; i++) { - ProcessStats.ProcessState ps = pkgList.valueAt(i); - if (ps != null && ps != baseProcessTracker) { - ps.makeInactive(); - } + if (baseProcessTracker != null) { + long now = SystemClock.uptimeMillis(); + baseProcessTracker.setState(ProcessStats.STATE_NOTHING, + tracker.getMemFactorLocked(), now, pkgList); + if (N != 1) { + for (int i=0; i<N; i++) { + ProcessStats.ProcessState ps = pkgList.valueAt(i); + if (ps != null && ps != baseProcessTracker) { + ps.makeInactive(); + } + } + pkgList.clear(); + ProcessStats.ProcessState ps = tracker.getProcessStateLocked( + info.packageName, info.uid, processName); + pkgList.put(info.packageName, ps); + if (thread != null && ps != baseProcessTracker) { + ps.makeActive(); + } } + } else if (N != 1) { pkgList.clear(); - ProcessStats.ProcessState ps = tracker.getProcessStateLocked( - info.packageName, info.uid, processName); - pkgList.put(info.packageName, ps); - if (thread != null && ps != baseProcessTracker) { - ps.makeActive(); - } + pkgList.put(info.packageName, null); } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index dbd42afd5ec1..69ff449b2c95 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -923,7 +923,8 @@ public class WindowManagerService extends IWindowManager.Stub //that was created later or a window at the top of the list of //windows associated with this token. if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, - "Adding window " + win + " at " + (newIdx + 1) + " of " + N); + "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + + N); windows.add(newIdx + 1, win); if (newIdx < 0) { // No window from token found on win's display. @@ -1044,7 +1045,7 @@ public class WindowManagerService extends IWindowManager.Stub } } if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, - "Adding window " + win + " at " + i + " of " + N); + "Based on layer: Adding window " + win + " at " + i + " of " + N); windows.add(i, win); mWindowsChanged = true; return tokenWindowsPos; @@ -1063,7 +1064,7 @@ public class WindowManagerService extends IWindowManager.Stub } i++; if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, - "Adding window " + win + " at " + i + " of " + windows.size()); + "Free window: Adding window " + win + " at " + i + " of " + windows.size()); windows.add(i, win); mWindowsChanged = true; } @@ -1130,6 +1131,8 @@ public class WindowManagerService extends IWindowManager.Stub } private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { + if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win + + " Callers=" + Debug.getCallers(4)); if (win.mAttachedWindow == null) { final WindowToken token = win.mToken; int tokenWindowsPos = 0; @@ -1185,16 +1188,15 @@ public class WindowManagerService extends IWindowManager.Stub // same display. Or even when the current IME/target are not on the same screen as the next // IME/target. For now only look for input windows on the main screen. WindowList windows = getDefaultWindowListLocked(); - final int N = windows.size(); WindowState w = null; - int i = N; - while (i > 0) { - i--; - w = windows.get(i); + int i; + for (i = windows.size() - 1; i >= 0; --i) { + WindowState win = windows.get(i); if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i - + " " + w + " fl=0x" + Integer.toHexString(w.mAttrs.flags)); - if (canBeImeTarget(w)) { + + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); + if (canBeImeTarget(win)) { + w = win; //Slog.i(TAG, "Putting input method here!"); // Yet more tricksyness! If this window is a "starting" @@ -7081,19 +7083,17 @@ public class WindowManagerService extends IWindowManager.Stub } } - if (lastFocus != newFocus) { - //System.out.println("Changing focus from " + lastFocus - // + " to " + newFocus); - if (newFocus != null) { - if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); - newFocus.reportFocusChangedSerialized(true, mInTouchMode); - notifyFocusChanged(); - } + //System.out.println("Changing focus from " + lastFocus + // + " to " + newFocus); + if (newFocus != null) { + if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); + newFocus.reportFocusChangedSerialized(true, mInTouchMode); + notifyFocusChanged(); + } - if (lastFocus != null) { - if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); - lastFocus.reportFocusChangedSerialized(false, mInTouchMode); - } + if (lastFocus != null) { + if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); + lastFocus.reportFocusChangedSerialized(false, mInTouchMode); } } break; @@ -10277,14 +10277,13 @@ public class WindowManagerService extends IWindowManager.Stub void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) { - int j = 0; final int numDisplays = mDisplayContents.size(); for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { final WindowState w = windowList.get(winNdx); if (windows == null || windows.contains(w)) { - pw.print(" Window #"); pw.print(j++); pw.print(' '); + pw.print(" Window #"); pw.print(winNdx); pw.print(' '); pw.print(w); pw.println(":"); w.dump(pw, " ", dumpAll || windows != null); } |