summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml28
-rw-r--r--core/java/android/app/ActivityThread.java9
-rw-r--r--core/java/android/widget/RemoteViews.java106
-rw-r--r--core/java/com/android/internal/os/SamplingProfilerIntegration.java56
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--data/keyboards/Generic.kcm12
-rw-r--r--include/media/stagefright/DataSource.h2
-rw-r--r--media/libstagefright/AwesomePlayer.cpp40
-rw-r--r--media/libstagefright/DataSource.cpp4
-rw-r--r--media/libstagefright/NuCachedSource2.cpp4
-rw-r--r--media/libstagefright/NuHTTPDataSource.cpp14
-rw-r--r--media/libstagefright/WAVExtractor.cpp5
-rw-r--r--media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp11
-rw-r--r--media/libstagefright/chromium_http/support.cpp6
-rw-r--r--media/libstagefright/include/ChromiumHTTPDataSource.h8
-rw-r--r--media/libstagefright/include/NuCachedSource2.h3
-rw-r--r--media/libstagefright/include/NuHTTPDataSource.h4
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java8
-rw-r--r--policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java110
-rw-r--r--services/java/com/android/server/LightsService.java3
20 files changed, 339 insertions, 96 deletions
diff --git a/api/current.xml b/api/current.xml
index ded1d1b..58aa1fd 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -15703,6 +15703,17 @@
visibility="public"
>
</field>
+<field name="Theme_Holo_Light_NoActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974064"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="Theme_Holo_Light_Panel"
type="int"
transient="false"
@@ -259887,7 +259898,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<parameter name="appWidgetId" type="int">
@@ -259897,6 +259908,21 @@
<parameter name="intent" type="android.content.Intent">
</parameter>
</method>
+<method name="setRemoteAdapter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
<method name="setScrollPosition"
return="void"
abstract="false"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3e5b21f..cb07135 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -916,7 +916,7 @@ public final class ActivityThread {
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
- public static final int DESTROY_ACTIVITY = 109;
+ public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int NEW_INTENT = 112;
@@ -1130,8 +1130,8 @@ public final class ActivityThread {
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
}
- void maybeSnapshot() {
- if (mBoundApplication != null) {
+ private void maybeSnapshot() {
+ if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) {
// convert the *private* ActivityThread.PackageInfo to *public* known
// android.content.pm.PackageInfo
String packageName = mBoundApplication.info.mPackageName;
@@ -3396,8 +3396,7 @@ public final class ActivityThread {
}
final void handleLowMemory() {
- ArrayList<ComponentCallbacks> callbacks
- = new ArrayList<ComponentCallbacks>();
+ ArrayList<ComponentCallbacks> callbacks;
synchronized (mPackages) {
callbacks = collectComponentCallbacksLocked(true, null);
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index c854fac..9cf2718 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -125,7 +125,7 @@ public class RemoteViews implements Parcelable, Filter {
* SUBCLASSES MUST BE IMMUTABLE SO CLONE WORKS!!!!!
*/
private abstract static class Action implements Parcelable {
- public abstract void apply(View root) throws ActionException;
+ public abstract void apply(View root, ViewGroup rootParent) throws ActionException;
public int describeContents() {
return 0;
@@ -183,7 +183,7 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
- public void apply(View root) {
+ public void apply(View root, ViewGroup rootParent) {
final View view = root.findViewById(viewId);
if (!(view instanceof AdapterView<?>)) return;
@@ -214,7 +214,7 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
- public void apply(View root) {
+ public void apply(View root, ViewGroup rootParent) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -295,7 +295,7 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
- public void apply(View root) {
+ public void apply(View root, ViewGroup rootParent) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -360,6 +360,60 @@ public class RemoteViews implements Parcelable, Filter {
public final static int TAG = 8;
}
+ private class SetRemoteViewsAdapterIntent extends Action {
+ public SetRemoteViewsAdapterIntent(int id, Intent intent) {
+ this.viewId = id;
+ this.intent = intent;
+ }
+
+ public SetRemoteViewsAdapterIntent(Parcel parcel) {
+ viewId = parcel.readInt();
+ intent = Intent.CREATOR.createFromParcel(parcel);
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(TAG);
+ dest.writeInt(viewId);
+ intent.writeToParcel(dest, flags);
+ }
+
+ @Override
+ public void apply(View root, ViewGroup rootParent) {
+ final View target = root.findViewById(viewId);
+ if (target == null) return;
+
+ // Ensure that we are applying to an AppWidget root
+ if (!(rootParent instanceof AppWidgetHostView)) {
+ Log.e("RemoteViews", "SetRemoteViewsAdapterIntent action can only be used for " +
+ "AppWidgets (root id: " + viewId + ")");
+ return;
+ }
+ // Ensure that we are calling setRemoteAdapter on an AdapterView that supports it
+ if (!(target instanceof AbsListView) && !(target instanceof AdapterViewAnimator)) {
+ Log.e("RemoteViews", "Cannot setRemoteViewsAdapter on a view which is not " +
+ "an AbsListView or AdapterViewAnimator (id: " + viewId + ")");
+ return;
+ }
+
+ // Embed the AppWidget Id for use in RemoteViewsAdapter when connecting to the intent
+ // RemoteViewsService
+ AppWidgetHostView host = (AppWidgetHostView) rootParent;
+ intent.putExtra(EXTRA_REMOTEADAPTER_APPWIDGET_ID, host.getAppWidgetId());
+ if (target instanceof AbsListView) {
+ AbsListView v = (AbsListView) target;
+ v.setRemoteViewsAdapter(intent);
+ } else if (target instanceof AdapterViewAnimator) {
+ AdapterViewAnimator v = (AdapterViewAnimator) target;
+ v.setRemoteViewsAdapter(intent);
+ }
+ }
+
+ int viewId;
+ Intent intent;
+
+ public final static int TAG = 10;
+ }
+
/**
* Equivalent to calling
* {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
@@ -383,7 +437,7 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
- public void apply(View root) {
+ public void apply(View root, ViewGroup rootParent) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -479,7 +533,7 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
- public void apply(View root) {
+ public void apply(View root, ViewGroup rootParent) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -539,7 +593,7 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
- public void apply(View root) {
+ public void apply(View root, ViewGroup rootParent) {
final View view = root.findViewById(viewId);
if (view == null) return;
@@ -755,7 +809,7 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
- public void apply(View root) {
+ public void apply(View root, ViewGroup rootParent) {
final View view = root.findViewById(viewId);
if (view == null) return;
@@ -850,7 +904,7 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
- public void apply(View root) {
+ public void apply(View root, ViewGroup rootParent) {
final Context context = root.getContext();
final ViewGroup target = (ViewGroup) root.findViewById(viewId);
if (target == null) return;
@@ -952,6 +1006,9 @@ public class RemoteViews implements Parcelable, Filter {
case SetOnClickFillInIntent.TAG:
mActions.add(new SetOnClickFillInIntent(parcel));
break;
+ case SetRemoteViewsAdapterIntent.TAG:
+ mActions.add(new SetRemoteViewsAdapterIntent(parcel));
+ break;
default:
throw new ActionException("Tag " + tag + " not found");
}
@@ -1287,16 +1344,29 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}.
*
- * @param appWidgetId The id of the app widget which contains the specified view
+ * @param appWidgetId The id of the app widget which contains the specified view. (This
+ * parameter is ignored in this deprecated method)
* @param viewId The id of the view whose text should change
* @param intent The intent of the service which will be
* providing data to the RemoteViewsAdapter
+ * @deprecated This method has been deprecated. See
+ * {@link android.widget.RemoteViews#setRemoteAdapter(int, Intent)}
*/
+ @Deprecated
public void setRemoteAdapter(int appWidgetId, int viewId, Intent intent) {
- // Embed the AppWidget Id for use in RemoteViewsAdapter when connecting to the intent
- // RemoteViewsService
- intent.putExtra(EXTRA_REMOTEADAPTER_APPWIDGET_ID, appWidgetId);
- setIntent(viewId, "setRemoteViewsAdapter", intent);
+ setRemoteAdapter(viewId, intent);
+ }
+
+ /**
+ * Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}.
+ * Can only be used for App Widgets.
+ *
+ * @param viewId The id of the view whose text should change
+ * @param intent The intent of the service which will be
+ * providing data to the RemoteViewsAdapter
+ */
+ public void setRemoteAdapter(int viewId, Intent intent) {
+ addAction(new SetRemoteViewsAdapterIntent(viewId, intent));
}
/**
@@ -1499,7 +1569,7 @@ public class RemoteViews implements Parcelable, Filter {
result = inflater.inflate(mLayoutId, parent, false);
- performApply(result);
+ performApply(result, parent);
return result;
}
@@ -1514,15 +1584,15 @@ public class RemoteViews implements Parcelable, Filter {
*/
public void reapply(Context context, View v) {
prepareContext(context);
- performApply(v);
+ performApply(v, (ViewGroup) v.getParent());
}
- private void performApply(View v) {
+ private void performApply(View v, ViewGroup parent) {
if (mActions != null) {
final int count = mActions.size();
for (int i = 0; i < count; i++) {
Action a = mActions.get(i);
- a.apply(v);
+ a.apply(v, parent);
}
}
}
diff --git a/core/java/com/android/internal/os/SamplingProfilerIntegration.java b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
index 268a9d4..df0fcd9 100644
--- a/core/java/com/android/internal/os/SamplingProfilerIntegration.java
+++ b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
@@ -20,13 +20,15 @@ import android.content.pm.PackageInfo;
import android.os.Build;
import android.os.SystemProperties;
import android.util.Log;
-import dalvik.system.profiler.AsciiHprofWriter;
+import dalvik.system.profiler.BinaryHprofWriter;
import dalvik.system.profiler.SamplingProfiler;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.PrintStream;
+import java.util.Date;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
@@ -81,7 +83,8 @@ public class SamplingProfilerIntegration {
}
}
- private static SamplingProfiler INSTANCE;
+ private static SamplingProfiler samplingProfiler;
+ private static long startMillis;
/**
* Is profiling enabled?
@@ -97,10 +100,16 @@ public class SamplingProfilerIntegration {
if (!enabled) {
return;
}
+ if (samplingProfiler != null) {
+ Log.e(TAG, "SamplingProfilerIntegration already started at " + new Date(startMillis));
+ return;
+ }
+
ThreadGroup group = Thread.currentThread().getThreadGroup();
SamplingProfiler.ThreadSet threadSet = SamplingProfiler.newThreadGroupTheadSet(group);
- INSTANCE = new SamplingProfiler(samplingProfilerDepth, threadSet);
- INSTANCE.start(samplingProfilerMilliseconds);
+ samplingProfiler = new SamplingProfiler(samplingProfilerDepth, threadSet);
+ samplingProfiler.start(samplingProfilerMilliseconds);
+ startMillis = System.currentTimeMillis();
}
/**
@@ -110,6 +119,10 @@ public class SamplingProfilerIntegration {
if (!enabled) {
return;
}
+ if (samplingProfiler == null) {
+ Log.e(TAG, "SamplingProfilerIntegration is not started");
+ return;
+ }
/*
* If we're already writing a snapshot, don't bother enqueueing another
@@ -138,8 +151,9 @@ public class SamplingProfilerIntegration {
return;
}
writeSnapshotFile("zygote", null);
- INSTANCE.shutdown();
- INSTANCE = null;
+ samplingProfiler.shutdown();
+ samplingProfiler = null;
+ startMillis = 0;
}
/**
@@ -149,40 +163,44 @@ public class SamplingProfilerIntegration {
if (!enabled) {
return;
}
- INSTANCE.stop();
+ samplingProfiler.stop();
/*
- * We use the current time as a unique ID. We can't use a counter
- * because processes restart. This could result in some overlap if
- * we capture two snapshots in rapid succession.
+ * We use the global start time combined with the process name
+ * as a unique ID. We can't use a counter because processes
+ * restart. This could result in some overlap if we capture
+ * two snapshots in rapid succession.
*/
- long start = System.currentTimeMillis();
String name = processName.replaceAll(":", ".");
- String path = SNAPSHOT_DIR + "/" + name + "-" +System.currentTimeMillis() + ".snapshot";
- PrintStream out = null;
+ String path = SNAPSHOT_DIR + "/" + name + "-" + startMillis + ".snapshot";
+ long start = System.currentTimeMillis();
+ OutputStream outputStream = null;
try {
- out = new PrintStream(new BufferedOutputStream(new FileOutputStream(path)));
+ outputStream = new BufferedOutputStream(new FileOutputStream(path));
+ PrintStream out = new PrintStream(outputStream);
generateSnapshotHeader(name, packageInfo, out);
- new AsciiHprofWriter(INSTANCE.getHprofData(), out).write();
if (out.checkError()) {
throw new IOException();
}
+ BinaryHprofWriter.write(samplingProfiler.getHprofData(), outputStream);
} catch (IOException e) {
Log.e(TAG, "Error writing snapshot to " + path, e);
return;
} finally {
- IoUtils.closeQuietly(out);
+ IoUtils.closeQuietly(outputStream);
}
// set file readable to the world so that SamplingProfilerService
// can put it to dropbox
new File(path).setReadable(true, false);
long elapsed = System.currentTimeMillis() - start;
- Log.i(TAG, "Wrote snapshot for " + name + " in " + elapsed + "ms.");
+ Log.i(TAG, "Wrote snapshot " + path + " in " + elapsed + "ms.");
+ samplingProfiler.start(samplingProfilerMilliseconds);
}
/**
- * generate header for snapshots, with the following format (like http header):
+ * generate header for snapshots, with the following format
+ * (like an HTTP header but without the \r):
*
* Version: <version number of profiler>\n
* Process: <process name>\n
@@ -195,7 +213,7 @@ public class SamplingProfilerIntegration {
private static void generateSnapshotHeader(String processName, PackageInfo packageInfo,
PrintStream out) {
// profiler version
- out.println("Version: 2");
+ out.println("Version: 3");
out.println("Process: " + processName);
if (packageInfo != null) {
out.println("Package: " + packageInfo.packageName);
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0fefbf2..4109ae1 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1657,4 +1657,6 @@
<public type="attr" name="state_drag_can_accept" />
<public type="attr" name="state_drag_hovered" />
+ <public type="style" name="Theme.Holo.Light.NoActionBar" />
+
</resources>
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 51a8b27..ef0a4e6 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -287,8 +287,8 @@ key 9 {
key SPACE {
label: ' '
base: ' '
- ctrl, alt: none
- meta: fallback SEARCH
+ ctrl: none
+ alt, meta: fallback SEARCH
}
key ENTER {
@@ -300,8 +300,8 @@ key ENTER {
key TAB {
label: '\t'
base: '\t'
- ctrl, alt: none
- meta: fallback APP_SWITCH
+ ctrl: none
+ alt, meta: fallback APP_SWITCH
}
key COMMA {
@@ -542,8 +542,8 @@ key PLUS {
key ESCAPE {
base: fallback BACK
- meta: fallback HOME
- alt: fallback MENU
+ alt, meta: fallback HOME
+ ctrl: fallback MENU
}
### Gamepad buttons ###
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index d30e908..6b6fcdf 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -84,6 +84,8 @@ public:
return String8();
}
+ virtual String8 getMIMEType() const;
+
protected:
virtual ~DataSource() {}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 7940de0..759bd86 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1693,29 +1693,37 @@ status_t AwesomePlayer::finishSetDataSource_l() {
dataSource = mCachedSource;
- // We're going to prefill the cache before trying to instantiate
- // the extractor below, as the latter is an operation that otherwise
- // could block on the datasource for a significant amount of time.
- // During that time we'd be unable to abort the preparation phase
- // without this prefill.
+ String8 contentType = dataSource->getMIMEType();
- mLock.unlock();
+ if (strncasecmp(contentType.string(), "audio/", 6)) {
+ // We're not doing this for streams that appear to be audio-only
+ // streams to ensure that even low bandwidth streams start
+ // playing back fairly instantly.
- for (;;) {
- status_t finalStatus;
- size_t cachedDataRemaining =
- mCachedSource->approxDataRemaining(&finalStatus);
+ // We're going to prefill the cache before trying to instantiate
+ // the extractor below, as the latter is an operation that otherwise
+ // could block on the datasource for a significant amount of time.
+ // During that time we'd be unable to abort the preparation phase
+ // without this prefill.
+
+ mLock.unlock();
+
+ for (;;) {
+ status_t finalStatus;
+ size_t cachedDataRemaining =
+ mCachedSource->approxDataRemaining(&finalStatus);
- if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
- || (mFlags & PREPARE_CANCELLED)) {
- break;
+ if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
+ || (mFlags & PREPARE_CANCELLED)) {
+ break;
+ }
+
+ usleep(200000);
}
- usleep(200000);
+ mLock.lock();
}
- mLock.lock();
-
if (mFlags & PREPARE_CANCELLED) {
LOGI("Prepare cancelled while waiting for initial cache fill.");
return UNKNOWN_ERROR;
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index b5c51f4..7c2096e 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -144,4 +144,8 @@ sp<DataSource> DataSource::CreateFromURI(
return source;
}
+String8 DataSource::getMIMEType() const {
+ return String8("application/octet-stream");
+}
+
} // namespace android
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 3c99d1c..c1aa46e 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -493,4 +493,8 @@ String8 NuCachedSource2::getUri() {
return mSource->getUri();
}
+String8 NuCachedSource2::getMIMEType() const {
+ return mSource->getMIMEType();
+}
+
} // namespace android
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 73daf12..5c43a5b 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -136,6 +136,7 @@ status_t NuHTTPDataSource::connect(
unsigned port;
mUri = uri;
+ mContentType = String8("application/octet-stream");
bool https;
if (!ParseURL(uri, &host, &port, &path, &https)) {
@@ -265,6 +266,15 @@ status_t NuHTTPDataSource::connect(
}
}
+ {
+ AString value;
+ if (mHTTP.find_header_value("Content-Type", &value)) {
+ mContentType = String8(value.c_str());
+ } else {
+ mContentType = String8("application/octet-stream");
+ }
+ }
+
applyTimeoutResponse();
if (offset == 0) {
@@ -564,4 +574,8 @@ String8 NuHTTPDataSource::getUri() {
return mUri;
}
+String8 NuHTTPDataSource::getMIMEType() const {
+ return mContentType;
+}
+
} // namespace android
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index e9e5ef9..76f47f7 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -425,6 +425,11 @@ bool SniffWAV(
return false;
}
+ sp<MediaExtractor> extractor = new WAVExtractor(source);
+ if (extractor->countTracks() == 0) {
+ return false;
+ }
+
*mimeType = MEDIA_MIMETYPE_CONTAINER_WAV;
*confidence = 0.3f;
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
index 949a5e4..1096717 100644
--- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -79,6 +79,7 @@ status_t ChromiumHTTPDataSource::connect_l(
}
mURI = uri;
+ mContentType = String8("application/octet-stream");
if (headers != NULL) {
mHeaders = *headers;
@@ -99,10 +100,12 @@ status_t ChromiumHTTPDataSource::connect_l(
return mState == CONNECTED ? OK : mIOResult;
}
-void ChromiumHTTPDataSource::onConnectionEstablished(int64_t contentSize) {
+void ChromiumHTTPDataSource::onConnectionEstablished(
+ int64_t contentSize, const char *contentType) {
Mutex::Autolock autoLock(mLock);
mState = CONNECTED;
mContentSize = (contentSize < 0) ? -1 : contentSize + mCurrentOffset;
+ mContentType = String8(contentType);
mCondition.broadcast();
}
@@ -314,6 +317,12 @@ String8 ChromiumHTTPDataSource::getUri() {
return String8(mURI.c_str());
}
+String8 ChromiumHTTPDataSource::getMIMEType() const {
+ Mutex::Autolock autoLock(mLock);
+
+ return mContentType;
+}
+
void ChromiumHTTPDataSource::clearDRMState_l() {
if (mDecryptHandle != NULL) {
// To release mDecryptHandle
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index 7ac56e8..af2f6ac 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -253,7 +253,11 @@ void SfDelegate::OnResponseStarted(URLRequest *request) {
MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str());
- mOwner->onConnectionEstablished(request->GetExpectedContentSize());
+ std::string contentType;
+ request->GetResponseHeaderByName("Content-Type", &contentType);
+
+ mOwner->onConnectionEstablished(
+ request->GetExpectedContentSize(), contentType.c_str());
}
void SfDelegate::OnReadCompleted(URLRequest *request, int bytes_read) {
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
index af49059..0e2927d 100644
--- a/media/libstagefright/include/ChromiumHTTPDataSource.h
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -51,6 +51,8 @@ struct ChromiumHTTPDataSource : public HTTPBase {
virtual String8 getUri();
+ virtual String8 getMIMEType() const;
+
protected:
virtual ~ChromiumHTTPDataSource();
@@ -90,6 +92,8 @@ private:
int64_t mContentSize;
+ String8 mContentType;
+
List<BandwidthEntry> mBandwidthHistory;
size_t mNumBandwidthHistoryItems;
int64_t mTotalTransferTimeUs;
@@ -110,7 +114,9 @@ private:
void initiateRead(void *data, size_t size);
- void onConnectionEstablished(int64_t contentSize);
+ void onConnectionEstablished(
+ int64_t contentSize, const char *contentType);
+
void onConnectionFailed(status_t err);
void onReadCompleted(ssize_t size);
void onDisconnectComplete();
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 02d5817..2128682 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -40,6 +40,9 @@ struct NuCachedSource2 : public DataSource {
virtual sp<DecryptHandle> DrmInitialization();
virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
virtual String8 getUri();
+
+ virtual String8 getMIMEType() const;
+
////////////////////////////////////////////////////////////////////////////
size_t cachedSize();
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
index 7dd5d59..2ab1f19 100644
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -51,6 +51,8 @@ struct NuHTTPDataSource : public HTTPBase {
virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
virtual String8 getUri();
+ virtual String8 getMIMEType() const;
+
protected:
virtual ~NuHTTPDataSource();
@@ -85,6 +87,8 @@ private:
bool mContentLengthValid;
bool mHasChunkedTransferEncoding;
+ String8 mContentType;
+
// The number of data bytes in the current chunk before any subsequent
// chunk header (or -1 if no more chunks).
ssize_t mChunkDataBytesLeft;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 4fa5bcb..44f55b3 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -626,7 +626,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
- showRecentAppsDialog();
+ showRecentAppsDialog(0);
} else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_ACTIVITY) {
try {
Intent intent = new Intent();
@@ -645,12 +645,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/**
* Create (if necessary) and launch the recent apps dialog
*/
- void showRecentAppsDialog() {
+ void showRecentAppsDialog(final int initialModifiers) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mRecentAppsDialog == null) {
- mRecentAppsDialog = new RecentApplicationsDialog(mContext);
+ mRecentAppsDialog = new RecentApplicationsDialog(mContext, initialModifiers);
}
mRecentAppsDialog.show();
}
@@ -1392,7 +1392,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return false;
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
if (down && repeatCount == 0) {
- showRecentAppsDialog();
+ showRecentAppsDialog(event.getMetaState() & KeyEvent.getModifierMetaStateMask());
}
return true;
}
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
index db66346..c4b7822 100644
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
@@ -17,16 +17,13 @@
package com.android.internal.policy.impl;
import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
import android.app.Dialog;
-import android.app.IActivityManager;
import android.app.StatusBarManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -34,6 +31,8 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
+import android.view.KeyEvent;
+import android.view.SoundEffectConstants;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@@ -72,13 +71,12 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener
}
};
- private int mIconSize;
+ private int mInitialModifiers;
- public RecentApplicationsDialog(Context context) {
+ public RecentApplicationsDialog(Context context, int initialModifiers) {
super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
- final Resources resources = context.getResources();
- mIconSize = (int) resources.getDimension(android.R.dimen.app_icon_size);
+ mInitialModifiers = initialModifiers;
}
/**
@@ -127,34 +125,102 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener
}
}
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_APP_SWITCH || keyCode == KeyEvent.KEYCODE_TAB) {
+ // Ignore all meta keys other than SHIFT. The app switch key could be a
+ // fallback action chorded with ALT, META or even CTRL depending on the key map.
+ // DPad navigation is handled by the ViewRoot elsewhere.
+ final boolean backward = event.isShiftPressed();
+ final int numIcons = mIcons.length;
+ int numButtons = 0;
+ while (numButtons < numIcons && mIcons[numButtons].getVisibility() == View.VISIBLE) {
+ numButtons += 1;
+ }
+ if (numButtons != 0) {
+ int nextFocus = backward ? numButtons - 1 : 0;
+ for (int i = 0; i < numButtons; i++) {
+ if (mIcons[i].hasFocus()) {
+ if (backward) {
+ nextFocus = (i + numButtons - 1) % numButtons;
+ } else {
+ nextFocus = (i + 1) % numButtons;
+ }
+ break;
+ }
+ }
+ final int direction = backward ? View.FOCUS_BACKWARD : View.FOCUS_FORWARD;
+ if (mIcons[nextFocus].requestFocus(direction)) {
+ mIcons[nextFocus].playSoundEffect(
+ SoundEffectConstants.getContantForFocusDirection(direction));
+ }
+ }
+
+ // The dialog always handles the key to prevent the ViewRoot from
+ // performing the default navigation itself.
+ return true;
+ }
+
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (mInitialModifiers != 0 && event.hasNoModifiers()) {
+ final int numIcons = mIcons.length;
+ RecentTag tag = null;
+ for (int i = 0; i < numIcons; i++) {
+ if (mIcons[i].getVisibility() != View.VISIBLE) {
+ break;
+ }
+ if (i == 0 || mIcons[i].hasFocus()) {
+ tag = (RecentTag) mIcons[i].getTag();
+ if (mIcons[i].hasFocus()) {
+ break;
+ }
+ }
+ }
+ if (tag != null) {
+ switchTo(tag);
+ }
+ dismiss();
+ return true;
+ }
+
+ return super.onKeyUp(keyCode, event);
+ }
+
/**
* Handler for user clicks. If a button was clicked, launch the corresponding activity.
*/
public void onClick(View v) {
-
for (TextView b: mIcons) {
if (b == v) {
RecentTag tag = (RecentTag)b.getTag();
- if (tag.info.id >= 0) {
- // This is an active task; it should just go to the foreground.
- final ActivityManager am = (ActivityManager)
- getContext().getSystemService(Context.ACTIVITY_SERVICE);
- am.moveTaskToFront(tag.info.id, ActivityManager.MOVE_TASK_WITH_HOME);
- } else if (tag.intent != null) {
- tag.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
- | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
- try {
- getContext().startActivity(tag.intent);
- } catch (ActivityNotFoundException e) {
- Log.w("Recent", "Unable to launch recent task", e);
- }
- }
+ switchTo(tag);
break;
}
}
dismiss();
}
+ private void switchTo(RecentTag tag) {
+ if (tag.info.id >= 0) {
+ // This is an active task; it should just go to the foreground.
+ final ActivityManager am = (ActivityManager)
+ getContext().getSystemService(Context.ACTIVITY_SERVICE);
+ am.moveTaskToFront(tag.info.id, ActivityManager.MOVE_TASK_WITH_HOME);
+ } else if (tag.intent != null) {
+ tag.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
+ | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+ try {
+ getContext().startActivity(tag.intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w("Recent", "Unable to launch recent task", e);
+ }
+ }
+ }
+
/**
* Set up and show the recent activities dialog.
*/
diff --git a/services/java/com/android/server/LightsService.java b/services/java/com/android/server/LightsService.java
index 21f2bcf..1e95f3e 100644
--- a/services/java/com/android/server/LightsService.java
+++ b/services/java/com/android/server/LightsService.java
@@ -148,7 +148,6 @@ public class LightsService {
fis.close();
return (result != '0');
} catch (Exception e) {
- Slog.e(TAG, "getFlashlightEnabled failed", e);
return false;
}
}
@@ -168,7 +167,7 @@ public class LightsService {
fos.write(bytes);
fos.close();
} catch (Exception e) {
- Slog.e(TAG, "setFlashlightEnabled failed", e);
+ // fail silently
}
}
};