Merge "Check whether media recorder client exists before dumping." into ics-mr0
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 4225393..7d683a5 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -990,8 +990,8 @@
mBound = false;
mContext.unbindService(this);
}
- mSyncWakeLock.setWorkSource(null);
mSyncWakeLock.release();
+ mSyncWakeLock.setWorkSource(null);
}
@Override
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e344197..438c536 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1095,6 +1095,16 @@
}
}
+ private static long computeWakeLock(Timer timer, long batteryRealtime, int which) {
+ if (timer != null) {
+ // Convert from microseconds to milliseconds with rounding
+ long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
+ long totalTimeMillis = (totalTimeMicros + 500) / 1000;
+ return totalTimeMillis;
+ }
+ return 0;
+ }
+
/**
*
* @param sb a StringBuilder object.
@@ -1109,9 +1119,7 @@
long batteryRealtime, String name, int which, String linePrefix) {
if (timer != null) {
- // Convert from microseconds to milliseconds with rounding
- long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
- long totalTimeMillis = (totalTimeMicros + 500) / 1000;
+ long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
int count = timer.getCountLocked(which);
if (totalTimeMillis != 0) {
@@ -1735,6 +1743,8 @@
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
+ long totalFull = 0, totalPartial = 0, totalWindow = 0;
+ int count = 0;
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
: wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
@@ -1754,6 +1764,44 @@
// Only print out wake locks that were held
pw.println(sb.toString());
uidActivity = true;
+ count++;
+ }
+ totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
+ batteryRealtime, which);
+ totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
+ batteryRealtime, which);
+ totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
+ batteryRealtime, which);
+ }
+ if (count > 1) {
+ if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" TOTAL wake: ");
+ boolean needComma = false;
+ if (totalFull != 0) {
+ needComma = true;
+ formatTimeMs(sb, totalFull);
+ sb.append("full");
+ }
+ if (totalPartial != 0) {
+ if (needComma) {
+ sb.append(", ");
+ }
+ needComma = true;
+ formatTimeMs(sb, totalPartial);
+ sb.append("partial");
+ }
+ if (totalWindow != 0) {
+ if (needComma) {
+ sb.append(", ");
+ }
+ needComma = true;
+ formatTimeMs(sb, totalWindow);
+ sb.append("window");
+ }
+ sb.append(" realtime");
+ pw.println(sb.toString());
}
}
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 64d3d31..2b254af 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -194,6 +194,9 @@
*/
public static final int FX_SURFACE_DIM = 0x00020000;
+ /** @hide */
+ public static final int FX_SURFACE_SCREENSHOT = 0x00030000;
+
/** Mask used for FX values above @hide */
public static final int FX_SURFACE_MASK = 0x000F0000;
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index e16a8bd..5d01a0f 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -925,7 +925,7 @@
event.setCurrentItemIndex(getSelectedItemPosition());
event.setFromIndex(getFirstVisiblePosition());
event.setToIndex(getLastVisiblePosition());
- event.setItemCount(getAdapter().getCount());
+ event.setItemCount(getCount());
}
private boolean isScrollableForAccessibility() {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index e2a2566..3e96c81 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -98,6 +98,10 @@
// in to one common name.
private static final int MAX_WAKELOCKS_PER_UID = 30;
+ // The system process gets more. It is special. Oh so special.
+ // With, you know, special needs. Like this.
+ private static final int MAX_WAKELOCKS_PER_UID_IN_SYSTEM = 50;
+
private static final String BATCHED_WAKELOCK_NAME = "*overflow*";
private static int sNumSpeedSteps;
@@ -2895,12 +2899,10 @@
String wakelockName = in.readString();
Uid.Wakelock wakelock = new Wakelock();
wakelock.readFromParcelLocked(unpluggables, in);
- if (mWakelockStats.size() < MAX_WAKELOCKS_PER_UID) {
- // We will just drop some random set of wakelocks if
- // the previous run of the system was an older version
- // that didn't impose a limit.
- mWakelockStats.put(wakelockName, wakelock);
- }
+ // We will just drop some random set of wakelocks if
+ // the previous run of the system was an older version
+ // that didn't impose a limit.
+ mWakelockStats.put(wakelockName, wakelock);
}
int numSensors = in.readInt();
@@ -3904,7 +3906,9 @@
public StopwatchTimer getWakeTimerLocked(String name, int type) {
Wakelock wl = mWakelockStats.get(name);
if (wl == null) {
- if (mWakelockStats.size() > MAX_WAKELOCKS_PER_UID) {
+ final int N = mWakelockStats.size();
+ if (N > MAX_WAKELOCKS_PER_UID && (mUid != Process.SYSTEM_UID
+ || N > MAX_WAKELOCKS_PER_UID_IN_SYSTEM)) {
name = BATCHED_WAKELOCK_NAME;
wl = mWakelockStats.get(name);
}
diff --git a/docs/html/resources/dashboard/opengl.jd b/docs/html/resources/dashboard/opengl.jd
index 2b94b28..9089937 100644
--- a/docs/html/resources/dashboard/opengl.jd
+++ b/docs/html/resources/dashboard/opengl.jd
@@ -57,7 +57,7 @@
<div class="dashboard-panel">
<img alt="" width="400" height="250"
-src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1|GL%202.0%20%26%201.1&chd=t%3A9.4,90.6" />
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1|GL%202.0%20%26%201.1&chd=t%3A9.2,90.8" />
<table>
<tr>
@@ -66,14 +66,14 @@
</tr>
<tr>
<td>1.1</th>
-<td>9.4%</td>
+<td>9.2%</td>
</tr>
<tr>
<td>2.0</th>
-<td>90.6%</td>
+<td>90.8%</td>
</tr>
</table>
-<p><em>Data collected during a 7-day period ending on September 2, 2011</em></p>
+<p><em>Data collected during a 7-day period ending on October 3, 2011</em></p>
</div>
diff --git a/docs/html/resources/dashboard/platform-versions.jd b/docs/html/resources/dashboard/platform-versions.jd
index 51cbae3..135c6f2 100644
--- a/docs/html/resources/dashboard/platform-versions.jd
+++ b/docs/html/resources/dashboard/platform-versions.jd
@@ -52,7 +52,7 @@
<div class="dashboard-panel">
<img alt="" height="250" width="470"
-src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:1.0,1.8,13.3,51.2,0.6,30.7,0.2,0.7,0.5&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.0|Android%203.1|Android%203.2&chco=c4df9b,6fad0c" />
+src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:1.1,1.4,11.7,45.3,0.5,38.2,0.2,0.9,0.7&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.0|Android%203.1|Android%203.2&chco=c4df9b,6fad0c" />
<table>
<tr>
@@ -61,21 +61,21 @@
<th>API Level</th>
<th>Distribution</th>
</tr>
-<tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</a></td><td>Cupcake</td> <td>3</td><td>1.0%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-1.6.html">Android 1.6</a></td><td>Donut</td> <td>4</td><td>1.8%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1</a></td><td>Eclair</td> <td>7</td><td>13.3%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2</a></td><td>Froyo</td> <td>8</td><td>51.2%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</a></td><td>Cupcake</td> <td>3</td><td>1.1%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-1.6.html">Android 1.6</a></td><td>Donut</td> <td>4</td><td>1.4%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1</a></td><td>Eclair</td> <td>7</td><td>11.7%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2</a></td><td>Froyo</td> <td>8</td><td>45.3%</td></tr>
<tr><td><a href="{@docRoot}sdk/android-2.3.html">Android 2.3 -<br/>
- Android 2.3.2</a></td><td rowspan="2">Gingerbread</td> <td>9</td><td>0.6%</td></tr>
+ Android 2.3.2</a></td><td rowspan="2">Gingerbread</td> <td>9</td><td>0.5%</td></tr>
<tr><td><a href="{@docRoot}sdk/android-2.3.3.html">Android 2.3.3 -<br/>
- Android 2.3.4</a></td><!-- Gingerbread --> <td>10</td><td>30.7%</td></tr>
+ Android 2.3.7</a></td><!-- Gingerbread --> <td>10</td><td>38.2%</td></tr>
<tr><td><a href="{@docRoot}sdk/android-3.0.html">Android 3.0</a></td>
<td rowspan="3">Honeycomb</td> <td>11</td><td>0.2%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-3.1.html">Android 3.1</a></td><!-- Honeycomb --><td>12</td><td>0.7%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td><!-- Honeycomb --><td>13</td><td>0.5%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-3.1.html">Android 3.1</a></td><!-- Honeycomb --><td>12</td><td>0.9%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td><!-- Honeycomb --><td>13</td><td>0.7%</td></tr>
</table>
-<p><em>Data collected during a 14-day period ending on September 2, 2011</em></p>
+<p><em>Data collected during a 14-day period ending on October 3, 2011</em></p>
<!--
<p style="font-size:.9em">* <em>Other: 0.1% of devices running obsolete versions</em></p>
-->
@@ -104,9 +104,9 @@
<div class="dashboard-panel">
<img alt="" height="250" width="660" style="padding:5px;background:#fff"
-src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C03/01%7C03/15%7C04/01%7C04/15%7C05/01%7C05/15%7C06/01%7C06/15%7C07/01%7C07/15%7C08/01%7C08/15%7C09/01%7C1%3A%7C2011%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C2011%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:100.0,99.8,99.7,99.6,99.6,99.5,99.4,99.3,99.2,99.0,98.8,98.7,98.6|96.7,96.8,97.0,97.1,97.3,97.5,97.5,97.5,97.7,97.6,97.5,97.5,97.5|91.5,92.0,93.5,93.9,94.3,94.8,95.0,95.2,95.5,95.5,95.5,95.6,95.8|61.5,63.0,66.4,68.0,69.8,71.5,73.9,75.4,77.6,79.0,80.2,81.1,82.4|1.1,1.7,2.5,3.1,4.0,6.1,9.5,13.6,17.8,20.6,24.3,27.5,31.1|0.0,1.0,1.7,2.2,3.0,5.1,8.4,12.6,16.8,20.0,23.7,26.9,30.5&chm=b,c3df9b,0,1,0|b,b4db77,1,2,0|tAndroid 2.1,547a19,2,0,15,,t::-5|b,a5db51,2,3,0|tAndroid 2.2,3f5e0e,3,0,15,,t::-5|b,96dd28,3,4,0|b,83c916,4,5,0|tAndroid 2.3.3,131d02,5,7,15,,t::-5|B,6fad0c,5,6,0&chg=7,25&chdl=Android 1.5|Android 1.6|Android 2.1|Android 2.2|Android 2.3|Android 2.3.3&chco=add274,9dd14f,8ece2a,7ab61c,659b11,507d08" />
+src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C04/01%7C04/15%7C05/01%7C05/15%7C06/01%7C06/15%7C07/01%7C07/15%7C08/01%7C08/15%7C09/01%7C09/15%7C10/01%7C1%3A%7C2011%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C2011%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:99.7,99.6,99.6,99.5,99.4,99.3,99.2,99.0,98.8,98.7,98.5,98.5,98.2|97.0,97.1,97.3,97.5,97.5,97.5,97.7,97.6,97.5,97.5,97.5,97.5,97.1|93.5,93.9,94.3,94.8,95.0,95.2,95.5,95.5,95.5,95.6,95.7,95.8,95.6|66.4,68.0,69.8,71.5,73.9,75.4,77.6,79.0,80.2,81.1,82.4,83.3,83.8|2.5,3.1,4.0,6.1,9.5,13.6,17.8,20.6,24.3,27.5,31.2,34.7,38.3|1.7,2.2,3.0,5.1,8.4,12.6,16.8,20.0,23.7,26.9,30.6,34.1,37.8&chm=b,c3df9b,0,1,0|b,b4db77,1,2,0|tAndroid 2.1,547a19,2,0,15,,t::-5|b,a5db51,2,3,0|tAndroid 2.2,3f5e0e,3,0,15,,t::-5|b,96dd28,3,4,0|b,83c916,4,5,0|tAndroid 2.3.3,131d02,5,5,15,,t::-5|B,6fad0c,5,6,0&chg=7,25&chdl=Android 1.5|Android 1.6|Android 2.1|Android 2.2|Android 2.3|Android 2.3.3&chco=add274,9dd14f,8ece2a,7ab61c,659b11,507d08" />
-<p><em>Last historical dataset collected during a 14-day period ending on September 2, 2011</em></p>
+<p><em>Last historical dataset collected during a 14-day period ending on October 3, 2011</em></p>
</div><!-- end dashboard-panel -->
diff --git a/docs/html/resources/dashboard/screens.jd b/docs/html/resources/dashboard/screens.jd
index 77fd2d2..67b47d0 100644
--- a/docs/html/resources/dashboard/screens.jd
+++ b/docs/html/resources/dashboard/screens.jd
@@ -59,7 +59,8 @@
<div class="dashboard-panel">
-<img alt="" width="400" height="250" src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=Xlarge%20/%20mdpi| Large%20/%20mdpi|Normal%20/%20hdpi|Normal%20/%20ldpi|Normal%20/%20mdpi|Small%20/%20hdpi&chd=t%3A1.5, 3.2,74,0.9,16.9,3.5" />
+<img alt="" width="400" height="250"
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=Xlarge%20/%20mdpi|Large%20/%20ldpi|Large%20/%20mdpi|Normal%20/%20hdpi|Normal%20/%20ldpi|Normal%20/%20mdpi|Small%20/%20hdpi|Small%20/%20ldpi&chd=t%3A2.6,0.1,3.0,71.9,0.9,17.6,2.7,1.2" />
<table>
<tr>
@@ -70,31 +71,31 @@
<th scope="col">xhdpi</th>
</tr>
<tr><th scope="row">small</th>
-<td></td> <!-- small/ldpi -->
+<td>1.2%</td> <!-- small/ldpi -->
<td></td> <!-- small/mdpi -->
-<td>3.5%</td> <!-- small/hdpi -->
+<td>2.7%</td> <!-- small/hdpi -->
<td></td> <!-- small/xhdpi -->
</tr>
<tr><th scope="row">normal</th>
<td>0.9%</td> <!-- normal/ldpi -->
-<td>16.9%</td> <!-- normal/mdpi -->
-<td>74%</td> <!-- normal/hdpi -->
+<td>17.6%</td> <!-- normal/mdpi -->
+<td>71.9%</td> <!-- normal/hdpi -->
<td></td> <!-- normal/xhdpi -->
</tr>
<tr><th scope="row">large</th>
-<td></td> <!-- large/ldpi -->
-<td>3.2%</td> <!-- large/mdpi -->
+<td>0.1%</td> <!-- large/ldpi -->
+<td>3.0%</td> <!-- large/mdpi -->
<td></td> <!-- large/hdpi -->
<td></td> <!-- large/xhdpi -->
</tr>
<tr><th scope="row">xlarge</th>
<td></td> <!-- xlarge/ldpi -->
-<td>1.5%</td> <!-- xlarge/mdpi -->
+<td>2.6%</td> <!-- xlarge/mdpi -->
<td></td> <!-- xlarge/hdpi -->
<td></td> <!-- xlarge/xhdpi -->
</tr>
</table>
-<p><em>Data collected during a 7-day period ending on September 2, 2011</em></p>
+<p><em>Data collected during a 7-day period ending on October 3, 2011</em></p>
</div>
diff --git a/docs/html/sdk/android-4.0.jd b/docs/html/sdk/android-4.0.jd
index da40d52..90319878 100644
--- a/docs/html/sdk/android-4.0.jd
+++ b/docs/html/sdk/android-4.0.jd
@@ -158,7 +158,7 @@
<p>Adding a new raw contact for the profile requires the {@link
android.Manifest.permission#WRITE_PROFILE} permission. Likewise, in order to read from the profile
table, you must request the {@link android.Manifest.permission#READ_PROFILE} permission. However,
-most apps should need to read the user profile, even when contributing data to the
+most apps should not need to read the user profile, even when contributing data to the
profile. Reading the user profile is a sensitive permission and you should expect users to be
skeptical of apps that request it.</p>
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index ea022a6..e7a33f1 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -53,6 +53,7 @@
eFXSurfaceNormal = 0x00000000,
eFXSurfaceBlur = 0x00010000,
eFXSurfaceDim = 0x00020000,
+ eFXSurfaceScreenshot= 0x00030000,
eFXSurfaceMask = 0x000F0000,
};
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 0bee0f1..98fa171 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -409,9 +409,9 @@
int SurfaceTextureClient::disconnect(int api) {
LOGV("SurfaceTextureClient::disconnect");
Mutex::Autolock lock(mMutex);
+ freeAllBuffers();
int err = mSurfaceTexture->disconnect(api);
if (!err) {
- freeAllBuffers();
mReqFormat = 0;
mReqWidth = 0;
mReqHeight = 0;
diff --git a/packages/SystemUI/res/anim/recent_appear.xml b/packages/SystemUI/res/anim/recent_appear.xml
index 20fe052..4400d9d 100644
--- a/packages/SystemUI/res/anim/recent_appear.xml
+++ b/packages/SystemUI/res/anim/recent_appear.xml
@@ -16,5 +16,5 @@
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0" android:toAlpha="1.0"
- android:duration="@android:integer/config_mediumAnimTime"
+ android:duration="@android:integer/config_shortAnimTime"
/>
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
index 83c4faf..2d76455 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
@@ -39,11 +39,11 @@
android:layout_marginTop="@dimen/status_bar_recents_thumbnail_top_margin"
android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
android:background="@drawable/recents_thumbnail_bg"
- android:foreground="@drawable/recents_thumbnail_fg">
+ android:foreground="@drawable/recents_thumbnail_fg"
+ android:visibility="invisible">
<ImageView android:id="@+id/app_thumbnail_image"
android:layout_width="@dimen/status_bar_recents_thumbnail_width"
android:layout_height="@dimen/status_bar_recents_thumbnail_height"
- android:visibility="invisible"
/>
</FrameLayout>
@@ -58,7 +58,6 @@
android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
android:scaleType="centerInside"
android:adjustViewBounds="true"
- android:visibility="invisible"
/>
<TextView android:id="@+id/app_label"
@@ -74,7 +73,6 @@
android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
android:singleLine="true"
android:ellipsize="marquee"
- android:visibility="invisible"
android:textColor="@color/status_bar_recents_app_label_color"
/>
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
index 3d8b9d6..b653fcd 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
@@ -52,11 +52,11 @@
android:layout_toRightOf="@id/app_label"
android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
android:background="@drawable/recents_thumbnail_bg"
- android:foreground="@drawable/recents_thumbnail_fg">
+ android:foreground="@drawable/recents_thumbnail_fg"
+ android:visibility="invisible">
<ImageView android:id="@+id/app_thumbnail_image"
android:layout_width="@dimen/status_bar_recents_thumbnail_width"
android:layout_height="@dimen/status_bar_recents_thumbnail_height"
- android:visibility="invisible"
/>
</FrameLayout>
<View android:id="@+id/recents_callout_line"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
index e6336718..18a31f7 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
@@ -31,11 +31,11 @@
android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
android:scaleType="center"
android:background="@drawable/recents_thumbnail_bg"
- android:foreground="@drawable/recents_thumbnail_fg">
+ android:foreground="@drawable/recents_thumbnail_fg"
+ android:visibility="invisible">
<ImageView android:id="@+id/app_thumbnail_image"
android:layout_width="@dimen/status_bar_recents_thumbnail_width"
android:layout_height="@dimen/status_bar_recents_thumbnail_height"
- android:visibility="invisible"
/>
<ImageView android:id="@+id/app_icon"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 47aa849..dcda9c2 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -86,8 +86,8 @@
mIconDpi = isTablet ? DisplayMetrics.DENSITY_HIGH : res.getDisplayMetrics().densityDpi;
// Render the default thumbnail background
- int width = (int) res.getDimension(R.dimen.status_bar_recents_thumbnail_width);
- int height = (int) res.getDimension(R.dimen.status_bar_recents_thumbnail_height);
+ int width = (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
+ int height = (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
int color = res.getColor(R.drawable.status_bar_recents_app_thumbnail_background);
mDefaultThumbnailBackground = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
@@ -106,6 +106,10 @@
mRecentsPanel = recentsPanel;
}
+ public Bitmap getDefaultThumbnail() {
+ return mDefaultThumbnailBackground;
+ }
+
// Create an TaskDescription, returning null if the title or icon is null, or if it's the
// home activity
TaskDescription createTaskDescription(int taskId, int persistentTaskId, Intent baseIntent,
@@ -278,7 +282,7 @@
TaskDescription td = descriptions.get(i);
loadThumbnail(td);
long now = SystemClock.uptimeMillis();
- nextTime += 150;
+ nextTime += 0;
if (nextTime > now) {
try {
Thread.sleep(nextTime-now);
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index bd1fcfc..343b33514 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -37,6 +37,7 @@
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
@@ -57,8 +58,8 @@
import com.android.systemui.statusbar.tablet.StatusBarPanel;
import com.android.systemui.statusbar.tablet.TabletStatusBar;
-public class RecentsPanelView extends RelativeLayout
- implements OnItemClickListener, RecentsCallback, StatusBarPanel, Animator.AnimatorListener {
+public class RecentsPanelView extends RelativeLayout implements OnItemClickListener, RecentsCallback,
+ StatusBarPanel, Animator.AnimatorListener, View.OnTouchListener {
static final String TAG = "RecentsPanelView";
static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
private Context mContext;
@@ -74,6 +75,7 @@
private RecentTasksLoader mRecentTasksLoader;
private ArrayList<TaskDescription> mRecentTaskDescriptions;
+ private boolean mRecentTasksDirty = true;
private TaskDescriptionAdapter mListAdapter;
private int mThumbnailWidth;
@@ -94,6 +96,7 @@
/* package */ final static class ViewHolder {
View thumbnailView;
ImageView thumbnailViewImage;
+ Bitmap thumbnailViewImageBitmap;
ImageView iconView;
TextView labelView;
TextView descriptionView;
@@ -127,6 +130,10 @@
holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail);
holder.thumbnailViewImage = (ImageView) convertView.findViewById(
R.id.app_thumbnail_image);
+ // If we set the default thumbnail now, we avoid an onLayout when we update
+ // 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.labelView = (TextView) convertView.findViewById(R.id.app_label);
holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
@@ -139,12 +146,15 @@
// index is reverse since most recent appears at the bottom...
final int index = mRecentTaskDescriptions.size() - position - 1;
- final TaskDescription taskDescription = mRecentTaskDescriptions.get(index);
- applyTaskDescription(holder, taskDescription, false);
+ final TaskDescription td = mRecentTaskDescriptions.get(index);
+ holder.iconView.setImageDrawable(td.getIcon());
+ holder.labelView.setText(td.getLabel());
+ holder.thumbnailView.setContentDescription(td.getLabel());
+ updateThumbnail(holder, td.getThumbnail(), true, false);
- holder.thumbnailView.setTag(taskDescription);
+ holder.thumbnailView.setTag(td);
holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView));
- holder.taskDescription = taskDescription;
+ holder.taskDescription = td;
return convertView;
}
@@ -193,6 +203,7 @@
}
} else {
mRecentTasksLoader.cancelLoadingThumbnails();
+ mRecentTasksDirty = true;
}
if (animate) {
if (mShowing != show) {
@@ -250,9 +261,7 @@
createCustomAnimations(transitioner);
} else {
((ViewGroup)mRecentsContainer).setLayoutTransition(null);
- // Clear memory used by screenshots
- mRecentTaskDescriptions.clear();
- mListAdapter.notifyDataSetInvalidated();
+ clearRecentTasksList();
}
}
@@ -374,47 +383,33 @@
}
}
-
- void applyTaskDescription(ViewHolder h, TaskDescription td, boolean anim) {
- h.iconView.setImageDrawable(td.getIcon());
- if (h.iconView.getVisibility() != View.VISIBLE) {
- if (anim) {
- h.iconView.setAnimation(AnimationUtils.loadAnimation(
- mContext, R.anim.recent_appear));
- }
- h.iconView.setVisibility(View.VISIBLE);
- }
- h.labelView.setText(td.getLabel());
- h.thumbnailView.setContentDescription(td.getLabel());
- if (h.labelView.getVisibility() != View.VISIBLE) {
- if (anim) {
- h.labelView.setAnimation(AnimationUtils.loadAnimation(
- mContext, R.anim.recent_appear));
- }
- h.labelView.setVisibility(View.VISIBLE);
- }
- Bitmap thumbnail = td.getThumbnail();
+ private void updateThumbnail(ViewHolder h, Bitmap 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);
- // scale to fill up the full width
- Matrix scaleMatrix = new Matrix();
- float scale = mThumbnailWidth / (float) thumbnail.getWidth();
- scaleMatrix.setScale(scale, scale);
- h.thumbnailViewImage.setScaleType(ScaleType.MATRIX);
- h.thumbnailViewImage.setImageMatrix(scaleMatrix);
- if (h.thumbnailViewImage.getVisibility() != View.VISIBLE) {
- if (anim) {
- h.thumbnailViewImage.setAnimation(
- AnimationUtils.loadAnimation(
- mContext, R.anim.recent_appear));
- }
- h.thumbnailViewImage.setVisibility(View.VISIBLE);
+
+ // 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()) {
+ Matrix scaleMatrix = new Matrix();
+ float scale = mThumbnailWidth / (float) thumbnail.getWidth();
+ scaleMatrix.setScale(scale, scale);
+ h.thumbnailViewImage.setScaleType(ScaleType.MATRIX);
+ h.thumbnailViewImage.setImageMatrix(scaleMatrix);
}
+ if (show && h.thumbnailView.getVisibility() != View.VISIBLE) {
+ if (anim) {
+ h.thumbnailView.setAnimation(
+ AnimationUtils.loadAnimation(mContext, R.anim.recent_appear));
+ }
+ h.thumbnailView.setVisibility(View.VISIBLE);
+ }
+ h.thumbnailViewImageBitmap = thumbnail;
}
- //h.descriptionView.setText(ad.description);
}
void onTaskThumbnailLoaded(TaskDescription ad) {
@@ -432,7 +427,11 @@
if (v.getTag() instanceof ViewHolder) {
ViewHolder h = (ViewHolder)v.getTag();
if (h.taskDescription == ad) {
- applyTaskDescription(h, ad, true);
+ // only fade in the thumbnail if recents is already visible-- we
+ // show it immediately otherwise
+ boolean animateShow = mShowing &&
+ mRecentsGlowView.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD;
+ updateThumbnail(h, ad.getThumbnail(), true, animateShow);
}
}
}
@@ -440,14 +439,55 @@
}
}
- private void refreshRecentTasksList(ArrayList<TaskDescription> recentTasksList) {
- if (recentTasksList != null) {
- mRecentTaskDescriptions = recentTasksList;
- } else {
- mRecentTaskDescriptions = mRecentTasksLoader.getRecentTasks();
+ // additional optimization when we have sofware system buttons - start loading the recent
+ // tasks on touch down
+ @Override
+ public boolean onTouch(View v, MotionEvent ev) {
+ if (!mShowing) {
+ int action = ev.getAction() & MotionEvent.ACTION_MASK;
+ if (action == MotionEvent.ACTION_DOWN) {
+ // If we set our visibility to INVISIBLE here, we avoid an extra call to onLayout
+ // later when we become visible
+ setVisibility(INVISIBLE);
+ refreshRecentTasksList();
+ } else if (action == MotionEvent.ACTION_CANCEL) {
+ setVisibility(GONE);
+ clearRecentTasksList();
+ } else if (action == MotionEvent.ACTION_UP) {
+ if (!v.isPressed()) {
+ setVisibility(GONE);
+ clearRecentTasksList();
+ }
+ }
}
- mListAdapter.notifyDataSetInvalidated();
- updateUiElements(getResources().getConfiguration());
+ return false;
+ }
+
+ public void clearRecentTasksList() {
+ // Clear memory used by screenshots
+ if (mRecentTaskDescriptions != null) {
+ mRecentTasksLoader.cancelLoadingThumbnails();
+ mRecentTaskDescriptions.clear();
+ mListAdapter.notifyDataSetInvalidated();
+ mRecentTasksDirty = true;
+ }
+ }
+
+ public void refreshRecentTasksList() {
+ refreshRecentTasksList(null);
+ }
+
+ private void refreshRecentTasksList(ArrayList<TaskDescription> recentTasksList) {
+ if (mRecentTasksDirty) {
+ if (recentTasksList != null) {
+ mRecentTaskDescriptions = recentTasksList;
+ } else {
+ mRecentTaskDescriptions = mRecentTasksLoader.getRecentTasks();
+ }
+ mListAdapter.notifyDataSetInvalidated();
+ updateUiElements(getResources().getConfiguration());
+ mRecentTasksDirty = false;
+ }
}
public ArrayList<TaskDescription> getRecentTasksList() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index b724552..352d4a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -113,6 +113,8 @@
// will likely move to a resource or other tunable param at some point
private static final int INTRUDER_ALERT_DECAY_MS = 10000;
+ private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true;
+
// fling gesture tuning parameters, scaled to display density
private float mSelfExpandVelocityPx; // classic value: 2000px/s
private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
@@ -435,13 +437,18 @@
}
};
+ private void prepareNavigationBarView() {
+ mNavigationBarView.reorient();
+
+ mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
+ mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
+ }
+
// For small-screen devices (read: phones) that lack hardware navigation buttons
private void addNavigationBar() {
if (mNavigationBarView == null) return;
- mNavigationBarView.reorient();
-
- mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
+ prepareNavigationBarView();
WindowManagerImpl.getDefault().addView(
mNavigationBarView, getNavigationBarLayoutParams());
@@ -450,9 +457,7 @@
private void repositionNavigationBar() {
if (mNavigationBarView == null) return;
- mNavigationBarView.reorient();
-
- mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
+ prepareNavigationBarView();
WindowManagerImpl.getDefault().updateViewLayout(
mNavigationBarView, getNavigationBarLayoutParams());
@@ -695,6 +700,10 @@
// Recalculate the position of the sliding windows and the titles.
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
+
+ if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 && !mAnimating) {
+ animateCollapse();
+ }
}
setAreThereNotifications();
@@ -2007,8 +2016,8 @@
}
public void toggleRecentApps() {
- int msg = (mRecentsPanel.getVisibility() == View.GONE)
- ? MSG_OPEN_RECENTS_PANEL : MSG_CLOSE_RECENTS_PANEL;
+ int msg = (mRecentsPanel.getVisibility() == View.VISIBLE)
+ ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL;
mHandler.removeMessages(msg);
mHandler.sendEmptyMessage(msg);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index f0a10f3..de8226b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -587,6 +587,7 @@
// Add the windows
addPanelWindows();
+ mRecentButton.setOnTouchListener(mRecentsPanel);
mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
mPile.removeAllViews();
@@ -1805,8 +1806,8 @@
}
public void toggleRecentApps() {
- int msg = (mRecentsPanel.getVisibility() == View.GONE)
- ? MSG_OPEN_RECENTS_PANEL : MSG_CLOSE_RECENTS_PANEL;
+ int msg = (mRecentsPanel.getVisibility() == View.VISIBLE)
+ ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL;
mHandler.removeMessages(msg);
mHandler.sendEmptyMessage(msg);
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3e0304f..69560e5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1332,7 +1332,13 @@
int sessionId)
{
Mutex::Autolock _l(mLock);
+ checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
+}
+void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
+ bool enabled,
+ int sessionId)
+{
if (mType != RECORD) {
// suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
// another session. This gives the priority to well behaved effect control panels
@@ -5224,6 +5230,9 @@
sp<EffectHandle> handle = effect->mHandles[j].promote();
if (handle != 0) {
handle->mEffect.clear();
+ if (handle->mHasControl && handle->mEnabled) {
+ t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
+ }
}
}
AudioSystem::unregisterEffect(effect->id());
@@ -6844,7 +6853,7 @@
}
mEffect->disconnect(this, unpiniflast);
- if (mEnabled) {
+ if (mHasControl && mEnabled) {
sp<ThreadBase> thread = mEffect->thread().promote();
if (thread != 0) {
thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ed9d81e..4b794ef 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -492,10 +492,12 @@
int sessionId = AUDIO_SESSION_OUTPUT_MIX);
// check if some effects must be suspended/restored when an effect is enabled
// or disabled
- virtual void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+ void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
bool enabled,
int sessionId = AUDIO_SESSION_OUTPUT_MIX);
-
+ void checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
+ bool enabled,
+ int sessionId = AUDIO_SESSION_OUTPUT_MIX);
mutable Mutex mLock;
protected:
@@ -1299,7 +1301,7 @@
// suspend all eligible effects
void setEffectSuspendedAll_l(bool suspend);
// check if effects should be suspend or restored when a given effect is enable or disabled
- virtual void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+ void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
bool enabled);
status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index f1b8bae..47644de 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -44,6 +44,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.os.Binder;
+import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.IPowerManager;
@@ -1656,8 +1657,18 @@
}
}
+ private boolean isExtStorageEncrypted() {
+ String state = SystemProperties.get("vold.decrypt");
+ return !"".equals(state);
+ }
+
void wipeDataLocked(int flags) {
- if ((flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0) {
+ // If the SD card is encrypted and non-removable, we have to force a wipe.
+ boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
+ boolean wipeExtRequested = (flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0;
+
+ // Note: we can only do the wipe via ExternalStorageFormatter if the volume is not emulated.
+ if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) {
Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
mWakeLock.acquire(10000);
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index 788ecda..a653322 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -691,7 +691,7 @@
}
ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service);
final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId);
- if (this == group.mInternalConnection) {
+ if (group != null && this == group.mInternalConnection) {
group.onServiceConnected(spellChecker);
}
}
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 91576e7..131f11c 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -64,17 +64,16 @@
boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
mContext = context;
- Bitmap screenshot = Surface.screenshot(0, 0);
-
- if (screenshot == null) {
- // Device is not capable of screenshots... we can't do an animation.
- return;
- }
-
// Screenshot does NOT include rotation!
mSnapshotRotation = 0;
- mWidth = screenshot.getWidth();
- mHeight = screenshot.getHeight();
+ if (originalRotation == Surface.ROTATION_90
+ || originalRotation == Surface.ROTATION_270) {
+ mWidth = originalHeight;
+ mHeight = originalWidth;
+ } else {
+ mWidth = originalWidth;
+ mHeight = originalHeight;
+ }
mOriginalRotation = originalRotation;
mOriginalWidth = originalWidth;
@@ -89,7 +88,12 @@
try {
try {
mSurface = new Surface(session, 0, "FreezeSurface",
- -1, mWidth, mHeight, PixelFormat.OPAQUE, 0);
+ -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT);
+ if (mSurface == null || !mSurface.isValid()) {
+ // Screenshot failed, punt.
+ mSurface = null;
+ return;
+ }
mSurface.setLayer(FREEZE_LAYER + 1);
} catch (Surface.OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate freeze surface", e);
@@ -100,38 +104,12 @@
" FREEZE " + mSurface + ": CREATE");
setRotation(originalRotation);
-
- if (mSurface != null) {
- Rect dirty = new Rect(0, 0, mWidth, mHeight);
- Canvas c = null;
- try {
- c = mSurface.lockCanvas(dirty);
- } catch (IllegalArgumentException e) {
- Slog.w(TAG, "Unable to lock surface", e);
- } catch (Surface.OutOfResourcesException e) {
- Slog.w(TAG, "Unable to lock surface", e);
- }
- if (c == null) {
- Slog.w(TAG, "Null surface canvas");
- mSurface.destroy();
- mSurface = null;
- return;
- }
-
- Paint paint = new Paint(0);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
- c.drawBitmap(screenshot, 0, 0, paint);
-
- mSurface.unlockCanvasAndPost(c);
- }
} finally {
if (!inTransaction) {
Surface.closeTransaction();
if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
"<<< CLOSE TRANSACTION ScreenRotationAnimation");
}
-
- screenshot.recycle();
}
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index e921818..eeffb02 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -1120,7 +1120,11 @@
// window's center).
final float w = frame.width();
final float h = frame.height();
- tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
+ if (w>=1 && h>=1) {
+ tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
+ } else {
+ tmpMatrix.reset();
+ }
} else {
tmpMatrix.reset();
}
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index dab0705..61a8358 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -5,6 +5,7 @@
Layer.cpp \
LayerBase.cpp \
LayerDim.cpp \
+ LayerScreenshot.cpp \
DdmConnection.cpp \
DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 34a0d73..f885fc7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -88,16 +88,8 @@
Layer::~Layer()
{
- class MessageDestroyGLState : public MessageBase {
- GLuint texture;
- public:
- MessageDestroyGLState(GLuint texture) : texture(texture) { }
- virtual bool handler() {
- glDeleteTextures(1, &texture);
- return true;
- }
- };
- mFlinger->postMessageAsync( new MessageDestroyGLState(mTextureName) );
+ mFlinger->postMessageAsync(
+ new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) );
}
void Layer::onFrameQueued() {
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
new file mode 100644
index 0000000..e30ccbf
--- /dev/null
+++ b/services/surfaceflinger/LayerScreenshot.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include "LayerScreenshot.h"
+#include "SurfaceFlinger.h"
+#include "DisplayHardware/DisplayHardware.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger, DisplayID display,
+ const sp<Client>& client)
+ : LayerBaseClient(flinger, display, client),
+ mTextureName(0), mFlinger(flinger)
+{
+}
+
+LayerScreenshot::~LayerScreenshot()
+{
+ if (mTextureName) {
+ mFlinger->postMessageAsync(
+ new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) );
+ }
+}
+
+status_t LayerScreenshot::capture() {
+ GLfloat u, v;
+ status_t result = mFlinger->renderScreenToTexture(0, &mTextureName, &u, &v);
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, mTextureName);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ mTexCoords[0] = 0; mTexCoords[1] = v;
+ mTexCoords[2] = 0; mTexCoords[3] = 0;
+ mTexCoords[4] = u; mTexCoords[5] = 0;
+ mTexCoords[6] = u; mTexCoords[7] = v;
+
+ return NO_ERROR;
+}
+
+void LayerScreenshot::onDraw(const Region& clip) const
+{
+ const State& s(drawingState());
+ Region::const_iterator it = clip.begin();
+ Region::const_iterator const end = clip.end();
+ if (s.alpha>0 && (it != end)) {
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ const GLfloat alpha = s.alpha/255.0f;
+ const uint32_t fbHeight = hw.getHeight();
+
+ if (s.alpha == 0xFF) {
+ glDisable(GL_BLEND);
+ } else {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ glColor4f(0, 0, 0, alpha);
+
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D, mTextureName);
+ glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
+ glVertexPointer(2, GL_FLOAT, 0, mVertices);
+
+ while (it != end) {
+ const Rect& r = *it++;
+ const GLint sy = fbHeight - (r.top + r.height());
+ glScissor(r.left, sy, r.width(), r.height());
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+
+ glDisable(GL_BLEND);
+ glDisable(GL_TEXTURE_2D);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/surfaceflinger/LayerScreenshot.h b/services/surfaceflinger/LayerScreenshot.h
new file mode 100644
index 0000000..e3a2b19
--- /dev/null
+++ b/services/surfaceflinger/LayerScreenshot.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ANDROID_LAYER_SCREENSHOT_H
+#define ANDROID_LAYER_SCREENSHOT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "LayerBase.h"
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class LayerScreenshot : public LayerBaseClient
+{
+ GLuint mTextureName;
+ GLfloat mTexCoords[8];
+ sp<SurfaceFlinger> mFlinger;
+public:
+ LayerScreenshot(SurfaceFlinger* flinger, DisplayID display,
+ const sp<Client>& client);
+ virtual ~LayerScreenshot();
+
+ status_t capture();
+
+ virtual void onDraw(const Region& clip) const;
+ virtual bool isOpaque() const { return false; }
+ virtual bool isSecure() const { return false; }
+ virtual bool isProtectedByApp() const { return false; }
+ virtual bool isProtectedByDRM() const { return false; }
+ virtual const char* getTypeId() const { return "LayerScreenshot"; }
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_SCREENSHOT_H
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 595ec1e..ad1995d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -50,6 +50,7 @@
#include "DdmConnection.h"
#include "Layer.h"
#include "LayerDim.h"
+#include "LayerScreenshot.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
@@ -1358,6 +1359,9 @@
case eFXSurfaceDim:
layer = createDimSurface(client, d, w, h, flags);
break;
+ case eFXSurfaceScreenshot:
+ layer = createScreenshotSurface(client, d, w, h, flags);
+ break;
}
if (layer != 0) {
@@ -1420,7 +1424,19 @@
uint32_t w, uint32_t h, uint32_t flags)
{
sp<LayerDim> layer = new LayerDim(this, display, client);
- layer->initStates(w, h, flags);
+ return layer;
+}
+
+sp<LayerScreenshot> SurfaceFlinger::createScreenshotSurface(
+ const sp<Client>& client, DisplayID display,
+ uint32_t w, uint32_t h, uint32_t flags)
+{
+ sp<LayerScreenshot> layer = new LayerScreenshot(this, display, client);
+ status_t err = layer->capture();
+ if (err != NO_ERROR) {
+ layer.clear();
+ LOGW("createScreenshotSurface failed (%s)", strerror(-err));
+ }
return layer;
}
@@ -1783,6 +1799,13 @@
// ---------------------------------------------------------------------------
+status_t SurfaceFlinger::renderScreenToTexture(DisplayID dpy,
+ GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
+{
+ Mutex::Autolock _l(mStateLock);
+ return renderScreenToTextureLocked(dpy, textureName, uOut, vOut);
+}
+
status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
{
@@ -1833,6 +1856,8 @@
layer->drawForSreenShot();
}
+ hw.compositionComplete();
+
// back to main framebuffer
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glDisable(GL_SCISSOR_TEST);
@@ -1848,11 +1873,6 @@
status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
{
- status_t result = PERMISSION_DENIED;
-
- if (!GLExtensions::getInstance().haveFramebufferObject())
- return INVALID_OPERATION;
-
// get screen geometry
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t hw_w = hw.getWidth();
@@ -1861,7 +1881,7 @@
GLfloat u, v;
GLuint tname;
- result = renderScreenToTextureLocked(0, &tname, &u, &v);
+ status_t result = renderScreenToTextureLocked(0, &tname, &u, &v);
if (result != NO_ERROR) {
return result;
}
@@ -2038,10 +2058,6 @@
return result;
}
- // back to main framebuffer
- glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
- glDisable(GL_SCISSOR_TEST);
-
GLfloat vtx[8];
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
glBindTexture(GL_TEXTURE_2D, tname);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0e642c1..3c8f4e5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -49,6 +49,7 @@
class FreezeLock;
class Layer;
class LayerDim;
+class LayerScreenshot;
struct surface_flinger_cblk_t;
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
@@ -186,6 +187,15 @@
void screenReleased(DisplayID dpy);
void screenAcquired(DisplayID dpy);
+ status_t renderScreenToTexture(DisplayID dpy,
+ GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
+
+ status_t postMessageAsync(const sp<MessageBase>& msg,
+ nsecs_t reltime=0, uint32_t flags = 0);
+
+ status_t postMessageSync(const sp<MessageBase>& msg,
+ nsecs_t reltime=0, uint32_t flags = 0);
+
status_t removeLayer(const sp<LayerBase>& layer);
status_t addLayer(const sp<LayerBase>& layer);
status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
@@ -195,6 +205,18 @@
GLuint getProtectedTexName() const { return mProtectedTexName; }
+
+ class MessageDestroyGLTexture : public MessageBase {
+ GLuint texture;
+ public:
+ MessageDestroyGLTexture(GLuint texture) : texture(texture) { }
+ virtual bool handler() {
+ glDeleteTextures(1, &texture);
+ return true;
+ }
+ };
+
+
private:
// DeathRecipient interface
virtual void binderDied(const wp<IBinder>& who);
@@ -204,7 +226,6 @@
friend class LayerBase;
friend class LayerBaseClient;
friend class Layer;
- friend class LayerDim;
sp<ISurface> createSurface(
ISurfaceComposerClient::surface_data_t* params,
@@ -222,6 +243,10 @@
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags);
+ sp<LayerScreenshot> createScreenshotSurface(
+ const sp<Client>& client, DisplayID display,
+ uint32_t w, uint32_t h, uint32_t flags);
+
status_t removeSurface(const sp<Client>& client, SurfaceID sid);
status_t destroySurface(const wp<LayerBaseClient>& layer);
uint32_t setClientStateLocked(const sp<Client>& client, const layer_state_t& s);
@@ -329,12 +354,6 @@
mutable MessageQueue mEventQueue;
- status_t postMessageAsync(const sp<MessageBase>& msg,
- nsecs_t reltime=0, uint32_t flags = 0);
-
- status_t postMessageSync(const sp<MessageBase>& msg,
- nsecs_t reltime=0, uint32_t flags = 0);
-
// access must be protected by mStateLock
mutable Mutex mStateLock;
State mCurrentState;