Merge "Guard against null Context in attachInfo()." into klp-dev
diff --git a/api/current.txt b/api/current.txt
index e96eec2..e50e57f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20,6 +20,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 3e4795c..bf2a1e4 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -65,7 +65,7 @@
// 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 @@
};
/**
+ * 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 @@
}
/**
+ * 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 d889353..efe6b15 100644
--- a/core/java/android/print/PrintAttributes.java
+++ b/core/java/android/print/PrintAttributes.java
@@ -373,27 +373,208 @@
// 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 c8312e3..6c6635d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4355,6 +4355,12 @@
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 969c94ba..7efcb6e 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -1639,6 +1639,8 @@
@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 @@
@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 499a930..c2a830d 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 98368a1..99b703b 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 9cb0a37..e82c0e1 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 dd729b4..48079f2 100644
--- a/media/java/android/media/IRemoteControlClient.aidl
+++ b/media/java/android/media/IRemoteControlClient.aidl
@@ -17,6 +17,7 @@
import android.graphics.Bitmap;
import android.media.IRemoteControlDisplay;
+import android.media.Rating;
/**
* @hide
@@ -49,5 +50,5 @@
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 ab686e6..34dc580 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -2093,8 +2093,11 @@
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 0000000..b601016
--- /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 0000000..1dc336a
--- /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 0000000..48443ff
--- /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 58f5d55..f8faf3a 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -30,6 +30,7 @@
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 @@
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 @@
* 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 @@
* 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 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 @@
* {@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 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 @@
* @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 @@
/**
* 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 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 @@
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 @@
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 @@
}
}
- 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 @@
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 6badaaf..8cdcb7a 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -102,6 +102,8 @@
== 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 3e499b2..c2cd32f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
@@ -295,6 +295,13 @@
}
}
}
+
+ @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 dcec654..f4bbf9a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -91,6 +91,7 @@
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 @@
case MSG_USER_INFO_CHANGED:
handleUserInfoChanged(msg.arg1);
break;
+ case MSG_REPORT_EMERGENCY_CALL_ACTION:
+ handleReportEmergencyCallAction();
+ break;
}
}
};
@@ -758,6 +762,18 @@
}
}
+ /**
+ * 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 @@
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 30b43f5..b0511e5 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -131,4 +131,8 @@
*/
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 4333aea..8ab4645 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -414,12 +414,25 @@
// 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 @@
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 2257617..2be8ee5 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -292,11 +292,7 @@
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 @@
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 0000000..b4d3edd
--- /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
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
rename to packages/SystemUI/src/com/android/systemui/recent/FadedEdgeDrawHelper.java
index f17766b..1cfc892 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 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 @@
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 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 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 8b2cd3f..c714d8b 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.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 @@
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 @@
// 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 @@
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 Bitmap getDefaultThumbnail() {
+ public Drawable getDefaultThumbnail() {
return mDefaultThumbnailBackground;
}
- public Bitmap getDefaultIcon() {
+ public Drawable getDefaultIcon() {
return mDefaultIconBackground;
}
@@ -199,7 +197,7 @@
+ 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 f51e34b..f5670e1 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.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 @@
}
} 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 217b7fd..be42bc0 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 @@
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 @@
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 @@
}
@Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
+ public void drawFadedEdges(Canvas canvas, int left, int right, int top, int bottom) {
+ if (mFadedEdgeDrawHelper != null) {
- 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);
-
- 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 @@
}
@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 @@
@Override
public int getHorizontalFadingEdgeLength() {
- if (mPerformanceHelper != null) {
- return mPerformanceHelper.getHorizontalFadingEdgeLengthCallback();
+ if (mFadedEdgeDrawHelper != null) {
+ return mFadedEdgeDrawHelper.getHorizontalFadingEdgeLength();
} else {
return super.getHorizontalFadingEdgeLength();
}
@@ -290,9 +287,8 @@
@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 5ebd11e0..788e843 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.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 @@
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 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 @@
/* package */ final static class ViewHolder {
View thumbnailView;
ImageView thumbnailViewImage;
- Bitmap thumbnailViewImageBitmap;
+ Drawable thumbnailViewDrawable;
ImageView iconView;
TextView labelView;
TextView descriptionView;
@@ -151,7 +154,7 @@
// 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 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 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 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 @@
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 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 @@
}
}
- 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 @@
}
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 @@
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 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 @@
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 @@
});
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 ee076d9..6dddc39 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 @@
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 @@
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 @@
}
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 @@
}
@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 @@
@Override
public int getHorizontalFadingEdgeLength() {
- if (mPerformanceHelper != null) {
- return mPerformanceHelper.getHorizontalFadingEdgeLengthCallback();
+ if (mFadedEdgeDrawHelper != null) {
+ return mFadedEdgeDrawHelper.getHorizontalFadingEdgeLength();
} else {
return super.getHorizontalFadingEdgeLength();
}
@@ -299,9 +296,8 @@
@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 7e979b7..2bc2821 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 @@
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 @@
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 c6c4a94..67b2307 100644
--- a/services/java/com/android/server/AppOpsService.java
+++ b/services/java/com/android/server/AppOpsService.java
@@ -113,7 +113,7 @@
uid = _uid;
packageName = _packageName;
op = _op;
- mode = AppOpsManager.MODE_ALLOWED;
+ mode = AppOpsManager.opToDefaultMode(op);
}
}
@@ -191,7 +191,7 @@
mHandler = new Handler();
readState();
}
-
+
public void publish(Context context) {
mContext = context;
ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
@@ -379,7 +379,7 @@
}
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 @@
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 @@
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 @@
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 2bac96e..80f4b00 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -14749,7 +14749,7 @@
}
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 f5d45b3..7756ff9 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1417,8 +1417,8 @@
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 4fdacb3..d230779 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -567,7 +567,8 @@
*/
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 @@
* 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 dbd42af..69ff449 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -923,7 +923,8 @@
//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 @@
}
}
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 @@
}
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 @@
}
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 @@
// 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 @@
}
}
- 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 @@
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);
}